зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1341191
- Fix messaging priv escalation of feed reader, simplify messaging from parent to child. Reduce race conditions on page. r=Gijs
This commit is contained in:
Родитель
863a41136f
Коммит
49113725c4
|
@ -3,11 +3,136 @@
|
|||
* 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.
|
||||
|
@ -195,7 +320,8 @@ var FeedHandler = {
|
|||
return file.leafName;
|
||||
},
|
||||
|
||||
chooseClientApp(aTitle, aPrefName, aBrowser) {
|
||||
_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);
|
||||
|
@ -222,7 +348,7 @@ var FeedHandler = {
|
|||
}
|
||||
|
||||
if (fp.file.leafName != appName) {
|
||||
Services.prefs.setComplexValue(aPrefName, Ci.nsILocalFile, selectedApp);
|
||||
Services.prefs.setComplexValue(prefName, Ci.nsILocalFile, selectedApp);
|
||||
aBrowser.messageManager.sendAsyncMessage("FeedWriter:SetApplicationLauncherMenuItem",
|
||||
{ name: this._getFileDisplayName(selectedApp),
|
||||
type: "SelectedAppMenuItem" });
|
||||
|
@ -277,70 +403,243 @@ var FeedHandler = {
|
|||
}
|
||||
},
|
||||
|
||||
// nsISupports
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
|
||||
init() {
|
||||
window.messageManager.addMessageListener("FeedWriter:ChooseClientApp", this);
|
||||
window.messageManager.addMessageListener("FeedWriter:RequestClientAppName", this);
|
||||
window.messageManager.addMessageListener("FeedWriter:SetFeedCharPref", this);
|
||||
window.messageManager.addMessageListener("FeedWriter:SetFeedComplexString", 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) {
|
||||
const supportsString = Cc["@mozilla.org/supports-string;1"].
|
||||
createInstance(Ci.nsISupportsString);
|
||||
supportsString.data = aPrefValue;
|
||||
Services.prefs.setComplexValue(aPrefName, Ci.nsISupportsString, supportsString);
|
||||
} 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.getComplexValue(getPrefWebForType(feedType), Ci.nsISupportsString).data;
|
||||
} 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:ChooseClientApp":
|
||||
this.chooseClientApp(msg.data.title, msg.data.prefName, msg.target);
|
||||
case "FeedWriter:GetSubscriptionUI":
|
||||
const response = this._initSubscriptionUIResponse(msg.data.feedType);
|
||||
msg.target.messageManager
|
||||
.sendAsyncMessage("FeedWriter:GetSubscriptionUIResponse",
|
||||
response);
|
||||
break;
|
||||
case "FeedWriter:RequestClientAppName":
|
||||
let selectedClientApp;
|
||||
try {
|
||||
selectedClientApp = Services.prefs.getComplexValue(msg.data.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
|
||||
msg.target.messageManager
|
||||
.sendAsyncMessage("FeedWriter:SetApplicationLauncherMenuItem",
|
||||
{ name: this._getFileDisplayName(defaultClientApp),
|
||||
type: "DefaultAppMenuItem" });
|
||||
}
|
||||
msg.target.messageManager
|
||||
.sendAsyncMessage("FeedWriter:SetApplicationLauncherMenuItem",
|
||||
{ name: this._getFileDisplayName(selectedClientApp),
|
||||
type: "SelectedAppMenuItem" });
|
||||
}
|
||||
case "FeedWriter:ChooseClientApp":
|
||||
this._chooseClientApp(msg.data.title, msg.data.feedType, msg.target);
|
||||
break;
|
||||
case "FeedWriter:ShownFirstRun":
|
||||
Services.prefs.setBoolPref("browser.feeds.showFirstRunUI", false);
|
||||
Services.prefs.setBoolPref(PREF_SHOW_FIRST_RUN_UI, false);
|
||||
break;
|
||||
case "FeedWriter:SetFeedCharPref":
|
||||
Services.prefs.setCharPref(msg.data.pref, msg.data.value);
|
||||
break;
|
||||
case "FeedWriter:SetFeedComplexString": {
|
||||
Services.prefs.setStringPref(msg.data.pref, msg.data.value);
|
||||
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":
|
||||
this.executeClientApp(msg.data.spec, msg.data.title,
|
||||
msg.data.subtitle, msg.data.feedHandler);
|
||||
// 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;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -223,8 +223,7 @@ FeedConverter.prototype = {
|
|||
try {
|
||||
let title = feed.title ? feed.title.plainText() : "";
|
||||
let desc = feed.subtitle ? feed.subtitle.plainText() : "";
|
||||
let feedReader = safeGetCharPref(getPrefActionForType(feed.type), "bookmarks");
|
||||
feedService.addToClientReader(result.uri.spec, title, desc, feed.type, feedReader);
|
||||
feedService.addToClientReader(result.uri.spec, title, desc, feed.type, handler);
|
||||
return;
|
||||
} catch (ex) { /* fallback to preview mode */ }
|
||||
}
|
||||
|
|
|
@ -44,83 +44,11 @@ function makeURI(aURLSpec, aCharset) {
|
|||
const XML_NS = "http://www.w3.org/XML/1998/namespace";
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
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 URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
|
||||
|
||||
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_SHOW_FIRST_RUN_UI = "browser.feeds.showFirstRunUI";
|
||||
|
||||
const TITLE_ID = "feedTitleText";
|
||||
const SUBTITLE_ID = "feedSubtitleText";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a number of bytes to the appropriate unit that results in a
|
||||
* number that needs fewer than 4 digits
|
||||
|
@ -153,9 +81,6 @@ function FeedWriter() {
|
|||
}
|
||||
|
||||
FeedWriter.prototype = {
|
||||
_mimeSvc : Cc["@mozilla.org/mime;1"].
|
||||
getService(Ci.nsIMIMEService),
|
||||
|
||||
_getPropertyAsBag(container, property) {
|
||||
return container.fields.getProperty(property).
|
||||
QueryInterface(Ci.nsIPropertyBag2);
|
||||
|
@ -226,18 +151,21 @@ FeedWriter.prototype = {
|
|||
return this._bundle.GetStringFromName(key);
|
||||
},
|
||||
|
||||
_setCheckboxCheckedState(aCheckbox, aValue) {
|
||||
// see checkbox.xml, xbl bindings are not applied within the sandbox! TODO
|
||||
let change = (aValue != (aCheckbox.getAttribute("checked") == "true"));
|
||||
if (aValue)
|
||||
aCheckbox.setAttribute("checked", "true");
|
||||
else
|
||||
aCheckbox.removeAttribute("checked");
|
||||
_setCheckboxCheckedState(aValue) {
|
||||
let checkbox = this._document.getElementById("alwaysUse");
|
||||
if (checkbox) {
|
||||
// see checkbox.xml, xbl bindings are not applied within the sandbox! TODO
|
||||
let change = (aValue != (checkbox.getAttribute("checked") == "true"));
|
||||
if (aValue)
|
||||
checkbox.setAttribute("checked", "true");
|
||||
else
|
||||
checkbox.removeAttribute("checked");
|
||||
|
||||
if (change) {
|
||||
let event = this._document.createEvent("Events");
|
||||
event.initEvent("CheckboxStateChange", true, true);
|
||||
aCheckbox.dispatchEvent(event);
|
||||
if (change) {
|
||||
let event = this._document.createEvent("Events");
|
||||
event.initEvent("CheckboxStateChange", true, true);
|
||||
checkbox.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -290,22 +218,6 @@ FeedWriter.prototype = {
|
|||
return Ci.nsIFeed.TYPE_FEED;
|
||||
},
|
||||
|
||||
/**
|
||||
* Maps a feed type to a maybe-feed mimetype.
|
||||
*/
|
||||
_getMimeTypeForFeedType() {
|
||||
switch (this._getFeedType()) {
|
||||
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;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Writes the feed title into the preview document.
|
||||
* @param container
|
||||
|
@ -491,17 +403,11 @@ FeedWriter.prototype = {
|
|||
|
||||
if (enc.hasKey("type")) {
|
||||
type_text = enc.get("type");
|
||||
try {
|
||||
let handlerInfoWrapper = this._mimeSvc.getFromTypeAndExtension(enc.get("type"), null);
|
||||
|
||||
if (handlerInfoWrapper)
|
||||
type_text = handlerInfoWrapper.description;
|
||||
|
||||
if (type_text && type_text.length > 0)
|
||||
mozicon = "moz-icon://goat?size=16&contentType=" + enc.get("type");
|
||||
|
||||
} catch (ex) { }
|
||||
if (enc.hasKey("typeDesc"))
|
||||
type_text = enc.get("typeDesc");
|
||||
|
||||
if (type_text && type_text.length > 0)
|
||||
mozicon = "moz-icon://goat?size=16&contentType=" + enc.get("type");
|
||||
}
|
||||
|
||||
if (enc.hasKey("length") && /^[0-9]+$/.test(enc.get("length"))) {
|
||||
|
@ -596,19 +502,7 @@ FeedWriter.prototype = {
|
|||
this._subscribeCallback = aCallback;
|
||||
this._mm.sendAsyncMessage("FeedWriter:ChooseClientApp",
|
||||
{ title: this._getString("chooseApplicationDialogTitle"),
|
||||
prefName: getPrefAppForType(this._getFeedType()) });
|
||||
},
|
||||
|
||||
_setAlwaysUseCheckedState(feedType) {
|
||||
let checkbox = this._document.getElementById("alwaysUse");
|
||||
if (checkbox) {
|
||||
let alwaysUse = false;
|
||||
try {
|
||||
if (Services.prefs.getCharPref(getPrefActionForType(feedType)) != "ask")
|
||||
alwaysUse = true;
|
||||
} catch (ex) { }
|
||||
this._setCheckboxCheckedState(checkbox, alwaysUse);
|
||||
}
|
||||
feedType: this._getFeedType() });
|
||||
},
|
||||
|
||||
_setSubscribeUsingLabel() {
|
||||
|
@ -671,13 +565,13 @@ FeedWriter.prototype = {
|
|||
}
|
||||
break;
|
||||
case "change":
|
||||
LOG("Change fired");
|
||||
if (event.target.selectedOptions[0].id == "chooseApplicationMenuItem") {
|
||||
this._chooseClientApp((aResult) => {
|
||||
if (!aResult) {
|
||||
// Select the (per-prefs) selected handler if no application
|
||||
// was selected
|
||||
this._setSelectedHandler(this._getFeedType());
|
||||
}
|
||||
this._chooseClientApp(() => {
|
||||
// Select the (per-prefs) selected handler if no application
|
||||
// was selected
|
||||
LOG("Selected handler after callback");
|
||||
this._setAlwaysUseLabel();
|
||||
});
|
||||
} else {
|
||||
this._setAlwaysUseLabel();
|
||||
|
@ -687,28 +581,18 @@ FeedWriter.prototype = {
|
|||
},
|
||||
|
||||
_getWebHandlerElementsForURL(aURL) {
|
||||
let menu = this._document.getElementById("handlersMenuList");
|
||||
return menu.querySelectorAll('[webhandlerurl="' + aURL + '"]');
|
||||
return this._handlersList.querySelectorAll('[webhandlerurl="' + aURL + '"]');
|
||||
},
|
||||
|
||||
_setSelectedHandler(feedType) {
|
||||
let prefs = Services.prefs;
|
||||
let handler = prefs.getCharPref(getPrefReaderForType(feedType), "bookmarks");
|
||||
|
||||
_setSelectedHandlerResponse(handler, url) {
|
||||
LOG(`Selecting handler response ${handler} ${url}`);
|
||||
switch (handler) {
|
||||
case "web": {
|
||||
if (this._handlersList) {
|
||||
let url;
|
||||
try {
|
||||
url = prefs.getStringPref(getPrefWebForType(feedType));
|
||||
} catch (ex) {
|
||||
LOG("FeedWriter._setSelectedHandler: invalid or no handler in prefs");
|
||||
return;
|
||||
}
|
||||
let handlers =
|
||||
this._getWebHandlerElementsForURL(url);
|
||||
if (handlers.length == 0) {
|
||||
LOG("FeedWriter._setSelectedHandler: selected web handler isn't in the menulist")
|
||||
LOG(`Selected web handler isn't in the menulist ${url}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -729,10 +613,10 @@ FeedWriter.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_initSubscriptionUI() {
|
||||
let handlersList = this._document.getElementById("handlersMenuList");
|
||||
if (!handlersList)
|
||||
_initSubscriptionUI(setupMessage) {
|
||||
if (!this._handlersList)
|
||||
return;
|
||||
LOG("UI init");
|
||||
|
||||
let feedType = this._getFeedType();
|
||||
|
||||
|
@ -763,7 +647,7 @@ FeedWriter.prototype = {
|
|||
menuItem.style.display = "none";
|
||||
this._selectedAppMenuItem = menuItem;
|
||||
|
||||
handlersList.appendChild(this._selectedAppMenuItem);
|
||||
this._handlersList.appendChild(this._selectedAppMenuItem);
|
||||
|
||||
// Create the menuitem for the default reader, but don't show/populate it until
|
||||
// we get confirmation of what it is from the parent
|
||||
|
@ -774,10 +658,7 @@ FeedWriter.prototype = {
|
|||
menuItem.style.display = "none";
|
||||
|
||||
this._defaultHandlerMenuItem = menuItem;
|
||||
handlersList.appendChild(this._defaultHandlerMenuItem);
|
||||
|
||||
this._mm.sendAsyncMessage("FeedWriter:RequestClientAppName",
|
||||
{ feedTypePref: getPrefAppForType(feedType) });
|
||||
this._handlersList.appendChild(this._defaultHandlerMenuItem);
|
||||
|
||||
// "Choose Application..." menuitem
|
||||
menuItem = liveBookmarksMenuItem.cloneNode(false);
|
||||
|
@ -785,18 +666,14 @@ FeedWriter.prototype = {
|
|||
menuItem.setAttribute("id", "chooseApplicationMenuItem");
|
||||
menuItem.textContent = this._getString("chooseApplicationMenuItem");
|
||||
|
||||
handlersList.appendChild(menuItem);
|
||||
this._handlersList.appendChild(menuItem);
|
||||
|
||||
// separator
|
||||
let chooseAppSep = liveBookmarksMenuItem.nextElementSibling.cloneNode(false);
|
||||
chooseAppSep.textContent = liveBookmarksMenuItem.nextElementSibling.textContent;
|
||||
handlersList.appendChild(chooseAppSep);
|
||||
this._handlersList.appendChild(chooseAppSep);
|
||||
|
||||
// List of web handlers
|
||||
let wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
|
||||
getService(Ci.nsIWebContentConverterService);
|
||||
let handlers = wccr.getContentHandlers(this._getMimeTypeForFeedType(feedType));
|
||||
for (let handler of handlers) {
|
||||
for (let handler of setupMessage.handlers) {
|
||||
if (!handler.uri) {
|
||||
LOG("Handler with name " + handler.name + " has no URI!? Skipping...");
|
||||
continue;
|
||||
|
@ -807,29 +684,37 @@ FeedWriter.prototype = {
|
|||
menuItem.textContent = handler.name;
|
||||
menuItem.setAttribute("handlerType", "web");
|
||||
menuItem.setAttribute("webhandlerurl", handler.uri);
|
||||
handlersList.appendChild(menuItem);
|
||||
this._handlersList.appendChild(menuItem);
|
||||
}
|
||||
|
||||
this._setSelectedHandler(feedType);
|
||||
this._setSelectedHandlerResponse(setupMessage.reader.handler, setupMessage.reader.url);
|
||||
|
||||
if (setupMessage.defaultMenuItem) {
|
||||
LOG(`Setting default menu item ${setupMessage.defaultMenuItem}`);
|
||||
this._setApplicationLauncherMenuItem(this._defaultHandlerMenuItem, setupMessage.defaultMenuItem);
|
||||
}
|
||||
if (setupMessage.selectedMenuItem) {
|
||||
LOG(`Setting selected menu item ${setupMessage.selectedMenuItem}`);
|
||||
this._setApplicationLauncherMenuItem(this._selectedAppMenuItem, setupMessage.selectedMenuItem);
|
||||
}
|
||||
|
||||
// "Subscribe using..."
|
||||
this._setSubscribeUsingLabel();
|
||||
|
||||
// "Always use..." checkbox initial state
|
||||
this._setAlwaysUseCheckedState(feedType);
|
||||
this._setCheckboxCheckedState(setupMessage.reader.alwaysUse);
|
||||
this._setAlwaysUseLabel();
|
||||
|
||||
// We update the "Always use.." checkbox label whenever the selected item
|
||||
// in the list is changed
|
||||
handlersList.addEventListener("change", this);
|
||||
this._handlersList.addEventListener("change", this);
|
||||
|
||||
// Set up the "Subscribe Now" button
|
||||
this._document.getElementById("subscribeButton")
|
||||
.addEventListener("click", this);
|
||||
|
||||
// first-run ui
|
||||
let showFirstRunUI = Services.prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI, true);
|
||||
if (showFirstRunUI) {
|
||||
if (setupMessage.showFirstRunUI) {
|
||||
let textfeedinfo1, textfeedinfo2;
|
||||
switch (feedType) {
|
||||
case Ci.nsIFeed.TYPE_VIDEO:
|
||||
|
@ -915,53 +800,74 @@ FeedWriter.prototype = {
|
|||
|
||||
LOG("Subscribe Preview: feed uri = " + this._window.location.href);
|
||||
|
||||
// Set up the subscription UI
|
||||
this._initSubscriptionUI();
|
||||
let prefs = Services.prefs;
|
||||
prefs.addObserver(PREF_SELECTED_ACTION, this, false);
|
||||
prefs.addObserver(PREF_SELECTED_READER, this, false);
|
||||
prefs.addObserver(PREF_SELECTED_WEB, this, false);
|
||||
prefs.addObserver(PREF_SELECTED_APP, this, false);
|
||||
prefs.addObserver(PREF_VIDEO_SELECTED_ACTION, this, false);
|
||||
prefs.addObserver(PREF_VIDEO_SELECTED_READER, this, false);
|
||||
prefs.addObserver(PREF_VIDEO_SELECTED_WEB, this, false);
|
||||
prefs.addObserver(PREF_VIDEO_SELECTED_APP, this, false);
|
||||
|
||||
prefs.addObserver(PREF_AUDIO_SELECTED_ACTION, this, false);
|
||||
prefs.addObserver(PREF_AUDIO_SELECTED_READER, this, false);
|
||||
prefs.addObserver(PREF_AUDIO_SELECTED_WEB, this, false);
|
||||
prefs.addObserver(PREF_AUDIO_SELECTED_APP, this, false);
|
||||
|
||||
this._mm.addMessageListener("FeedWriter:PreferenceUpdated", this);
|
||||
this._mm.addMessageListener("FeedWriter:SetApplicationLauncherMenuItem", this);
|
||||
this._mm.addMessageListener("FeedWriter:GetSubscriptionUIResponse", this);
|
||||
this._mm.addMessageListener("FeedWriter:SetFeedPrefsAndSubscribeResponse", this);
|
||||
|
||||
const feedType = this._getFeedType();
|
||||
this._mm.sendAsyncMessage("FeedWriter:GetSubscriptionUI",
|
||||
{ feedType });
|
||||
},
|
||||
|
||||
receiveMessage(msg) {
|
||||
if (!this._window) {
|
||||
// this._window is null unless this.init was called with a trusted
|
||||
// window object.
|
||||
return;
|
||||
}
|
||||
LOG(`received message from parent ${msg.name}`);
|
||||
switch (msg.name) {
|
||||
case "FeedWriter:SetApplicationLauncherMenuItem":
|
||||
let menuItem = null;
|
||||
|
||||
if (msg.data.type == "DefaultAppMenuItem") {
|
||||
menuItem = this._defaultHandlerMenuItem;
|
||||
} else {
|
||||
// Most likely SelectedAppMenuItem
|
||||
menuItem = this._selectedAppMenuItem;
|
||||
case "FeedWriter:PreferenceUpdated":
|
||||
// This is called when browser-feeds.js spots a pref change
|
||||
// This will happen when
|
||||
// - about:preferences#applications changes
|
||||
// - another feed reader page changes the preference
|
||||
// - when this page itself changes the select and there isn't a redirect
|
||||
// bookmarks and launching an external app means the page stays open after subscribe
|
||||
const feedType = this._getFeedType();
|
||||
LOG(`Got prefChange! ${JSON.stringify(msg.data)} current type: ${feedType}`);
|
||||
let feedTypePref = msg.data.default;
|
||||
if (feedType in msg.data) {
|
||||
feedTypePref = msg.data[feedType];
|
||||
}
|
||||
|
||||
menuItem.textContent = msg.data.name;
|
||||
menuItem.style.display = "";
|
||||
menuItem.selected = true;
|
||||
|
||||
LOG(`Got pref ${JSON.stringify(feedTypePref)}`);
|
||||
this._setCheckboxCheckedState(feedTypePref.alwaysUse);
|
||||
this._setSelectedHandlerResponse(feedTypePref.handler, feedTypePref.url);
|
||||
this._setAlwaysUseLabel();
|
||||
break;
|
||||
case "FeedWriter:SetFeedPrefsAndSubscribeResponse":
|
||||
LOG(`FeedWriter:SetFeedPrefsAndSubscribeResponse - Redirecting ${msg.data.redirect}`);
|
||||
this._window.location.href = msg.data.redirect;
|
||||
break;
|
||||
case "FeedWriter:GetSubscriptionUIResponse":
|
||||
// Set up the subscription UI
|
||||
this._initSubscriptionUI(msg.data);
|
||||
break;
|
||||
case "FeedWriter:SetApplicationLauncherMenuItem":
|
||||
LOG(`FeedWriter:SetApplicationLauncherMenuItem - picked ${msg.data.name}`);
|
||||
this._setApplicationLauncherMenuItem(this._selectedAppMenuItem, msg.data.name);
|
||||
// Potentially a bit racy, but I don't think we can get into a state where this callback is set and
|
||||
// we're not coming back from ChooseClientApp in browser-feeds.js
|
||||
if (this._subscribeCallback) {
|
||||
this._subscribeCallback();
|
||||
this._subscribeCallback = null;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_setApplicationLauncherMenuItem(menuItem, aName) {
|
||||
/* unselect all handlers */
|
||||
[...this._handlersList.children].forEach((option) => {
|
||||
option.removeAttribute("selected");
|
||||
});
|
||||
menuItem.textContent = aName;
|
||||
menuItem.style.display = "";
|
||||
menuItem.selected = true;
|
||||
},
|
||||
|
||||
writeContent() {
|
||||
if (!this._window)
|
||||
return;
|
||||
|
@ -983,24 +889,11 @@ FeedWriter.prototype = {
|
|||
close() {
|
||||
this._document.getElementById("subscribeButton")
|
||||
.removeEventListener("click", this);
|
||||
this._document.getElementById("handlersMenuList")
|
||||
this._handlersList
|
||||
.removeEventListener("change", this);
|
||||
this._document = null;
|
||||
this._window = null;
|
||||
let prefs = Services.prefs;
|
||||
prefs.removeObserver(PREF_SELECTED_ACTION, this);
|
||||
prefs.removeObserver(PREF_SELECTED_READER, this);
|
||||
prefs.removeObserver(PREF_SELECTED_WEB, this);
|
||||
prefs.removeObserver(PREF_SELECTED_APP, this);
|
||||
prefs.removeObserver(PREF_VIDEO_SELECTED_ACTION, this);
|
||||
prefs.removeObserver(PREF_VIDEO_SELECTED_READER, this);
|
||||
prefs.removeObserver(PREF_VIDEO_SELECTED_WEB, this);
|
||||
prefs.removeObserver(PREF_VIDEO_SELECTED_APP, this);
|
||||
|
||||
prefs.removeObserver(PREF_AUDIO_SELECTED_ACTION, this);
|
||||
prefs.removeObserver(PREF_AUDIO_SELECTED_READER, this);
|
||||
prefs.removeObserver(PREF_AUDIO_SELECTED_WEB, this);
|
||||
prefs.removeObserver(PREF_AUDIO_SELECTED_APP, this);
|
||||
this._handlersList = null;
|
||||
|
||||
this._removeFeedFromCache();
|
||||
this.__bundle = null;
|
||||
|
@ -1020,20 +913,6 @@ FeedWriter.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
setFeedCharPref(aPrefName, aPrefValue) {
|
||||
this._mm.sendAsyncMessage("FeedWriter:SetFeedCharPref",
|
||||
{ pref: aPrefName,
|
||||
value: aPrefValue });
|
||||
},
|
||||
|
||||
setFeedComplexString(aPrefName, aPrefValue) {
|
||||
// This sends the string data across to the parent, which will use it in an nsISupportsString
|
||||
// for a complex value pref.
|
||||
this._mm.sendAsyncMessage("FeedWriter:SetFeedComplexString",
|
||||
{ pref: aPrefName,
|
||||
value: aPrefValue });
|
||||
},
|
||||
|
||||
subscribe() {
|
||||
let feedType = this._getFeedType();
|
||||
|
||||
|
@ -1041,26 +920,21 @@ FeedWriter.prototype = {
|
|||
let defaultHandler = "reader";
|
||||
let useAsDefault = this._document.getElementById("alwaysUse").getAttribute("checked");
|
||||
|
||||
let menuList = this._document.getElementById("handlersMenuList");
|
||||
let selectedItem = menuList.selectedOptions[0];
|
||||
let selectedItem = this._handlersList.selectedOptions[0];
|
||||
let subscribeCallback = () => {
|
||||
let feedReader = null;
|
||||
let settings = {
|
||||
feedType,
|
||||
useAsDefault,
|
||||
// Pull the title and subtitle out of the document
|
||||
feedTitle: this._document.getElementById(TITLE_ID).textContent,
|
||||
feedSubtitle: this._document.getElementById(SUBTITLE_ID).textContent,
|
||||
feedLocation: this._window.location.href
|
||||
};
|
||||
if (selectedItem.hasAttribute("webhandlerurl")) {
|
||||
let webURI = selectedItem.getAttribute("webhandlerurl");
|
||||
this.setFeedCharPref(getPrefReaderForType(feedType), "web");
|
||||
this.setFeedComplexString(getPrefWebForType(feedType), webURI);
|
||||
|
||||
let wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
|
||||
getService(Ci.nsIWebContentConverterService);
|
||||
let handler = wccr.getWebContentHandlerByURI(this._getMimeTypeForFeedType(feedType), webURI);
|
||||
if (handler) {
|
||||
if (useAsDefault) {
|
||||
wccr.setAutoHandler(this._getMimeTypeForFeedType(feedType), handler);
|
||||
}
|
||||
|
||||
this._window.location.href = handler.getHandlerURI(this._window.location.href);
|
||||
}
|
||||
feedReader = "web";
|
||||
settings.uri = selectedItem.getAttribute("webhandlerurl");
|
||||
} else {
|
||||
let feedReader = null;
|
||||
switch (selectedItem.id) {
|
||||
case "selectedAppMenuItem":
|
||||
feedReader = "client";
|
||||
|
@ -1073,27 +947,20 @@ FeedWriter.prototype = {
|
|||
feedReader = "bookmarks";
|
||||
break;
|
||||
}
|
||||
|
||||
this.setFeedCharPref(getPrefReaderForType(feedType), feedReader);
|
||||
|
||||
let feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
|
||||
getService(Ci.nsIFeedResultService);
|
||||
|
||||
// Pull the title and subtitle out of the document
|
||||
let feedTitle = this._document.getElementById(TITLE_ID).textContent;
|
||||
let feedSubtitle = this._document.getElementById(SUBTITLE_ID).textContent;
|
||||
feedService.addToClientReader(this._window.location.href, feedTitle, feedSubtitle, feedType, feedReader);
|
||||
}
|
||||
settings.reader = feedReader;
|
||||
|
||||
// If "Always use..." is checked, we should set PREF_*SELECTED_ACTION
|
||||
// to either "reader" (If a web reader or if an application is selected),
|
||||
// or to "bookmarks" (if the live bookmarks option is selected).
|
||||
// Otherwise, we should set it to "ask"
|
||||
if (useAsDefault) {
|
||||
this.setFeedCharPref(getPrefActionForType(feedType), defaultHandler);
|
||||
} else {
|
||||
this.setFeedCharPref(getPrefActionForType(feedType), "ask");
|
||||
if (!useAsDefault) {
|
||||
defaultHandler = "ask";
|
||||
}
|
||||
settings.action = defaultHandler;
|
||||
LOG(`FeedWriter:SetFeedPrefsAndSubscribe - ${JSON.stringify(settings)}`);
|
||||
this._mm.sendAsyncMessage("FeedWriter:SetFeedPrefsAndSubscribe",
|
||||
settings);
|
||||
}
|
||||
|
||||
// Show the file picker before subscribing if the
|
||||
|
@ -1111,37 +978,6 @@ FeedWriter.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe(subject, topic, data) {
|
||||
if (!this._window) {
|
||||
// this._window is null unless this.init was called with a trusted
|
||||
// window object.
|
||||
return;
|
||||
}
|
||||
|
||||
let feedType = this._getFeedType();
|
||||
|
||||
if (topic == "nsPref:changed") {
|
||||
switch (data) {
|
||||
case PREF_SELECTED_READER:
|
||||
case PREF_SELECTED_WEB:
|
||||
case PREF_SELECTED_APP:
|
||||
case PREF_VIDEO_SELECTED_READER:
|
||||
case PREF_VIDEO_SELECTED_WEB:
|
||||
case PREF_VIDEO_SELECTED_APP:
|
||||
case PREF_AUDIO_SELECTED_READER:
|
||||
case PREF_AUDIO_SELECTED_WEB:
|
||||
case PREF_AUDIO_SELECTED_APP:
|
||||
this._setSelectedHandler(feedType);
|
||||
break;
|
||||
case PREF_SELECTED_ACTION:
|
||||
case PREF_VIDEO_SELECTED_ACTION:
|
||||
case PREF_AUDIO_SELECTED_ACTION:
|
||||
this._setAlwaysUseCheckedState(feedType);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get _mm() {
|
||||
let mm = this._window.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDocShell).
|
||||
|
|
|
@ -42,7 +42,7 @@ const ARRAY_CONTRACTID = "@mozilla.org/array;1";
|
|||
const SAX_CONTRACTID = "@mozilla.org/saxparser/xmlreader;1";
|
||||
const PARSERUTILS_CONTRACTID = "@mozilla.org/parserutils;1";
|
||||
|
||||
|
||||
const gMimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
|
||||
var gIoService = null;
|
||||
|
||||
const XMLNS = "http://www.w3.org/XML/1998/namespace";
|
||||
|
@ -484,8 +484,15 @@ Entry.prototype = {
|
|||
if (previous_enc != undefined) {
|
||||
previous_enc.QueryInterface(Ci.nsIWritablePropertyBag2);
|
||||
|
||||
if (!bagHasKey(previous_enc, "type") && bagHasKey(new_enc, "type"))
|
||||
if (!bagHasKey(previous_enc, "type") && bagHasKey(new_enc, "type")) {
|
||||
previous_enc.setPropertyAsAString("type", new_enc.getPropertyAsAString("type"));
|
||||
try {
|
||||
let handlerInfoWrapper = gMimeService.getFromTypeAndExtension(new_enc.getPropertyAsAString("type"), null);
|
||||
if (handlerInfoWrapper && handlerInfoWrapper.description) {
|
||||
previous_enc.setPropertyAsAString("typeDesc", handlerInfoWrapper.description);
|
||||
}
|
||||
} catch (ext) {}
|
||||
}
|
||||
|
||||
if (!bagHasKey(previous_enc, "length") && bagHasKey(new_enc, "length"))
|
||||
previous_enc.setPropertyAsAString("length", new_enc.getPropertyAsAString("length"));
|
||||
|
|
Загрузка…
Ссылка в новой задаче