Bug 1477669 - remove feed preview code and associated files/code, r=flod,mak,nika
Differential Revision: https://phabricator.services.mozilla.com/D8524 --HG-- extra : moz-landing-system : lando
|
|
@ -742,10 +742,6 @@ pref("layout.spellcheckDefault", 1);
|
||||||
|
|
||||||
pref("browser.send_pings", false);
|
pref("browser.send_pings", false);
|
||||||
|
|
||||||
pref("browser.feeds.handler", "ask");
|
|
||||||
pref("browser.videoFeeds.handler", "ask");
|
|
||||||
pref("browser.audioFeeds.handler", "ask");
|
|
||||||
|
|
||||||
// At startup, if the handler service notices that the version number in the
|
// At startup, if the handler service notices that the version number in the
|
||||||
// region.properties file is newer than the version number in the handler
|
// region.properties file is newer than the version number in the handler
|
||||||
// service datastore, it will add any new handlers it finds in the prefs (as
|
// service datastore, it will add any new handlers it finds in the prefs (as
|
||||||
|
|
|
||||||
|
|
@ -1,409 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
ChromeUtils.defineModuleGetter(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_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_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_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,
|
|
||||||
]);
|
|
||||||
|
|
||||||
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(["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 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,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.nsIFile, 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 nsIFile 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.nsIFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 = Services.io.newURI(aSpec);
|
|
||||||
if (feedURI.schemeIs("http")) {
|
|
||||||
feedURI = feedURI.mutate()
|
|
||||||
.setScheme("feed")
|
|
||||||
.finalize();
|
|
||||||
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: ChromeUtils.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_VIDEO_SELECTED_ACTION, this, true);
|
|
||||||
prefs.addObserver(PREF_VIDEO_SELECTED_READER, this, true);
|
|
||||||
prefs.addObserver(PREF_AUDIO_SELECTED_ACTION, this, true);
|
|
||||||
prefs.addObserver(PREF_AUDIO_SELECTED_READER, 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_VIDEO_SELECTED_READER:
|
|
||||||
case PREF_AUDIO_SELECTED_READER:
|
|
||||||
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) {
|
|
||||||
let showFirstRunUI = Services.prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI, true);
|
|
||||||
const response = { showFirstRunUI };
|
|
||||||
let selectedClientApp;
|
|
||||||
const feedTypePref = getPrefAppForType(feedType);
|
|
||||||
try {
|
|
||||||
selectedClientApp = Services.prefs.getComplexValue(feedTypePref, Ci.nsIFile);
|
|
||||||
} 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 handler = Services.prefs.getCharPref(getPrefReaderForType(feedType), "bookmarks");
|
|
||||||
const alwaysUse = this._getAlwaysUseState(feedType);
|
|
||||||
const action = Services.prefs.getCharPref(getPrefActionForType(feedType));
|
|
||||||
return { handler, alwaysUse, action };
|
|
||||||
},
|
|
||||||
|
|
||||||
_getAlwaysUseState(feedType) {
|
|
||||||
try {
|
|
||||||
return Services.prefs.getCharPref(getPrefActionForType(feedType)) != "ask";
|
|
||||||
} catch (ex) { }
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
receiveMessage(msg) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
Services.telemetry.scalarAdd("browser.feeds.feed_subscribed", 1);
|
|
||||||
|
|
||||||
const actionPref = getPrefActionForType(settings.feedType);
|
|
||||||
this._setPref(actionPref, settings.action);
|
|
||||||
const readerPref = getPrefReaderForType(settings.feedType);
|
|
||||||
this._setPref(readerPref, settings.reader);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
@ -489,10 +489,6 @@ toolbar:not(#TabsToolbar) > #personal-bookmarks {
|
||||||
-moz-box-flex: 1;
|
-moz-box-flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#PanelUI-feeds > .feed-toolbarbutton:-moz-locale-dir(rtl) {
|
|
||||||
direction: rtl;
|
|
||||||
}
|
|
||||||
|
|
||||||
#appMenu_historyMenu > .bookmark-item,
|
#appMenu_historyMenu > .bookmark-item,
|
||||||
#appMenu-library-recentlyClosedTabs > .panel-subview-body > .bookmark-item,
|
#appMenu-library-recentlyClosedTabs > .panel-subview-body > .bookmark-item,
|
||||||
#appMenu-library-recentlyClosedWindows > .panel-subview-body > .bookmark-item,
|
#appMenu-library-recentlyClosedWindows > .panel-subview-body > .bookmark-item,
|
||||||
|
|
|
||||||
|
|
@ -1352,7 +1352,6 @@ var gBrowserInit = {
|
||||||
gPageStyleMenu.init();
|
gPageStyleMenu.init();
|
||||||
LanguageDetectionListener.init();
|
LanguageDetectionListener.init();
|
||||||
BrowserOnClick.init();
|
BrowserOnClick.init();
|
||||||
FeedHandler.init();
|
|
||||||
ContentBlocking.init();
|
ContentBlocking.init();
|
||||||
CaptivePortalWatcher.init();
|
CaptivePortalWatcher.init();
|
||||||
ZoomUI.init(window);
|
ZoomUI.init(window);
|
||||||
|
|
@ -1933,8 +1932,6 @@ var gBrowserInit = {
|
||||||
|
|
||||||
BrowserOnClick.uninit();
|
BrowserOnClick.uninit();
|
||||||
|
|
||||||
FeedHandler.uninit();
|
|
||||||
|
|
||||||
ContentBlocking.uninit();
|
ContentBlocking.uninit();
|
||||||
|
|
||||||
CaptivePortalWatcher.uninit();
|
CaptivePortalWatcher.uninit();
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ for (let script of [
|
||||||
"chrome://browser/content/browser-captivePortal.js",
|
"chrome://browser/content/browser-captivePortal.js",
|
||||||
"chrome://browser/content/browser-compacttheme.js",
|
"chrome://browser/content/browser-compacttheme.js",
|
||||||
"chrome://browser/content/browser-contentblocking.js",
|
"chrome://browser/content/browser-contentblocking.js",
|
||||||
"chrome://browser/content/browser-feeds.js",
|
|
||||||
"chrome://browser/content/browser-media.js",
|
"chrome://browser/content/browser-media.js",
|
||||||
"chrome://browser/content/browser-pageActions.js",
|
"chrome://browser/content/browser-pageActions.js",
|
||||||
"chrome://browser/content/browser-places.js",
|
"chrome://browser/content/browser-places.js",
|
||||||
|
|
|
||||||
|
|
@ -122,9 +122,6 @@ with Files("browser-compacttheme.js"):
|
||||||
with Files("browser-customization.js"):
|
with Files("browser-customization.js"):
|
||||||
BUG_COMPONENT = ("Firefox", "Toolbars and Customization")
|
BUG_COMPONENT = ("Firefox", "Toolbars and Customization")
|
||||||
|
|
||||||
with Files("browser-feeds.js"):
|
|
||||||
BUG_COMPONENT = ("Firefox", "Toolbars and Customization")
|
|
||||||
|
|
||||||
with Files("browser-fullZoom.js"):
|
with Files("browser-fullZoom.js"):
|
||||||
BUG_COMPONENT = ("Firefox", "Tabbed Browsing")
|
BUG_COMPONENT = ("Firefox", "Tabbed Browsing")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,7 @@ var gTests = [
|
||||||
preventDefault: true,
|
preventDefault: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// The next test was once handling feedService.forcePreview(). Now it should
|
// The next test should just be like Alt click.
|
||||||
// just be like Alt click.
|
|
||||||
{
|
{
|
||||||
desc: "Shift+Alt left click",
|
desc: "Shift+Alt left click",
|
||||||
setup() {
|
setup() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
<rss version="2.0">
|
|
||||||
<channel>
|
|
||||||
<link>http://example.org/</link>
|
|
||||||
<title>t</title>
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<!--
|
|
||||||
https://bugzilla.mozilla.org/show_bug.cgi?id=458579
|
|
||||||
-->
|
|
||||||
<head>
|
|
||||||
<title>Test for page info feeds tab</title>
|
|
||||||
|
|
||||||
<!-- Straight up standard -->
|
|
||||||
<link rel="alternate" type="application/atom+xml" title="1" href="/1.atom" />
|
|
||||||
<link rel="alternate" type="application/rss+xml" title="2" href="/2.rss" />
|
|
||||||
<link rel="feed" title="3" href="/3.xml" />
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
|
|
||||||
function getTestPlugin(pluginName) {
|
|
||||||
var ph = SpecialPowers.Cc["@mozilla.org/plugin/host;1"]
|
|
||||||
.getService(SpecialPowers.Ci.nsIPluginHost);
|
|
||||||
var tags = ph.getPluginTags();
|
|
||||||
var name = pluginName || "Test Plug-in";
|
|
||||||
for (var tag of tags) {
|
|
||||||
if (tag.name == name) {
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ok(false, "Could not find plugin tag with plugin name '" + name + "'");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// call this to set the test plugin(s) initially expected enabled state.
|
|
||||||
// it will automatically be reset to it's previous value after the test
|
|
||||||
// ends
|
|
||||||
function setTestPluginEnabledState(newEnabledState, pluginName) {
|
|
||||||
var plugin = getTestPlugin(pluginName);
|
|
||||||
var oldEnabledState = plugin.enabledState;
|
|
||||||
plugin.enabledState = newEnabledState;
|
|
||||||
SimpleTest.registerCleanupFunction(function() {
|
|
||||||
getTestPlugin(pluginName).enabledState = oldEnabledState;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
[DEFAULT]
|
|
||||||
support-files =
|
|
||||||
audio.ogg
|
|
||||||
bug395533-data.txt
|
|
||||||
contextmenu_common.js
|
|
||||||
ctxmenu-image.png
|
|
||||||
head_plain.js
|
|
||||||
offlineByDefault.js
|
|
||||||
offlineChild.cacheManifest
|
|
||||||
offlineChild.cacheManifest^headers^
|
|
||||||
offlineChild.html
|
|
||||||
offlineChild2.cacheManifest
|
|
||||||
offlineChild2.cacheManifest^headers^
|
|
||||||
offlineChild2.html
|
|
||||||
offlineEvent.cacheManifest
|
|
||||||
offlineEvent.cacheManifest^headers^
|
|
||||||
offlineEvent.html
|
|
||||||
subtst_contextmenu.html
|
|
||||||
video.ogg
|
|
||||||
!/image/test/mochitest/blue.png
|
|
||||||
|
|
||||||
[test_bug395533.html]
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
var offlineByDefault = {
|
|
||||||
defaultValue: false,
|
|
||||||
set(allow) {
|
|
||||||
this.defaultValue = SpecialPowers.Services.prefs.getBoolPref("offline-apps.allow_by_default", false);
|
|
||||||
SpecialPowers.Services.prefs.setBoolPref("offline-apps.allow_by_default", allow);
|
|
||||||
},
|
|
||||||
reset() {
|
|
||||||
SpecialPowers.Services.prefs.setBoolPref("offline-apps.allow_by_default", this.defaultValue);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
offlineByDefault.set(false);
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
CACHE MANIFEST
|
|
||||||
offlineChild.html
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Content-Type: text/cache-manifest
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
<html manifest="offlineChild.cacheManifest">
|
|
||||||
<head>
|
|
||||||
<title></title>
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
function finish(success) {
|
|
||||||
window.parent.postMessage(success ? "success" : "failure", "*");
|
|
||||||
}
|
|
||||||
|
|
||||||
applicationCache.oncached = function() { finish(true); };
|
|
||||||
applicationCache.onnoupdate = function() { finish(true); };
|
|
||||||
applicationCache.onerror = function() { finish(false); };
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h1>Child</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
CACHE MANIFEST
|
|
||||||
offlineChild2.html
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Content-Type: text/cache-manifest
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
<html manifest="offlineChild2.cacheManifest">
|
|
||||||
<head>
|
|
||||||
<title></title>
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
function finish(success) {
|
|
||||||
window.parent.postMessage(success ? "success" : "failure", "*");
|
|
||||||
}
|
|
||||||
|
|
||||||
applicationCache.oncached = function() { finish(true); };
|
|
||||||
applicationCache.onnoupdate = function() { finish(true); };
|
|
||||||
applicationCache.onerror = function() { finish(false); };
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h1>Child</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
CACHE MANIFEST
|
|
||||||
offlineChild.html
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Content-Type: text/cache-manifest
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
<html manifest="offlineEvent.cacheManifest">
|
|
||||||
<head>
|
|
||||||
<title></title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h1>Child</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<!--
|
|
||||||
https://bugzilla.mozilla.org/show_bug.cgi?id=395533
|
|
||||||
-->
|
|
||||||
<head>
|
|
||||||
<title>Test for Bug 395533</title>
|
|
||||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=395533">Mozilla Bug 395533</a>
|
|
||||||
<p id="display"><iframe id="testFrame" src="bug395533-data.txt"></iframe></p>
|
|
||||||
<div id="content" style="display: none">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<pre id="test">
|
|
||||||
<script class="testbody" type="text/javascript">
|
|
||||||
|
|
||||||
/** Test for Bug 395533 **/
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
|
|
||||||
addLoadEvent(function() {
|
|
||||||
// Need privs because the feed seems to have an about:feeds principal or some
|
|
||||||
// such. It's not same-origin with us in any case.
|
|
||||||
is(SpecialPowers.wrap($("testFrame")).contentDocument.documentElement.id, "",
|
|
||||||
"Text got sniffed as a feed?");
|
|
||||||
});
|
|
||||||
addLoadEvent(SimpleTest.finish);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
@ -44,7 +44,6 @@ browser.jar:
|
||||||
#ifndef MOZILLA_OFFICIAL
|
#ifndef MOZILLA_OFFICIAL
|
||||||
content/browser/browser-development-helpers.js (content/browser-development-helpers.js)
|
content/browser/browser-development-helpers.js (content/browser-development-helpers.js)
|
||||||
#endif
|
#endif
|
||||||
content/browser/browser-feeds.js (content/browser-feeds.js)
|
|
||||||
content/browser/browser-fullScreenAndPointerLock.js (content/browser-fullScreenAndPointerLock.js)
|
content/browser/browser-fullScreenAndPointerLock.js (content/browser-fullScreenAndPointerLock.js)
|
||||||
content/browser/browser-fullZoom.js (content/browser-fullZoom.js)
|
content/browser/browser-fullZoom.js (content/browser-fullZoom.js)
|
||||||
content/browser/browser-gestureSupport.js (content/browser-gestureSupport.js)
|
content/browser/browser-gestureSupport.js (content/browser-gestureSupport.js)
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,6 @@ SPHINX_TREES['tabbrowser'] = 'content/docs/tabbrowser'
|
||||||
with Files('content/docs/sslerrorreport/**'):
|
with Files('content/docs/sslerrorreport/**'):
|
||||||
SCHEDULES.exclusive = ['docs']
|
SCHEDULES.exclusive = ['docs']
|
||||||
|
|
||||||
MOCHITEST_MANIFESTS += [
|
|
||||||
'content/test/general/mochitest.ini',
|
|
||||||
]
|
|
||||||
|
|
||||||
MOCHITEST_CHROME_MANIFESTS += [
|
MOCHITEST_CHROME_MANIFESTS += [
|
||||||
'content/test/chrome/chrome.ini',
|
'content/test/chrome/chrome.ini',
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -60,10 +60,6 @@ static const RedirEntry kRedirMap[] = {
|
||||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||||
nsIAboutModule::ALLOW_SCRIPT |
|
nsIAboutModule::ALLOW_SCRIPT |
|
||||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
|
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
|
||||||
{ "feeds", "chrome://browser/content/feeds/subscribe.xhtml",
|
|
||||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
|
||||||
nsIAboutModule::ALLOW_SCRIPT |
|
|
||||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
|
|
||||||
{ "policies", "chrome://browser/content/policies/aboutPolicies.xhtml",
|
{ "policies", "chrome://browser/content/policies/aboutPolicies.xhtml",
|
||||||
nsIAboutModule::ALLOW_SCRIPT },
|
nsIAboutModule::ALLOW_SCRIPT },
|
||||||
{ "privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.xhtml",
|
{ "privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.xhtml",
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ FINAL_LIBRARY = 'xul'
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
'../about',
|
'../about',
|
||||||
'../dirprovider',
|
'../dirprovider',
|
||||||
'../feeds',
|
|
||||||
'../migration',
|
'../migration',
|
||||||
'../sessionstore',
|
'../sessionstore',
|
||||||
'../shell',
|
'../shell',
|
||||||
|
|
|
||||||
|
|
@ -21,15 +21,6 @@
|
||||||
#define NS_RDF_FORWARDPROXY_INFER_DATASOURCE_CID \
|
#define NS_RDF_FORWARDPROXY_INFER_DATASOURCE_CID \
|
||||||
{ 0x7a024bcf, 0xedd5, 0x4d9a, { 0x86, 0x14, 0xd4, 0x4b, 0xe1, 0xda, 0xda, 0xd3 } }
|
{ 0x7a024bcf, 0xedd5, 0x4d9a, { 0x86, 0x14, 0xd4, 0x4b, 0xe1, 0xda, 0xda, 0xd3 } }
|
||||||
|
|
||||||
#define NS_FEEDSNIFFER_CID \
|
|
||||||
{ 0x6893e69, 0x71d8, 0x4b23, { 0x81, 0xeb, 0x80, 0x31, 0x4d, 0xaf, 0x3e, 0x66 } }
|
|
||||||
|
|
||||||
#define NS_FEEDSNIFFER_CONTRACTID \
|
|
||||||
"@mozilla.org/browser/feeds/sniffer;1"
|
|
||||||
|
|
||||||
#define NS_ABOUTFEEDS_CID \
|
|
||||||
{ 0x12ff56ec, 0x58be, 0x402c, { 0xb0, 0x57, 0x1, 0xf9, 0x61, 0xde, 0x96, 0x9b } }
|
|
||||||
|
|
||||||
// 136e2c4d-c5a4-477c-b131-d93d7d704f64
|
// 136e2c4d-c5a4-477c-b131-d93d7d704f64
|
||||||
#define NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID \
|
#define NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID \
|
||||||
{ 0x136e2c4d, 0xc5a4, 0x477c, { 0xb1, 0x31, 0xd9, 0x3d, 0x7d, 0x70, 0x4f, 0x64 } }
|
{ 0x136e2c4d, 0xc5a4, 0x477c, { 0xb1, 0x31, 0xd9, 0x3d, 0x7d, 0x70, 0x4f, 0x64 } }
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
#include "nsIEHistoryEnumerator.h"
|
#include "nsIEHistoryEnumerator.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "nsFeedSniffer.h"
|
|
||||||
#include "AboutRedirector.h"
|
#include "AboutRedirector.h"
|
||||||
#include "nsIAboutModule.h"
|
#include "nsIAboutModule.h"
|
||||||
|
|
||||||
|
|
@ -51,15 +50,12 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacAttributionService)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEHistoryEnumerator)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEHistoryEnumerator)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
|
|
||||||
|
|
||||||
NS_DEFINE_NAMED_CID(NS_BROWSERDIRECTORYPROVIDER_CID);
|
NS_DEFINE_NAMED_CID(NS_BROWSERDIRECTORYPROVIDER_CID);
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
|
NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
|
||||||
#elif defined(MOZ_WIDGET_GTK)
|
#elif defined(MOZ_WIDGET_GTK)
|
||||||
NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
|
NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
|
||||||
#endif
|
#endif
|
||||||
NS_DEFINE_NAMED_CID(NS_FEEDSNIFFER_CID);
|
|
||||||
NS_DEFINE_NAMED_CID(NS_BROWSER_ABOUT_REDIRECTOR_CID);
|
NS_DEFINE_NAMED_CID(NS_BROWSER_ABOUT_REDIRECTOR_CID);
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
NS_DEFINE_NAMED_CID(NS_WINIEHISTORYENUMERATOR_CID);
|
NS_DEFINE_NAMED_CID(NS_WINIEHISTORYENUMERATOR_CID);
|
||||||
|
|
@ -78,7 +74,6 @@ static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
|
||||||
#elif defined(MOZ_WIDGET_GTK)
|
#elif defined(MOZ_WIDGET_GTK)
|
||||||
{ &kNS_SHELLSERVICE_CID, false, nullptr, nsGNOMEShellServiceConstructor },
|
{ &kNS_SHELLSERVICE_CID, false, nullptr, nsGNOMEShellServiceConstructor },
|
||||||
#endif
|
#endif
|
||||||
{ &kNS_FEEDSNIFFER_CID, false, nullptr, nsFeedSnifferConstructor },
|
|
||||||
{ &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, nullptr, AboutRedirector::Create },
|
{ &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, nullptr, AboutRedirector::Create },
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
{ &kNS_WINIEHISTORYENUMERATOR_CID, false, nullptr, nsIEHistoryEnumeratorConstructor },
|
{ &kNS_WINIEHISTORYENUMERATOR_CID, false, nullptr, nsIEHistoryEnumeratorConstructor },
|
||||||
|
|
@ -100,11 +95,9 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
|
||||||
#elif defined(MOZ_WIDGET_GTK)
|
#elif defined(MOZ_WIDGET_GTK)
|
||||||
{ NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
|
{ NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
|
||||||
#endif
|
#endif
|
||||||
{ NS_FEEDSNIFFER_CONTRACTID, &kNS_FEEDSNIFFER_CID },
|
|
||||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "blocked", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "blocked", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "certerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "certerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "tabcrashed", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "tabcrashed", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "feeds", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
|
||||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "privatebrowsing", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "privatebrowsing", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "rights", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "rights", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "robots", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "robots", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||||
|
|
@ -134,7 +127,6 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
|
||||||
|
|
||||||
static const mozilla::Module::CategoryEntry kBrowserCategories[] = {
|
static const mozilla::Module::CategoryEntry kBrowserCategories[] = {
|
||||||
{ XPCOM_DIRECTORY_PROVIDER_CATEGORY, "browser-directory-provider", NS_BROWSERDIRECTORYPROVIDER_CONTRACTID },
|
{ XPCOM_DIRECTORY_PROVIDER_CATEGORY, "browser-directory-provider", NS_BROWSERDIRECTORYPROVIDER_CONTRACTID },
|
||||||
{ NS_CONTENT_SNIFFER_CATEGORY, "Feed Sniffer", NS_FEEDSNIFFER_CONTRACTID },
|
|
||||||
{ nullptr }
|
{ nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -571,9 +571,6 @@
|
||||||
onclick="PanelUI.hide();"/>
|
onclick="PanelUI.hide();"/>
|
||||||
</panelview>
|
</panelview>
|
||||||
|
|
||||||
<panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);">
|
|
||||||
</panelview>
|
|
||||||
|
|
||||||
<panelview id="PanelUI-containers" flex="1">
|
<panelview id="PanelUI-containers" flex="1">
|
||||||
<vbox id="PanelUI-containersItems"/>
|
<vbox id="PanelUI-containersItems"/>
|
||||||
</panelview>
|
</panelview>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,2 @@
|
||||||
component {229fa115-9412-4d32-baf3-2fc407f76fb1} FeedConverter.js
|
|
||||||
contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
|
|
||||||
contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.video.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
|
|
||||||
contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.audio.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
|
|
||||||
component {2376201c-bbc6-472f-9b62-7548040a61c6} FeedConverter.js
|
|
||||||
contract @mozilla.org/browser/feeds/result-service;1 {2376201c-bbc6-472f-9b62-7548040a61c6}
|
|
||||||
component {49bb6593-3aff-4eb3-a068-2712c28bd58e} FeedWriter.js
|
|
||||||
contract @mozilla.org/browser/feeds/result-writer;1 {49bb6593-3aff-4eb3-a068-2712c28bd58e}
|
|
||||||
component {792a7e82-06a0-437c-af63-b2d12e808acc} WebContentConverter.js
|
component {792a7e82-06a0-437c-af63-b2d12e808acc} WebContentConverter.js
|
||||||
contract @mozilla.org/embeddor.implemented/web-content-handler-registrar;1 {792a7e82-06a0-437c-af63-b2d12e808acc}
|
contract @mozilla.org/embeddor.implemented/web-content-handler-registrar;1 {792a7e82-06a0-437c-af63-b2d12e808acc}
|
||||||
|
|
|
||||||
|
|
@ -1,415 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
|
||||||
function LOG(str) {
|
|
||||||
dump("*** " + str + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
const FS_CONTRACTID = "@mozilla.org/browser/feeds/result-service;1";
|
|
||||||
const FPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=feed";
|
|
||||||
const PCPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=pcast";
|
|
||||||
|
|
||||||
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
|
|
||||||
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
|
|
||||||
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
|
|
||||||
const TYPE_ANY = "*/*";
|
|
||||||
|
|
||||||
const PREF_SELECTED_APP = "browser.feeds.handlers.application";
|
|
||||||
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_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_ACTION = "browser.audioFeeds.handler";
|
|
||||||
const PREF_AUDIO_SELECTED_READER = "browser.audioFeeds.handler.default";
|
|
||||||
|
|
||||||
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 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(this, "gCanFrameFeeds",
|
|
||||||
"browser.feeds.unsafelyFrameFeeds", false);
|
|
||||||
|
|
||||||
|
|
||||||
function FeedConverter() {
|
|
||||||
}
|
|
||||||
FeedConverter.prototype = {
|
|
||||||
classID: Components.ID("{229fa115-9412-4d32-baf3-2fc407f76fb1}"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the downloaded text data for the feed.
|
|
||||||
*/
|
|
||||||
_data: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the object listening to the conversion, which is ultimately the
|
|
||||||
* docshell for the load.
|
|
||||||
*/
|
|
||||||
_listener: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Records if the feed was sniffed
|
|
||||||
*/
|
|
||||||
_sniffed: false,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsIStreamConverter.idl
|
|
||||||
*/
|
|
||||||
convert(sourceStream, sourceType, destinationType,
|
|
||||||
context) {
|
|
||||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsIStreamConverter.idl
|
|
||||||
*/
|
|
||||||
asyncConvertData(sourceType, destinationType,
|
|
||||||
listener, context) {
|
|
||||||
this._listener = listener;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the preview page is being forced.
|
|
||||||
*/
|
|
||||||
_forcePreviewPage: false,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release our references to various things once we're done using them.
|
|
||||||
*/
|
|
||||||
_releaseHandles() {
|
|
||||||
this._listener = null;
|
|
||||||
this._request = null;
|
|
||||||
this._processor = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsIFeedResultListener.idl
|
|
||||||
*/
|
|
||||||
handleResult(result) {
|
|
||||||
// Feeds come in various content types, which our feed sniffer coerces to
|
|
||||||
// the maybe.feed type. However, feeds are used as a transport for
|
|
||||||
// different data types, e.g. news/blogs (traditional feed), video/audio
|
|
||||||
// (podcasts) and photos (photocasts, photostreams). Each of these is
|
|
||||||
// different in that there's a different class of application suitable for
|
|
||||||
// handling feeds of that type, but without a content-type differentiation
|
|
||||||
// it is difficult for us to disambiguate.
|
|
||||||
//
|
|
||||||
// The other problem is that if the user specifies an auto-action handler
|
|
||||||
// for one feed application, the fact that the content type is shared means
|
|
||||||
// that all other applications will auto-load with that handler too,
|
|
||||||
// regardless of the content-type.
|
|
||||||
//
|
|
||||||
// This means that content-type alone is not enough to determine whether
|
|
||||||
// or not a feed should be auto-handled. This means that for feeds we need
|
|
||||||
// to always use this stream converter, even when an auto-action is
|
|
||||||
// specified, not the basic one provided by WebContentConverter. This
|
|
||||||
// converter needs to consume all of the data and parse it, and based on
|
|
||||||
// that determination make a judgment about type.
|
|
||||||
//
|
|
||||||
// Since there are no content types for this content, and I'm not going to
|
|
||||||
// invent any, the upshot is that while a user can set an auto-handler for
|
|
||||||
// generic feed content, the system will prevent them from setting an auto-
|
|
||||||
// handler for other stream types. In those cases, the user will always see
|
|
||||||
// the preview page and have to select a handler. We can guess and show
|
|
||||||
// a client handler.
|
|
||||||
//
|
|
||||||
// If this is just a feed, not some kind of specialized application, then
|
|
||||||
// auto-handlers can be set and we should obey them.
|
|
||||||
try {
|
|
||||||
let feedService =
|
|
||||||
Cc["@mozilla.org/browser/feeds/result-service;1"].
|
|
||||||
getService(Ci.nsIFeedResultService);
|
|
||||||
if (!this._forcePreviewPage && result.doc) {
|
|
||||||
let feed = result.doc.QueryInterface(Ci.nsIFeed);
|
|
||||||
let handler = Services.prefs.getCharPref(getPrefActionForType(feed.type), "ask");
|
|
||||||
|
|
||||||
if (handler != "ask") {
|
|
||||||
if (handler == "reader")
|
|
||||||
handler = Services.prefs.getCharPref(getPrefReaderForType(feed.type), "bookmarks");
|
|
||||||
try {
|
|
||||||
let title = feed.title ? feed.title.plainText() : "";
|
|
||||||
let desc = feed.subtitle ? feed.subtitle.plainText() : "";
|
|
||||||
feedService.addToClientReader(result.uri.spec, title, desc, feed.type, handler);
|
|
||||||
return;
|
|
||||||
} catch (ex) { /* fallback to preview mode */ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let chromeChannel;
|
|
||||||
|
|
||||||
// handling a redirect, hence forwarding the loadInfo from the old channel
|
|
||||||
// to the newchannel.
|
|
||||||
let oldChannel = this._request.QueryInterface(Ci.nsIChannel);
|
|
||||||
let loadInfo = oldChannel.loadInfo;
|
|
||||||
|
|
||||||
// If there was no automatic handler, or this was a podcast,
|
|
||||||
// photostream or some other kind of application, show the preview page
|
|
||||||
// if the parser returned a document.
|
|
||||||
if (result.doc) {
|
|
||||||
|
|
||||||
// Store the result in the result service so that the display
|
|
||||||
// page can access it.
|
|
||||||
feedService.addFeedResult(result);
|
|
||||||
|
|
||||||
// Now load the actual XUL document.
|
|
||||||
let aboutFeedsURI = Services.io.newURI("about:feeds");
|
|
||||||
chromeChannel = Services.io.newChannelFromURIWithLoadInfo(aboutFeedsURI, loadInfo);
|
|
||||||
chromeChannel.originalURI = result.uri;
|
|
||||||
|
|
||||||
// carry the origin attributes from the channel that loaded the feed.
|
|
||||||
chromeChannel.owner =
|
|
||||||
Services.scriptSecurityManager.createCodebasePrincipal(aboutFeedsURI,
|
|
||||||
loadInfo.originAttributes);
|
|
||||||
} else {
|
|
||||||
chromeChannel = Services.io.newChannelFromURIWithLoadInfo(result.uri, loadInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
chromeChannel.loadGroup = this._request.loadGroup;
|
|
||||||
chromeChannel.asyncOpen2(this._listener);
|
|
||||||
} finally {
|
|
||||||
this._releaseHandles();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsIStreamListener.idl
|
|
||||||
*/
|
|
||||||
onDataAvailable(request, context, inputStream,
|
|
||||||
sourceOffset, count) {
|
|
||||||
if (this._processor)
|
|
||||||
this._processor.onDataAvailable(request, context, inputStream,
|
|
||||||
sourceOffset, count);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsIRequestObserver.idl
|
|
||||||
*/
|
|
||||||
onStartRequest(request, context) {
|
|
||||||
let channel = request.QueryInterface(Ci.nsIChannel);
|
|
||||||
|
|
||||||
let {loadInfo} = channel;
|
|
||||||
if ((loadInfo.frameOuterWindowID || loadInfo.outerWindowID) != loadInfo.topOuterWindowID &&
|
|
||||||
!gCanFrameFeeds) {
|
|
||||||
// We don't care about frame loads:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for a header that tells us there was no sniffing
|
|
||||||
// The value doesn't matter.
|
|
||||||
try {
|
|
||||||
let httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
|
|
||||||
// Make sure to check requestSucceeded before the potentially-throwing
|
|
||||||
// getResponseHeader.
|
|
||||||
if (!httpChannel.requestSucceeded) {
|
|
||||||
// Just give up, but don't forget to cancel the channel first!
|
|
||||||
request.cancel(Cr.NS_BINDING_ABORTED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: this throws if the header is not set.
|
|
||||||
httpChannel.getResponseHeader("X-Moz-Is-Feed");
|
|
||||||
} catch (ex) {
|
|
||||||
this._sniffed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._request = request;
|
|
||||||
|
|
||||||
// Save and reset the forced state bit early, in case there's some kind of
|
|
||||||
// error.
|
|
||||||
let feedService =
|
|
||||||
Cc["@mozilla.org/browser/feeds/result-service;1"].
|
|
||||||
getService(Ci.nsIFeedResultService);
|
|
||||||
this._forcePreviewPage = feedService.forcePreviewPage;
|
|
||||||
feedService.forcePreviewPage = false;
|
|
||||||
|
|
||||||
// Parse feed data as it comes in
|
|
||||||
this._processor =
|
|
||||||
Cc["@mozilla.org/feed-processor;1"].
|
|
||||||
createInstance(Ci.nsIFeedProcessor);
|
|
||||||
this._processor.listener = this;
|
|
||||||
this._processor.parseAsync(null, channel.URI);
|
|
||||||
|
|
||||||
this._processor.onStartRequest(request, context);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsIRequestObserver.idl
|
|
||||||
*/
|
|
||||||
onStopRequest(request, context, status) {
|
|
||||||
if (this._processor)
|
|
||||||
this._processor.onStopRequest(request, context, status);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsISupports.idl
|
|
||||||
*/
|
|
||||||
QueryInterface: ChromeUtils.generateQI(["nsIFeedResultListener",
|
|
||||||
"nsIStreamConverter",
|
|
||||||
"nsIStreamListener",
|
|
||||||
"nsIRequestObserver"]),
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Keeps parsed FeedResults around for use elsewhere in the UI after the stream
|
|
||||||
* converter completes.
|
|
||||||
*/
|
|
||||||
function FeedResultService() {
|
|
||||||
}
|
|
||||||
|
|
||||||
FeedResultService.prototype = {
|
|
||||||
classID: Components.ID("{2376201c-bbc6-472f-9b62-7548040a61c6}"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A URI spec -> [nsIFeedResult] hash. We have to keep a list as the
|
|
||||||
* value in case the same URI is requested concurrently.
|
|
||||||
*/
|
|
||||||
_results: { },
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsIFeedResultService.idl
|
|
||||||
*/
|
|
||||||
forcePreviewPage: false,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsIFeedResultService.idl
|
|
||||||
*/
|
|
||||||
addToClientReader(spec, title, subtitle, feedType, feedReader) {
|
|
||||||
if (!feedReader) {
|
|
||||||
feedReader = "default";
|
|
||||||
}
|
|
||||||
|
|
||||||
let handler = Services.prefs.getCharPref(getPrefActionForType(feedType), "bookmarks");
|
|
||||||
if (handler == "ask" || handler == "reader")
|
|
||||||
handler = feedReader;
|
|
||||||
|
|
||||||
switch (handler) {
|
|
||||||
case "client":
|
|
||||||
Services.cpmm.sendAsyncMessage("FeedConverter:ExecuteClientApp",
|
|
||||||
{ spec,
|
|
||||||
title,
|
|
||||||
subtitle,
|
|
||||||
feedHandler: getPrefAppForType(feedType) });
|
|
||||||
break;
|
|
||||||
case "default":
|
|
||||||
// Default system feed reader
|
|
||||||
Services.cpmm.sendAsyncMessage("FeedConverter:ExecuteClientApp",
|
|
||||||
{ spec,
|
|
||||||
title,
|
|
||||||
subtitle,
|
|
||||||
feedHandler: "default" });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsIFeedResultService.idl
|
|
||||||
*/
|
|
||||||
addFeedResult(feedResult) {
|
|
||||||
if (feedResult.uri == null)
|
|
||||||
throw new Error("null URI!");
|
|
||||||
if (feedResult.uri == null)
|
|
||||||
throw new Error("null feedResult!");
|
|
||||||
let spec = feedResult.uri.spec;
|
|
||||||
if (!this._results[spec])
|
|
||||||
this._results[spec] = [];
|
|
||||||
this._results[spec].push(feedResult);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsIFeedResultService.idl
|
|
||||||
*/
|
|
||||||
getFeedResult(uri) {
|
|
||||||
if (uri == null)
|
|
||||||
throw new Error("null URI!");
|
|
||||||
let resultList = this._results[uri.spec];
|
|
||||||
for (let result of resultList) {
|
|
||||||
if (result.uri == uri)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsIFeedResultService.idl
|
|
||||||
*/
|
|
||||||
removeFeedResult(uri) {
|
|
||||||
if (uri == null)
|
|
||||||
throw new Error("null URI!");
|
|
||||||
let resultList = this._results[uri.spec];
|
|
||||||
if (!resultList)
|
|
||||||
return;
|
|
||||||
let deletions = 0;
|
|
||||||
for (let i = 0; i < resultList.length; ++i) {
|
|
||||||
if (resultList[i].uri == uri) {
|
|
||||||
delete resultList[i];
|
|
||||||
++deletions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// send the holes to the end
|
|
||||||
resultList.sort();
|
|
||||||
// and trim the list
|
|
||||||
resultList.splice(resultList.length - deletions, deletions);
|
|
||||||
if (resultList.length == 0)
|
|
||||||
delete this._results[uri.spec];
|
|
||||||
},
|
|
||||||
|
|
||||||
createInstance(outer, iid) {
|
|
||||||
if (outer != null)
|
|
||||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
|
||||||
return this.QueryInterface(iid);
|
|
||||||
},
|
|
||||||
|
|
||||||
QueryInterface: ChromeUtils.generateQI(["nsIFeedResultService",
|
|
||||||
"nsIFactory"]),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var components = [FeedConverter,
|
|
||||||
FeedResultService];
|
|
||||||
|
|
||||||
|
|
||||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
|
||||||
|
|
@ -1,528 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
||||||
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
|
||||||
|
|
||||||
const FEEDWRITER_CID = Components.ID("{49bb6593-3aff-4eb3-a068-2712c28bd58e}");
|
|
||||||
const FEEDWRITER_CONTRACTID = "@mozilla.org/browser/feeds/result-writer;1";
|
|
||||||
|
|
||||||
function LOG(str) {
|
|
||||||
let shouldLog = Services.prefs.getBoolPref("feeds.log", false);
|
|
||||||
|
|
||||||
if (shouldLog)
|
|
||||||
dump("*** Feeds: " + str + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper function for nsIIOService::newURI.
|
|
||||||
* @param aURLSpec
|
|
||||||
* The URL string from which to create an nsIURI.
|
|
||||||
* @returns an nsIURI object, or null if the creation of the URI failed.
|
|
||||||
*/
|
|
||||||
function makeURI(aURLSpec, aCharset) {
|
|
||||||
try {
|
|
||||||
return Services.io.newURI(aURLSpec, aCharset);
|
|
||||||
} catch (ex) { }
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
|
|
||||||
|
|
||||||
const TITLE_ID = "feedTitleText";
|
|
||||||
const SUBTITLE_ID = "feedSubtitleText";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a number of bytes to the appropriate unit that results in a
|
|
||||||
* number that needs fewer than 4 digits
|
|
||||||
*
|
|
||||||
* @return a pair: [new value with 3 sig. figs., its unit]
|
|
||||||
*/
|
|
||||||
function convertByteUnits(aBytes) {
|
|
||||||
let units = ["bytes", "kilobyte", "megabyte", "gigabyte"];
|
|
||||||
let unitIndex = 0;
|
|
||||||
|
|
||||||
// convert to next unit if it needs 4 digits (after rounding), but only if
|
|
||||||
// we know the name of the next unit
|
|
||||||
while ((aBytes >= 999.5) && (unitIndex < units.length - 1)) {
|
|
||||||
aBytes /= 1024;
|
|
||||||
unitIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get rid of insignificant bits by truncating to 1 or 0 decimal points
|
|
||||||
// 0 -> 0; 1.2 -> 1.2; 12.3 -> 12.3; 123.4 -> 123; 234.5 -> 235
|
|
||||||
aBytes = aBytes.toFixed((aBytes > 0) && (aBytes < 100) ? 1 : 0);
|
|
||||||
|
|
||||||
return [aBytes, units[unitIndex]];
|
|
||||||
}
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(this, "gCanFrameFeeds",
|
|
||||||
"browser.feeds.unsafelyFrameFeeds", false);
|
|
||||||
|
|
||||||
function FeedWriter() {
|
|
||||||
Services.telemetry.scalarAdd("browser.feeds.preview_loaded", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
FeedWriter.prototype = {
|
|
||||||
_getPropertyAsBag(container, property) {
|
|
||||||
return container.fields.getProperty(property).
|
|
||||||
QueryInterface(Ci.nsIPropertyBag2);
|
|
||||||
},
|
|
||||||
|
|
||||||
_getPropertyAsString(container, property) {
|
|
||||||
try {
|
|
||||||
return container.fields.getPropertyAsAString(property);
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
},
|
|
||||||
|
|
||||||
_setContentText(id, text) {
|
|
||||||
let element = this._document.getElementById(id);
|
|
||||||
let textNode = text.createDocumentFragment(element);
|
|
||||||
while (element.hasChildNodes())
|
|
||||||
element.firstChild.remove();
|
|
||||||
element.appendChild(textNode);
|
|
||||||
if (text.base) {
|
|
||||||
element.setAttributeNS(XML_NS, "base", text.base.spec);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Safely sets the href attribute on an anchor tag, providing the URI
|
|
||||||
* specified can be loaded according to rules.
|
|
||||||
* @param element
|
|
||||||
* The element to set a URI attribute on
|
|
||||||
* @param attribute
|
|
||||||
* The attribute of the element to set the URI to, e.g. href or src
|
|
||||||
* @param uri
|
|
||||||
* The URI spec to set as the href
|
|
||||||
*/
|
|
||||||
_safeSetURIAttribute(element, attribute, uri) {
|
|
||||||
const flags = Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL;
|
|
||||||
try {
|
|
||||||
// TODO Is this necessary?
|
|
||||||
Services.scriptSecurityManager.checkLoadURIStrWithPrincipal(this._feedPrincipal, uri, flags);
|
|
||||||
// checkLoadURIStrWithPrincipal will throw if the link URI should not be
|
|
||||||
// loaded, either because our feedURI isn't allowed to load it or per
|
|
||||||
// the rules specified in |flags|, so we'll never "linkify" the link...
|
|
||||||
} catch (e) {
|
|
||||||
// Not allowed to load this link because secman.checkLoadURIStr threw
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
element.setAttribute(attribute, uri);
|
|
||||||
},
|
|
||||||
|
|
||||||
__bundle: null,
|
|
||||||
get _bundle() {
|
|
||||||
if (!this.__bundle) {
|
|
||||||
this.__bundle = Services.strings.createBundle(URI_BUNDLE);
|
|
||||||
}
|
|
||||||
return this.__bundle;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getFormattedString(key, params) {
|
|
||||||
return this._bundle.formatStringFromName(key, params, params.length);
|
|
||||||
},
|
|
||||||
|
|
||||||
_getString(key) {
|
|
||||||
return this._bundle.GetStringFromName(key);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a date suitable for displaying in the feed preview.
|
|
||||||
* If the date cannot be parsed, the return value is "false".
|
|
||||||
* @param dateString
|
|
||||||
* A date as extracted from a feed entry. (entry.updated)
|
|
||||||
*/
|
|
||||||
_parseDate(dateString) {
|
|
||||||
// Convert the date into the user's local time zone
|
|
||||||
let dateObj = new Date(dateString);
|
|
||||||
|
|
||||||
// Make sure the date we're given is valid.
|
|
||||||
if (!dateObj.getTime())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return this._dateFormatter.format(dateObj);
|
|
||||||
},
|
|
||||||
|
|
||||||
__dateFormatter: null,
|
|
||||||
get _dateFormatter() {
|
|
||||||
if (!this.__dateFormatter) {
|
|
||||||
const dtOptions = {
|
|
||||||
timeStyle: "short",
|
|
||||||
dateStyle: "long",
|
|
||||||
};
|
|
||||||
this.__dateFormatter = new Services.intl.DateTimeFormat(undefined, dtOptions);
|
|
||||||
}
|
|
||||||
return this.__dateFormatter;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the feed title into the preview document.
|
|
||||||
* @param container
|
|
||||||
* The feed container
|
|
||||||
*/
|
|
||||||
_setTitleText(container) {
|
|
||||||
if (container.title) {
|
|
||||||
let title = container.title.plainText();
|
|
||||||
this._setContentText(TITLE_ID, container.title);
|
|
||||||
this._document.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
let feed = container.QueryInterface(Ci.nsIFeed);
|
|
||||||
if (feed && feed.subtitle)
|
|
||||||
this._setContentText(SUBTITLE_ID, container.subtitle);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the title image into the preview document if one is present.
|
|
||||||
* @param container
|
|
||||||
* The feed container
|
|
||||||
*/
|
|
||||||
_setTitleImage(container) {
|
|
||||||
try {
|
|
||||||
let parts = container.image;
|
|
||||||
|
|
||||||
// Set up the title image (supplied by the feed)
|
|
||||||
let feedTitleImage = this._document.getElementById("feedTitleImage");
|
|
||||||
this._safeSetURIAttribute(feedTitleImage, "src",
|
|
||||||
parts.getPropertyAsAString("url"));
|
|
||||||
|
|
||||||
// Set up the title image link
|
|
||||||
let feedTitleLink = this._document.getElementById("feedTitleLink");
|
|
||||||
|
|
||||||
let titleText = this._getFormattedString("linkTitleTextFormat",
|
|
||||||
[parts.getPropertyAsAString("title")]);
|
|
||||||
let feedTitleText = this._document.getElementById("feedTitleText");
|
|
||||||
let titleImageWidth = parseInt(parts.getPropertyAsAString("width")) + 15;
|
|
||||||
|
|
||||||
// Fix the margin on the main title, so that the image doesn't run over
|
|
||||||
// the underline
|
|
||||||
feedTitleLink.setAttribute("title", titleText);
|
|
||||||
feedTitleText.style.marginRight = titleImageWidth + "px";
|
|
||||||
|
|
||||||
this._safeSetURIAttribute(feedTitleLink, "href",
|
|
||||||
parts.getPropertyAsAString("link"));
|
|
||||||
} catch (e) {
|
|
||||||
LOG("Failed to set Title Image (this is benign): " + e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes all entries contained in the feed.
|
|
||||||
* @param container
|
|
||||||
* The container of entries in the feed
|
|
||||||
*/
|
|
||||||
_writeFeedContent(container) {
|
|
||||||
// Build the actual feed content
|
|
||||||
let feed = container.QueryInterface(Ci.nsIFeed);
|
|
||||||
if (feed.items.length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let feedContent = this._document.getElementById("feedContent");
|
|
||||||
|
|
||||||
for (let i = 0; i < feed.items.length; ++i) {
|
|
||||||
let entry = feed.items.queryElementAt(i, Ci.nsIFeedEntry);
|
|
||||||
entry.QueryInterface(Ci.nsIFeedContainer);
|
|
||||||
|
|
||||||
let entryContainer = this._document.createElementNS(HTML_NS, "div");
|
|
||||||
entryContainer.className = "entry";
|
|
||||||
|
|
||||||
// If the entry has a title, make it a link
|
|
||||||
if (entry.title) {
|
|
||||||
let a = this._document.createElementNS(HTML_NS, "a");
|
|
||||||
let span = this._document.createElementNS(HTML_NS, "span");
|
|
||||||
a.appendChild(span);
|
|
||||||
if (entry.title.base)
|
|
||||||
span.setAttributeNS(XML_NS, "base", entry.title.base.spec);
|
|
||||||
span.appendChild(entry.title.createDocumentFragment(a));
|
|
||||||
|
|
||||||
// Entries are not required to have links, so entry.link can be null.
|
|
||||||
if (entry.link)
|
|
||||||
this._safeSetURIAttribute(a, "href", entry.link.spec);
|
|
||||||
|
|
||||||
let title = this._document.createElementNS(HTML_NS, "h3");
|
|
||||||
title.appendChild(a);
|
|
||||||
|
|
||||||
let lastUpdated = this._parseDate(entry.updated);
|
|
||||||
if (lastUpdated) {
|
|
||||||
let dateDiv = this._document.createElementNS(HTML_NS, "div");
|
|
||||||
dateDiv.className = "lastUpdated";
|
|
||||||
dateDiv.textContent = lastUpdated;
|
|
||||||
title.appendChild(dateDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
entryContainer.appendChild(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
let body = this._document.createElementNS(HTML_NS, "div");
|
|
||||||
let summary = entry.summary || entry.content;
|
|
||||||
let docFragment = null;
|
|
||||||
if (summary) {
|
|
||||||
if (summary.base)
|
|
||||||
body.setAttributeNS(XML_NS, "base", summary.base.spec);
|
|
||||||
else
|
|
||||||
LOG("no base?");
|
|
||||||
docFragment = summary.createDocumentFragment(body);
|
|
||||||
if (docFragment)
|
|
||||||
body.appendChild(docFragment);
|
|
||||||
|
|
||||||
// If the entry doesn't have a title, append a # permalink
|
|
||||||
// See http://scripting.com/rss.xml for an example
|
|
||||||
if (!entry.title && entry.link) {
|
|
||||||
let a = this._document.createElementNS(HTML_NS, "a");
|
|
||||||
a.appendChild(this._document.createTextNode("#"));
|
|
||||||
this._safeSetURIAttribute(a, "href", entry.link.spec);
|
|
||||||
body.appendChild(this._document.createTextNode(" "));
|
|
||||||
body.appendChild(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
body.className = "feedEntryContent";
|
|
||||||
entryContainer.appendChild(body);
|
|
||||||
|
|
||||||
if (entry.enclosures && entry.enclosures.length > 0) {
|
|
||||||
let enclosuresDiv = this._buildEnclosureDiv(entry);
|
|
||||||
entryContainer.appendChild(enclosuresDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
let clearDiv = this._document.createElementNS(HTML_NS, "div");
|
|
||||||
clearDiv.style.clear = "both";
|
|
||||||
|
|
||||||
feedContent.appendChild(entryContainer);
|
|
||||||
feedContent.appendChild(clearDiv);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a url to a media item and returns the best name it can come up with.
|
|
||||||
* Frequently this is the filename portion (e.g. passing in
|
|
||||||
* http://example.com/foo.mpeg would return "foo.mpeg"), but in more complex
|
|
||||||
* cases, this will return the entire url (e.g. passing in
|
|
||||||
* http://example.com/somedirectory/ would return
|
|
||||||
* http://example.com/somedirectory/).
|
|
||||||
* @param aURL
|
|
||||||
* The URL string from which to create a display name
|
|
||||||
* @returns a string
|
|
||||||
*/
|
|
||||||
_getURLDisplayName(aURL) {
|
|
||||||
let url = makeURI(aURL);
|
|
||||||
url.QueryInterface(Ci.nsIURL);
|
|
||||||
if (url == null || url.fileName.length == 0)
|
|
||||||
return decodeURIComponent(aURL);
|
|
||||||
|
|
||||||
return decodeURIComponent(url.fileName);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a FeedEntry with enclosures, generates the HTML code to represent
|
|
||||||
* them, and returns that.
|
|
||||||
* @param entry
|
|
||||||
* FeedEntry with enclosures
|
|
||||||
* @returns element
|
|
||||||
*/
|
|
||||||
_buildEnclosureDiv(entry) {
|
|
||||||
let enclosuresDiv = this._document.createElementNS(HTML_NS, "div");
|
|
||||||
enclosuresDiv.className = "enclosures";
|
|
||||||
|
|
||||||
enclosuresDiv.appendChild(this._document.createTextNode(this._getString("mediaLabel")));
|
|
||||||
|
|
||||||
for (let i_enc = 0; i_enc < entry.enclosures.length; ++i_enc) {
|
|
||||||
let enc = entry.enclosures.queryElementAt(i_enc, Ci.nsIWritablePropertyBag2);
|
|
||||||
|
|
||||||
if (!(enc.hasKey("url")))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let enclosureDiv = this._document.createElementNS(HTML_NS, "div");
|
|
||||||
enclosureDiv.setAttribute("class", "enclosure");
|
|
||||||
|
|
||||||
let mozicon = "moz-icon://.txt?size=16";
|
|
||||||
let type_text = null;
|
|
||||||
let size_text = null;
|
|
||||||
|
|
||||||
if (enc.hasKey("type")) {
|
|
||||||
type_text = enc.get("type");
|
|
||||||
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"))) {
|
|
||||||
let enc_size = convertByteUnits(parseInt(enc.get("length")));
|
|
||||||
|
|
||||||
size_text = this._getFormattedString("enclosureSizeText",
|
|
||||||
[enc_size[0],
|
|
||||||
this._getString(enc_size[1])]);
|
|
||||||
}
|
|
||||||
|
|
||||||
let iconimg = this._document.createElementNS(HTML_NS, "img");
|
|
||||||
iconimg.setAttribute("src", mozicon);
|
|
||||||
iconimg.setAttribute("class", "type-icon");
|
|
||||||
enclosureDiv.appendChild(iconimg);
|
|
||||||
|
|
||||||
enclosureDiv.appendChild(this._document.createTextNode( " " ));
|
|
||||||
|
|
||||||
let enc_href = this._document.createElementNS(HTML_NS, "a");
|
|
||||||
enc_href.appendChild(this._document.createTextNode(this._getURLDisplayName(enc.get("url"))));
|
|
||||||
this._safeSetURIAttribute(enc_href, "href", enc.get("url"));
|
|
||||||
enclosureDiv.appendChild(enc_href);
|
|
||||||
|
|
||||||
if (type_text && size_text)
|
|
||||||
enclosureDiv.appendChild(this._document.createTextNode( " (" + type_text + ", " + size_text + ")"));
|
|
||||||
|
|
||||||
else if (type_text)
|
|
||||||
enclosureDiv.appendChild(this._document.createTextNode( " (" + type_text + ")"));
|
|
||||||
|
|
||||||
else if (size_text)
|
|
||||||
enclosureDiv.appendChild(this._document.createTextNode( " (" + size_text + ")"));
|
|
||||||
|
|
||||||
enclosuresDiv.appendChild(enclosureDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return enclosuresDiv;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a valid nsIFeedContainer object from the parsed nsIFeedResult.
|
|
||||||
* Displays error information if there was one.
|
|
||||||
* @returns A valid nsIFeedContainer object containing the contents of
|
|
||||||
* the feed.
|
|
||||||
*/
|
|
||||||
_getContainer() {
|
|
||||||
let feedService =
|
|
||||||
Cc["@mozilla.org/browser/feeds/result-service;1"].
|
|
||||||
getService(Ci.nsIFeedResultService);
|
|
||||||
|
|
||||||
let result;
|
|
||||||
try {
|
|
||||||
result =
|
|
||||||
feedService.getFeedResult(this._getOriginalURI(this._window));
|
|
||||||
} catch (e) {
|
|
||||||
LOG("Subscribe Preview: feed not available?!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.bozo) {
|
|
||||||
LOG("Subscribe Preview: feed result is bozo?!");
|
|
||||||
}
|
|
||||||
|
|
||||||
let container;
|
|
||||||
try {
|
|
||||||
container = result.doc;
|
|
||||||
} catch (e) {
|
|
||||||
LOG("Subscribe Preview: no result.doc? Why didn't the original reload?");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return container;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the original URI object of the feed and ensures that this
|
|
||||||
* component is only ever invoked from the preview document.
|
|
||||||
* @param aWindow
|
|
||||||
* The window of the document invoking the BrowserFeedWriter
|
|
||||||
*/
|
|
||||||
_getOriginalURI(aWindow) {
|
|
||||||
let docShell = aWindow.docShell;
|
|
||||||
let chan = docShell.currentDocumentChannel;
|
|
||||||
|
|
||||||
// We probably need to call Inherit() for this, but right now we can't call
|
|
||||||
// it from JS.
|
|
||||||
let attrs = docShell.getOriginAttributes();
|
|
||||||
let ssm = Services.scriptSecurityManager;
|
|
||||||
let nullPrincipal = ssm.createNullPrincipal(attrs);
|
|
||||||
|
|
||||||
// this channel is not going to be openend, use a nullPrincipal
|
|
||||||
// and the most restrctive securityFlag.
|
|
||||||
let resolvedURI = NetUtil.newChannel({
|
|
||||||
uri: "about:feeds",
|
|
||||||
loadingPrincipal: nullPrincipal,
|
|
||||||
securityFlags: Ci.nsILoadInfo.SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
|
|
||||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
|
|
||||||
}).URI;
|
|
||||||
|
|
||||||
if (resolvedURI.equals(chan.URI))
|
|
||||||
return chan.originalURI;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
_window: null,
|
|
||||||
_document: null,
|
|
||||||
_feedURI: null,
|
|
||||||
_feedPrincipal: null,
|
|
||||||
|
|
||||||
// BrowserFeedWriter WebIDL methods
|
|
||||||
init(aWindow) {
|
|
||||||
let window = aWindow;
|
|
||||||
if (window != window.top && !gCanFrameFeeds) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._feedURI = this._getOriginalURI(window);
|
|
||||||
if (!this._feedURI)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._window = window;
|
|
||||||
this._document = window.document;
|
|
||||||
|
|
||||||
this._feedPrincipal = Services.scriptSecurityManager.createCodebasePrincipal(this._feedURI, {});
|
|
||||||
|
|
||||||
LOG("Subscribe Preview: feed uri = " + this._window.location.href);
|
|
||||||
},
|
|
||||||
|
|
||||||
writeContent() {
|
|
||||||
if (!this._window)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Set up the feed content
|
|
||||||
let container = this._getContainer();
|
|
||||||
if (!container)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._setTitleText(container);
|
|
||||||
this._setTitleImage(container);
|
|
||||||
this._writeFeedContent(container);
|
|
||||||
} finally {
|
|
||||||
this._removeFeedFromCache();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
close() {
|
|
||||||
if (!this._window) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._document = null;
|
|
||||||
this._window = null;
|
|
||||||
|
|
||||||
this._removeFeedFromCache();
|
|
||||||
this.__bundle = null;
|
|
||||||
this._feedURI = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
_removeFeedFromCache() {
|
|
||||||
if (this._window && this._feedURI) {
|
|
||||||
let feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
|
|
||||||
getService(Ci.nsIFeedResultService);
|
|
||||||
feedService.removeFeedResult(this._feedURI);
|
|
||||||
this._feedURI = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
classID: FEEDWRITER_CID,
|
|
||||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver,
|
|
||||||
Ci.nsIDOMGlobalPropertyInitializer]),
|
|
||||||
};
|
|
||||||
|
|
||||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([FeedWriter]);
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
var SubscribeHandler = {
|
|
||||||
/**
|
|
||||||
* The nsIFeedWriter object that produces the UI
|
|
||||||
*/
|
|
||||||
_feedWriter: null,
|
|
||||||
|
|
||||||
init: function SH_init() {
|
|
||||||
this._feedWriter = new BrowserFeedWriter();
|
|
||||||
},
|
|
||||||
|
|
||||||
writeContent: function SH_writeContent() {
|
|
||||||
this._feedWriter.writeContent();
|
|
||||||
},
|
|
||||||
|
|
||||||
uninit: function SH_uninit() {
|
|
||||||
this._feedWriter.close();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
SubscribeHandler.init();
|
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
SubscribeHandler.writeContent();
|
|
||||||
};
|
|
||||||
|
|
||||||
window.onunload = function() {
|
|
||||||
SubscribeHandler.uninit();
|
|
||||||
};
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 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/. -->
|
|
||||||
|
|
||||||
|
|
||||||
<!DOCTYPE html [
|
|
||||||
<!ENTITY % htmlDTD
|
|
||||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
|
||||||
"DTD/xhtml1-strict.dtd">
|
|
||||||
%htmlDTD;
|
|
||||||
<!ENTITY % globalDTD
|
|
||||||
SYSTEM "chrome://global/locale/global.dtd">
|
|
||||||
%globalDTD;
|
|
||||||
<!ENTITY % feedDTD
|
|
||||||
SYSTEM "chrome://browser/locale/feeds/subscribe.dtd">
|
|
||||||
%feedDTD;
|
|
||||||
]>
|
|
||||||
|
|
||||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
|
||||||
|
|
||||||
<html id="feedHandler"
|
|
||||||
xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; img-src *; media-src *" />
|
|
||||||
<title>&feedPage.title;</title>
|
|
||||||
<link rel="stylesheet"
|
|
||||||
href="chrome://browser/skin/feeds/subscribe.css"
|
|
||||||
type="text/css"
|
|
||||||
media="all"/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="feedHeaderContainer">
|
|
||||||
<div id="feedHeader" dir="&locale.dir;">
|
|
||||||
<div id="feedIntroText">
|
|
||||||
<p id="feedSubscriptionInfo1" />
|
|
||||||
<p id="feedSubscriptionInfo2" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="feedHeaderContainerSpacer"/>
|
|
||||||
</div>
|
|
||||||
<div id="feedBody">
|
|
||||||
<div id="feedTitle">
|
|
||||||
<a id="feedTitleLink">
|
|
||||||
<img id="feedTitleImage"/>
|
|
||||||
</a>
|
|
||||||
<div id="feedTitleContainer">
|
|
||||||
<h1 id="feedTitleText"/>
|
|
||||||
<h2 id="feedSubtitleText"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="feedContent"/>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
<script type="application/javascript" src="chrome://browser/content/feeds/subscribe.js"/>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,7 +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/.
|
|
||||||
|
|
||||||
browser.jar:
|
|
||||||
content/browser/feeds/subscribe.xhtml (content/subscribe.xhtml)
|
|
||||||
content/browser/feeds/subscribe.js (content/subscribe.js)
|
|
||||||
|
|
@ -4,37 +4,13 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome/chrome.ini']
|
|
||||||
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
||||||
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
|
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
|
||||||
|
|
||||||
JAR_MANIFESTS += ['jar.mn']
|
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
|
||||||
'nsIFeedResultService.idl',
|
|
||||||
]
|
|
||||||
|
|
||||||
XPIDL_MODULE = 'browser-feeds'
|
|
||||||
|
|
||||||
SOURCES += [
|
|
||||||
'nsFeedSniffer.cpp',
|
|
||||||
]
|
|
||||||
|
|
||||||
EXTRA_COMPONENTS += [
|
EXTRA_COMPONENTS += [
|
||||||
'BrowserFeeds.manifest',
|
'BrowserFeeds.manifest',
|
||||||
'FeedConverter.js',
|
|
||||||
'FeedWriter.js',
|
|
||||||
'WebContentConverter.js',
|
'WebContentConverter.js',
|
||||||
]
|
]
|
||||||
|
|
||||||
FINAL_LIBRARY = 'browsercomps'
|
|
||||||
|
|
||||||
for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
|
|
||||||
DEFINES[var] = CONFIG[var]
|
|
||||||
|
|
||||||
LOCAL_INCLUDES += [
|
|
||||||
'../build',
|
|
||||||
]
|
|
||||||
|
|
||||||
with Files('**'):
|
with Files('**'):
|
||||||
BUG_COMPONENT = ('Firefox', 'RSS Discovery and Preview')
|
BUG_COMPONENT = ('Firefox', 'RSS Discovery and Preview')
|
||||||
|
|
|
||||||
|
|
@ -1,391 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 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/. */
|
|
||||||
|
|
||||||
#include "nsFeedSniffer.h"
|
|
||||||
|
|
||||||
#include "mozilla/Preferences.h"
|
|
||||||
#include "mozilla/Unused.h"
|
|
||||||
|
|
||||||
#include "nsNetCID.h"
|
|
||||||
#include "nsXPCOM.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsStringStream.h"
|
|
||||||
|
|
||||||
#include "nsBrowserCompsCID.h"
|
|
||||||
|
|
||||||
#include "nsICategoryManager.h"
|
|
||||||
#include "nsIServiceManager.h"
|
|
||||||
#include "nsComponentManagerUtils.h"
|
|
||||||
#include "nsServiceManagerUtils.h"
|
|
||||||
|
|
||||||
#include "nsIStreamConverterService.h"
|
|
||||||
#include "nsIStreamConverter.h"
|
|
||||||
|
|
||||||
#include "nsIStreamListener.h"
|
|
||||||
|
|
||||||
#include "nsIHttpChannel.h"
|
|
||||||
#include "nsIMIMEHeaderParam.h"
|
|
||||||
|
|
||||||
#include "nsMimeTypes.h"
|
|
||||||
#include "nsIURI.h"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#define TYPE_ATOM "application/atom+xml"
|
|
||||||
#define TYPE_RSS "application/rss+xml"
|
|
||||||
#define TYPE_MAYBE_FEED "application/vnd.mozilla.maybe.feed"
|
|
||||||
|
|
||||||
#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
#define NS_RSS "http://purl.org/rss/1.0/"
|
|
||||||
|
|
||||||
#define MAX_BYTES 512u
|
|
||||||
|
|
||||||
static bool sFramePrefCached = false;
|
|
||||||
static bool sFramingAllowed = false;
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(nsFeedSniffer,
|
|
||||||
nsIContentSniffer,
|
|
||||||
nsIStreamListener,
|
|
||||||
nsIRequestObserver)
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsFeedSniffer::ConvertEncodedData(nsIRequest* request,
|
|
||||||
const uint8_t* data,
|
|
||||||
uint32_t length)
|
|
||||||
{
|
|
||||||
nsresult rv = NS_OK;
|
|
||||||
|
|
||||||
mDecodedData = "";
|
|
||||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
|
|
||||||
if (!httpChannel)
|
|
||||||
return NS_ERROR_NO_INTERFACE;
|
|
||||||
|
|
||||||
nsAutoCString contentEncoding;
|
|
||||||
mozilla::Unused << httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"),
|
|
||||||
contentEncoding);
|
|
||||||
if (!contentEncoding.IsEmpty()) {
|
|
||||||
nsCOMPtr<nsIStreamConverterService> converterService(do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID));
|
|
||||||
if (converterService) {
|
|
||||||
ToLowerCase(contentEncoding);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIStreamListener> converter;
|
|
||||||
rv = converterService->AsyncConvertData(contentEncoding.get(),
|
|
||||||
"uncompressed", this, nullptr,
|
|
||||||
getter_AddRefs(converter));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
converter->OnStartRequest(request, nullptr);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIStringInputStream> rawStream =
|
|
||||||
do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID);
|
|
||||||
if (!rawStream)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
rv = rawStream->SetData((const char*)data, length);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = converter->OnDataAvailable(request, nullptr, rawStream, 0, length);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
converter->OnStopRequest(request, nullptr, NS_OK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int N>
|
|
||||||
static bool
|
|
||||||
StringBeginsWithLowercaseLiteral(nsAString& aString,
|
|
||||||
const char (&aSubstring)[N])
|
|
||||||
{
|
|
||||||
return StringHead(aString, N).LowerCaseEqualsLiteral(aSubstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
HasAttachmentDisposition(nsIHttpChannel* httpChannel)
|
|
||||||
{
|
|
||||||
if (!httpChannel)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
uint32_t disp;
|
|
||||||
nsresult rv = httpChannel->GetContentDisposition(&disp);
|
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv) && disp == nsIChannel::DISPOSITION_ATTACHMENT)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the first occurrence of a character within a string buffer,
|
|
||||||
* or nullptr if not found
|
|
||||||
*/
|
|
||||||
static const char*
|
|
||||||
FindChar(char c, const char *begin, const char *end)
|
|
||||||
{
|
|
||||||
for (; begin < end; ++begin) {
|
|
||||||
if (*begin == c)
|
|
||||||
return begin;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Determine if a substring is the "documentElement" in the document.
|
|
||||||
*
|
|
||||||
* All of our sniffed substrings: <rss, <feed, <rdf:RDF must be the "document"
|
|
||||||
* element within the XML DOM, i.e. the root container element. Otherwise,
|
|
||||||
* it's possible that someone embedded one of these tags inside a document of
|
|
||||||
* another type, e.g. a HTML document, and we don't want to show the preview
|
|
||||||
* page if the document isn't actually a feed.
|
|
||||||
*
|
|
||||||
* @param start
|
|
||||||
* The beginning of the data being sniffed
|
|
||||||
* @param end
|
|
||||||
* The end of the data being sniffed, right before the substring that
|
|
||||||
* was found.
|
|
||||||
* @returns true if the found substring is the documentElement, false
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
IsDocumentElement(const char *start, const char* end)
|
|
||||||
{
|
|
||||||
// For every tag in the buffer, check to see if it's a PI, Doctype or
|
|
||||||
// comment, our desired substring or something invalid.
|
|
||||||
while ( (start = FindChar('<', start, end)) ) {
|
|
||||||
++start;
|
|
||||||
if (start >= end)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check to see if the character following the '<' is either '?' or '!'
|
|
||||||
// (processing instruction or doctype or comment)... these are valid nodes
|
|
||||||
// to have in the prologue.
|
|
||||||
if (*start != '?' && *start != '!')
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Now advance the iterator until the '>' (We do this because we don't want
|
|
||||||
// to sniff indicator substrings that are embedded within other nodes, e.g.
|
|
||||||
// comments: <!-- <rdf:RDF .. > -->
|
|
||||||
start = FindChar('>', start, end);
|
|
||||||
if (!start)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
++start;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether or not a string exists as the root element in an XML data
|
|
||||||
* string buffer.
|
|
||||||
* @param dataString
|
|
||||||
* The data being sniffed
|
|
||||||
* @param substring
|
|
||||||
* The substring being tested for existence and root-ness.
|
|
||||||
* @returns true if the substring exists and is the documentElement, false
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
ContainsTopLevelSubstring(nsACString& dataString, const char *substring)
|
|
||||||
{
|
|
||||||
nsACString::const_iterator start, end;
|
|
||||||
dataString.BeginReading(start);
|
|
||||||
dataString.EndReading(end);
|
|
||||||
|
|
||||||
if (!FindInReadable(nsCString(substring), start, end)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto offset = start.get() - dataString.Data();
|
|
||||||
|
|
||||||
const char *begin = dataString.BeginReading();
|
|
||||||
|
|
||||||
// Only do the validation when we find the substring.
|
|
||||||
return IsDocumentElement(begin, begin + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsFeedSniffer::GetMIMETypeFromContent(nsIRequest* request,
|
|
||||||
const uint8_t* data,
|
|
||||||
uint32_t length,
|
|
||||||
nsACString& sniffedType)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIHttpChannel> channel(do_QueryInterface(request));
|
|
||||||
if (!channel)
|
|
||||||
return NS_ERROR_NO_INTERFACE;
|
|
||||||
|
|
||||||
// Check that this is a GET request, since you can't subscribe to a POST...
|
|
||||||
nsAutoCString method;
|
|
||||||
mozilla::Unused << channel->GetRequestMethod(method);
|
|
||||||
if (!method.EqualsLiteral("GET")) {
|
|
||||||
sniffedType.Truncate();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sFramePrefCached) {
|
|
||||||
sFramePrefCached = true;
|
|
||||||
Preferences::AddBoolVarCache(&sFramingAllowed,
|
|
||||||
"browser.feeds.unsafelyFrameFeeds");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sFramingAllowed) {
|
|
||||||
// Check that we're the toplevel frame:
|
|
||||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
|
||||||
if (!loadInfo) {
|
|
||||||
sniffedType.Truncate();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
auto frameID = loadInfo->GetFrameOuterWindowID();
|
|
||||||
if (!frameID) {
|
|
||||||
frameID = loadInfo->GetOuterWindowID();
|
|
||||||
}
|
|
||||||
if (loadInfo->GetTopOuterWindowID() != frameID) {
|
|
||||||
sniffedType.Truncate();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to find out if this is a load of a view-source document. In this
|
|
||||||
// case we do not want to override the content type, since the source display
|
|
||||||
// does not need to be converted from feed format to XUL. More importantly,
|
|
||||||
// we don't want to change the content type from something
|
|
||||||
// nsContentDLF::CreateInstance knows about (e.g. application/xml, text/html
|
|
||||||
// etc) to something that only the application fe knows about (maybe.feed)
|
|
||||||
// thus deactivating syntax highlighting.
|
|
||||||
nsCOMPtr<nsIURI> originalURI;
|
|
||||||
channel->GetOriginalURI(getter_AddRefs(originalURI));
|
|
||||||
|
|
||||||
nsAutoCString scheme;
|
|
||||||
originalURI->GetScheme(scheme);
|
|
||||||
if (scheme.EqualsLiteral("view-source")) {
|
|
||||||
sniffedType.Truncate();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the Content-Type to see if it is set correctly. If it is set to
|
|
||||||
// something specific that we think is a reliable indication of a feed, don't
|
|
||||||
// bother sniffing since we assume the site maintainer knows what they're
|
|
||||||
// doing.
|
|
||||||
nsAutoCString contentType;
|
|
||||||
channel->GetContentType(contentType);
|
|
||||||
bool noSniff = contentType.EqualsLiteral(TYPE_RSS) ||
|
|
||||||
contentType.EqualsLiteral(TYPE_ATOM);
|
|
||||||
|
|
||||||
if (noSniff) {
|
|
||||||
// check for an attachment after we have a likely feed.
|
|
||||||
if(HasAttachmentDisposition(channel)) {
|
|
||||||
sniffedType.Truncate();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the feed header as a response header, since we have good metadata
|
|
||||||
// telling us that the feed is supposed to be RSS or Atom
|
|
||||||
mozilla::DebugOnly<nsresult> rv =
|
|
||||||
channel->SetResponseHeader(NS_LITERAL_CSTRING("X-Moz-Is-Feed"),
|
|
||||||
NS_LITERAL_CSTRING("1"), false);
|
|
||||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
|
||||||
sniffedType.AssignLiteral(TYPE_MAYBE_FEED);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't sniff arbitrary types. Limit sniffing to situations that
|
|
||||||
// we think can reasonably arise.
|
|
||||||
if (!contentType.EqualsLiteral(TEXT_HTML) &&
|
|
||||||
!contentType.EqualsLiteral(APPLICATION_OCTET_STREAM) &&
|
|
||||||
// Same criterion as XMLHttpRequest. Should we be checking for "+xml"
|
|
||||||
// and check for text/xml and application/xml by hand instead?
|
|
||||||
contentType.Find("xml") == -1) {
|
|
||||||
sniffedType.Truncate();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we need to potentially decompress data served with
|
|
||||||
// Content-Encoding: gzip
|
|
||||||
nsresult rv = ConvertEncodedData(request, data, length);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
|
|
||||||
// We cap the number of bytes to scan at MAX_BYTES to prevent picking up
|
|
||||||
// false positives by accidentally reading document content, e.g. a "how to
|
|
||||||
// make a feed" page.
|
|
||||||
const char* testData;
|
|
||||||
if (mDecodedData.IsEmpty()) {
|
|
||||||
testData = (const char*)data;
|
|
||||||
length = std::min(length, MAX_BYTES);
|
|
||||||
} else {
|
|
||||||
testData = mDecodedData.get();
|
|
||||||
length = std::min(mDecodedData.Length(), MAX_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The strategy here is based on that described in:
|
|
||||||
// http://blogs.msdn.com/rssteam/articles/PublishersGuide.aspx
|
|
||||||
// for interoperarbility purposes.
|
|
||||||
|
|
||||||
// Thus begins the actual sniffing.
|
|
||||||
nsDependentCSubstring dataString((const char*)testData, length);
|
|
||||||
|
|
||||||
bool isFeed = false;
|
|
||||||
|
|
||||||
// RSS 0.91/0.92/2.0
|
|
||||||
isFeed = ContainsTopLevelSubstring(dataString, "<rss");
|
|
||||||
|
|
||||||
// Atom 1.0
|
|
||||||
if (!isFeed)
|
|
||||||
isFeed = ContainsTopLevelSubstring(dataString, "<feed");
|
|
||||||
|
|
||||||
// RSS 1.0
|
|
||||||
if (!isFeed) {
|
|
||||||
bool foundNS_RDF = FindInReadable(NS_LITERAL_CSTRING(NS_RDF), dataString);
|
|
||||||
bool foundNS_RSS = FindInReadable(NS_LITERAL_CSTRING(NS_RSS), dataString);
|
|
||||||
isFeed = ContainsTopLevelSubstring(dataString, "<rdf:RDF") &&
|
|
||||||
foundNS_RDF && foundNS_RSS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we sniffed a feed, coerce our internal type
|
|
||||||
if (isFeed && !HasAttachmentDisposition(channel))
|
|
||||||
sniffedType.AssignLiteral(TYPE_MAYBE_FEED);
|
|
||||||
else
|
|
||||||
sniffedType.Truncate();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsFeedSniffer::OnStartRequest(nsIRequest* request, nsISupports* context)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsFeedSniffer::AppendSegmentToString(nsIInputStream* inputStream,
|
|
||||||
void* closure,
|
|
||||||
const char* rawSegment,
|
|
||||||
uint32_t toOffset,
|
|
||||||
uint32_t count,
|
|
||||||
uint32_t* writeCount)
|
|
||||||
{
|
|
||||||
nsCString* decodedData = static_cast<nsCString*>(closure);
|
|
||||||
decodedData->Append(rawSegment, count);
|
|
||||||
*writeCount = count;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsFeedSniffer::OnDataAvailable(nsIRequest* request, nsISupports* context,
|
|
||||||
nsIInputStream* stream, uint64_t offset,
|
|
||||||
uint32_t count)
|
|
||||||
{
|
|
||||||
uint32_t read;
|
|
||||||
return stream->ReadSegments(AppendSegmentToString, &mDecodedData, count,
|
|
||||||
&read);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsFeedSniffer::OnStopRequest(nsIRequest* request, nsISupports* context,
|
|
||||||
nsresult status)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 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/. */
|
|
||||||
|
|
||||||
|
|
||||||
#include "nsIContentSniffer.h"
|
|
||||||
#include "nsIStreamListener.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
#include "mozilla/Attributes.h"
|
|
||||||
|
|
||||||
class nsFeedSniffer final : public nsIContentSniffer,
|
|
||||||
nsIStreamListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSICONTENTSNIFFER
|
|
||||||
NS_DECL_NSIREQUESTOBSERVER
|
|
||||||
NS_DECL_NSISTREAMLISTENER
|
|
||||||
|
|
||||||
static nsresult AppendSegmentToString(nsIInputStream* inputStream,
|
|
||||||
void* closure,
|
|
||||||
const char* rawSegment,
|
|
||||||
uint32_t toOffset,
|
|
||||||
uint32_t count,
|
|
||||||
uint32_t* writeCount);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
~nsFeedSniffer() {}
|
|
||||||
|
|
||||||
nsresult ConvertEncodedData(nsIRequest* request, const uint8_t* data,
|
|
||||||
uint32_t length);
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsCString mDecodedData;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 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/. */
|
|
||||||
|
|
||||||
#include "nsISupports.idl"
|
|
||||||
interface nsIURI;
|
|
||||||
interface nsIRequest;
|
|
||||||
interface nsIFeedResult;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* nsIFeedResultService provides a globally-accessible object for retrieving
|
|
||||||
* the results of feed processing.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(95309fd2-7b3a-47fb-97f3-5c460d9473cd)]
|
|
||||||
interface nsIFeedResultService : nsISupports
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* When set to true, forces the preview page to be displayed, regardless
|
|
||||||
* of the user's preferences.
|
|
||||||
*/
|
|
||||||
attribute boolean forcePreviewPage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a URI to the user's specified external feed handler, or live
|
|
||||||
* bookmarks.
|
|
||||||
* @param uri
|
|
||||||
* The uri of the feed to add.
|
|
||||||
* @param title
|
|
||||||
* The title of the feed to add.
|
|
||||||
* @param subtitle
|
|
||||||
* The subtitle of the feed to add.
|
|
||||||
* @param feedType
|
|
||||||
* The nsIFeed type of the feed. See nsIFeed.idl
|
|
||||||
* @param feedReader
|
|
||||||
* The type of feed reader we're using (client, bookmarks, default)
|
|
||||||
* If this parameter is null, the type is set to default
|
|
||||||
*/
|
|
||||||
void addToClientReader(in AUTF8String uri,
|
|
||||||
in AString title,
|
|
||||||
in AString subtitle,
|
|
||||||
in unsigned long feedType,
|
|
||||||
[optional] in AString feedReader);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a Feed Result object with a globally accessible service
|
|
||||||
* so that it can be accessed by a singleton method outside the usual
|
|
||||||
* flow of control in document loading.
|
|
||||||
*
|
|
||||||
* @param feedResult
|
|
||||||
* An object implementing nsIFeedResult representing the feed.
|
|
||||||
*/
|
|
||||||
void addFeedResult(in nsIFeedResult feedResult);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a Feed Handler object registered using addFeedResult.
|
|
||||||
*
|
|
||||||
* @param uri
|
|
||||||
* The URI of the feed a handler is being requested for
|
|
||||||
*/
|
|
||||||
nsIFeedResult getFeedResult(in nsIURI uri);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregisters a Feed Handler object registered using addFeedResult.
|
|
||||||
* @param uri
|
|
||||||
* The feed URI the handler was registered under. This must be
|
|
||||||
* the same *instance* the feed was registered under.
|
|
||||||
*/
|
|
||||||
void removeFeedResult(in nsIURI uri);
|
|
||||||
};
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
<rss version="2.0">
|
|
||||||
<channel>
|
|
||||||
<title>t</title>
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Content-Type: text/xml
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<rdf:RDF
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns="http://my.netscape.com/rdf/simple/0.9/">
|
|
||||||
<channel>
|
|
||||||
<title>Tinderbox - Firefox</title>
|
|
||||||
<description>Build bustages for Firefox</description>
|
|
||||||
<link>http://tinderbox.mozilla.org/showbuilds.cgi?tree=Firefox</link>
|
|
||||||
</channel>
|
|
||||||
<image>
|
|
||||||
<title>Bad</title>
|
|
||||||
<url>http://tinderbox.mozilla.org/channelflames.gif</url>
|
|
||||||
<link>http://tinderbox.mozilla.org/showbuilds.cgi?tree=Firefox</link>
|
|
||||||
</image>
|
|
||||||
<item><title>The tree is currently closed</title><link>http://tinderbox.mozilla.org/showbuilds.cgi?tree=Firefox</link></item>
|
|
||||||
|
|
||||||
<item><title>MacOSX Darwin 8.8.4 qm-xserve01 dep unit test is in flames</title><link>http://tinderbox.mozilla.org/showbuilds.cgi?tree=Firefox</link></item>
|
|
||||||
</rdf:RDF>
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
||||||
|
|
||||||
<title>Example Feed</title>
|
|
||||||
<link href="http://example.org/"/>
|
|
||||||
<updated>2003-12-13T18:30:02Z</updated>
|
|
||||||
|
|
||||||
<author>
|
|
||||||
<name>John Doe</name>
|
|
||||||
</author>
|
|
||||||
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
|
|
||||||
|
|
||||||
<entry>
|
|
||||||
|
|
||||||
<title>Good item</title>
|
|
||||||
<link href="http://example.org/first"/>
|
|
||||||
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
|
|
||||||
<updated>2003-12-13T18:30:02Z</updated>
|
|
||||||
|
|
||||||
<summary>Some text.</summary>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
<entry>
|
|
||||||
|
|
||||||
<title>data: link</title>
|
|
||||||
<link href="data:text/plain,Hi"/>
|
|
||||||
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6b</id>
|
|
||||||
<updated>2003-12-13T18:30:03Z</updated>
|
|
||||||
|
|
||||||
<summary>Some text.</summary>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
<entry>
|
|
||||||
|
|
||||||
<title>javascript: link</title>
|
|
||||||
<link href="javascript:alert('Hi')"/>
|
|
||||||
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6c</id>
|
|
||||||
<updated>2003-12-13T18:30:04Z</updated>
|
|
||||||
|
|
||||||
<summary>Some text.</summary>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
<entry>
|
|
||||||
|
|
||||||
<title>file: link</title>
|
|
||||||
<link href="file:///var/"/>
|
|
||||||
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6d</id>
|
|
||||||
<updated>2003-12-13T18:30:05Z</updated>
|
|
||||||
|
|
||||||
<summary>Some text.</summary>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
<entry>
|
|
||||||
|
|
||||||
<title>chrome: link</title>
|
|
||||||
<link href="chrome://browser/content/browser.js"/>
|
|
||||||
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6e</id>
|
|
||||||
<updated>2003-12-13T18:30:06Z</updated>
|
|
||||||
|
|
||||||
<summary>Some text.</summary>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
</feed>
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="http://www.example.com/">
|
|
||||||
|
|
||||||
<title type="xhtml" xml:base="/foo/bar/">
|
|
||||||
<div xmlns="http://www.w3.org/1999/xhtml">Example of a <em>special</em> feed (<img height="20px" src="baz.png" alt="base test sprite"/>)</div>
|
|
||||||
</title>
|
|
||||||
|
|
||||||
<subtitle type="html" xml:base="/foo/bar/">
|
|
||||||
<![CDATA[
|
|
||||||
With a <em>special</em> subtitle (<img height="20px" src="baz.png" alt="base test sprite"/>)
|
|
||||||
]]>
|
|
||||||
</subtitle>
|
|
||||||
|
|
||||||
<link href="http://example.org/"/>
|
|
||||||
|
|
||||||
<updated>2010-09-02T18:30:02Z</updated>
|
|
||||||
|
|
||||||
<author>
|
|
||||||
<name>John Doe</name>
|
|
||||||
</author>
|
|
||||||
|
|
||||||
<id>urn:uuid:22906062-ecbd-46e2-b6a7-3039506a398f</id>
|
|
||||||
|
|
||||||
<entry>
|
|
||||||
<title type="xhtml" xml:base="/foo/bar/">
|
|
||||||
<div xmlns="http://www.w3.org/1999/xhtml">Some <abbr title="Extensible Hyper-text Mark-up Language">XHTML</abbr> examples (<img height="20px" src="baz.png" alt="base test sprite"/>)</div>
|
|
||||||
</title>
|
|
||||||
<id>urn:uuid:b48083a7-71a7-4c9c-8515-b7c0d22955e7</id>
|
|
||||||
<updated>2010-09-02T18:30:02Z</updated>
|
|
||||||
<summary>Some text.</summary>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
<entry>
|
|
||||||
<title type="html" xml:base="/foo/bar/">
|
|
||||||
<![CDATA[
|
|
||||||
Some <abbr title="Hyper-text Mark-up Language">HTML</abbr> examples (<img height="20px" src="baz.png" alt="base test sprite"/>)
|
|
||||||
]]>
|
|
||||||
</title>
|
|
||||||
<id>urn:uuid:1424967a-280a-414d-b0ab-8b11c4ac1bb7</id>
|
|
||||||
<updated>2010-09-02T18:30:02Z</updated>
|
|
||||||
<summary>Some text.</summary>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
</feed>
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<rss version="2.0">
|
|
||||||
<channel>
|
|
||||||
<title>Channel title</title>
|
|
||||||
<description>Channel description</description>
|
|
||||||
<link>Channel link</link>
|
|
||||||
<item>
|
|
||||||
<title>Episode 1</title>
|
|
||||||
<enclosure url="http://www.example.com/podcasts/Episode%201" length="0" type="audio/x-m4a" />
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<title>Episode 2</title>
|
|
||||||
<enclosure url="http://www.example.com/podcasts/Episode%20%232" length="0" type="audio/x-m4a" />
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<title>Episode 3</title>
|
|
||||||
<enclosure url="http://www.example.com/podcasts/Episode%20%233/" length="0" type="audio/x-m4a" />
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<title>Episode 4</title>
|
|
||||||
<enclosure url="http://www.example.com/podcasts/Is%20This%20Episode%20%234%3F" length="0" type="audio/x-m4a" />
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
"extends": [
|
|
||||||
"plugin:mozilla/chrome-test"
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
[DEFAULT]
|
|
||||||
prefs =
|
|
||||||
browser.feeds.unsafelyFrameFeeds=true
|
|
||||||
|
|
||||||
support-files = sample_feed.atom
|
|
||||||
!/browser/components/feeds/test/bug408328-data.xml
|
|
||||||
!/browser/components/feeds/test/valid-feed.xml
|
|
||||||
!/browser/components/feeds/test/valid-unsniffable-feed.xml
|
|
||||||
|
|
||||||
[test_bug368464.html]
|
|
||||||
[test_bug408328.html]
|
|
||||||
[test_maxSniffing.html]
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
||||||
|
|
||||||
<title>Example Feed</title>
|
|
||||||
<link href="http://example.org/"/>
|
|
||||||
<updated>2003-12-13T18:30:02Z</updated>
|
|
||||||
|
|
||||||
<author>
|
|
||||||
<name>John Doe</name>
|
|
||||||
</author>
|
|
||||||
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
|
|
||||||
|
|
||||||
<entry>
|
|
||||||
|
|
||||||
<title>Atom-Powered Robots Run Amok</title>
|
|
||||||
<link href="http://example.org/2003/12/13/atom03"/>
|
|
||||||
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
|
|
||||||
<updated>2003-12-13T18:30:02Z</updated>
|
|
||||||
|
|
||||||
<summary>Some text.</summary>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
</feed>
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<!--
|
|
||||||
https://bugzilla.mozilla.org/show_bug.cgi?id=368464
|
|
||||||
-->
|
|
||||||
<head>
|
|
||||||
<title>Test that RSS 0.90 isn't sniffed</title>
|
|
||||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=368464">Mozilla Bug 368464</a>
|
|
||||||
<p id="display"><iframe id="testFrame" src="http://mochi.test:8888/tests/browser/components/feeds/test/bug368464-data.xml"></iframe></p>
|
|
||||||
<div id="content" style="display: none">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<pre id="test">
|
|
||||||
<script class="testbody" type="text/javascript">
|
|
||||||
|
|
||||||
/** Test for Bug 368464 **/
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
|
|
||||||
addLoadEvent(function() {
|
|
||||||
ok($("testFrame").contentDocument.documentElement.id != "feedHandler",
|
|
||||||
"RSS 0.90 shouldn't be sniffed as a feed");
|
|
||||||
});
|
|
||||||
addLoadEvent(SimpleTest.finish);
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<!--
|
|
||||||
https://bugzilla.mozilla.org/show_bug.cgi?id=408328
|
|
||||||
-->
|
|
||||||
<head>
|
|
||||||
<title>Test feed preview safe-linkification</title>
|
|
||||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408328">Mozilla Bug 408328</a>
|
|
||||||
<p id="display"><iframe id="testFrame" src="http://mochi.test:8888/tests/browser/components/feeds/test/bug408328-data.xml"></iframe></p>
|
|
||||||
<div id="content" style="display: none">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<pre id="test">
|
|
||||||
<script class="testbody" type="text/javascript">
|
|
||||||
|
|
||||||
/** Test for Bug 408328 **/
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
|
|
||||||
addLoadEvent(function() {
|
|
||||||
var links = $("testFrame").contentDocument.getElementById("feedContent").getElementsByTagName("a");
|
|
||||||
is(links.length, 5, "wrong number of linked items in feed preview");
|
|
||||||
for (var i = 0; i < links.length; i++) {
|
|
||||||
if (links[i].href)
|
|
||||||
is(links[i].href, "http://example.org/first", "bad linkified item");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
addLoadEvent(SimpleTest.finish);
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<!--
|
|
||||||
https://bugzilla.mozilla.org/show_bug.cgi?id=739040
|
|
||||||
-->
|
|
||||||
<head>
|
|
||||||
<title>Test that we only sniff 512 bytes</title>
|
|
||||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=739040">Mozilla Bug 739040</a>
|
|
||||||
<p id="display">
|
|
||||||
<iframe id="validTestFrame" src="http://mochi.test:8888/tests/browser/components/feeds/test/valid-feed.xml"></iframe>
|
|
||||||
<iframe id="unsniffableTestFrame" src="http://mochi.test:8888/tests/browser/components/feeds/test/valid-unsniffable-feed.xml"></iframe>
|
|
||||||
</p>
|
|
||||||
<div id="content" style="display: none">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<pre id="test">
|
|
||||||
<script class="testbody" type="text/javascript">
|
|
||||||
|
|
||||||
/** Test for Bug 739040 **/
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
|
|
||||||
addLoadEvent(function() {
|
|
||||||
is($("validTestFrame").contentDocument.documentElement.id, "feedHandler",
|
|
||||||
"valid feed should be sniffed");
|
|
||||||
isnot($("unsniffableTestFrame").contentDocument.documentElement.id, "feedHandler",
|
|
||||||
"unsniffable feed should not be sniffed");
|
|
||||||
});
|
|
||||||
addLoadEvent(SimpleTest.finish);
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,20 +1,2 @@
|
||||||
[DEFAULT]
|
|
||||||
prefs =
|
|
||||||
browser.feeds.unsafelyFrameFeeds=true
|
|
||||||
|
|
||||||
support-files =
|
|
||||||
bug368464-data.xml
|
|
||||||
bug408328-data.xml
|
|
||||||
bug436801-data.xml
|
|
||||||
bug494328-data.xml
|
|
||||||
valid-feed.xml
|
|
||||||
valid-unsniffable-feed.xml
|
|
||||||
|
|
||||||
[test_bug364677.html]
|
|
||||||
support-files =
|
|
||||||
bug364677-data.xml
|
|
||||||
bug364677-data.xml^headers^
|
|
||||||
[test_bug436801.html]
|
|
||||||
[test_bug494328.html]
|
|
||||||
[test_registerHandler.html]
|
[test_registerHandler.html]
|
||||||
[test_registerHandler_disabled.html]
|
[test_registerHandler_disabled.html]
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<!--
|
|
||||||
https://bugzilla.mozilla.org/show_bug.cgi?id=364677
|
|
||||||
-->
|
|
||||||
<head>
|
|
||||||
<title>Test for Bug 364677</title>
|
|
||||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=364677">Mozilla Bug 364677</a>
|
|
||||||
<p id="display"><iframe id="testFrame" src="bug364677-data.xml"></iframe></p>
|
|
||||||
<div id="content" style="display: none">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<pre id="test">
|
|
||||||
<script class="testbody" type="text/javascript">
|
|
||||||
|
|
||||||
/** Test for Bug 364677 **/
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
|
|
||||||
addLoadEvent(function() {
|
|
||||||
is(SpecialPowers.wrap($("testFrame")).contentDocument.documentElement.id, "feedHandler",
|
|
||||||
"Feed served as text/xml without a channel/link should have been sniffed");
|
|
||||||
});
|
|
||||||
addLoadEvent(SimpleTest.finish);
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<!--
|
|
||||||
https://bugzilla.mozilla.org/show_bug.cgi?id=436801
|
|
||||||
-->
|
|
||||||
<head>
|
|
||||||
<title>Test feed preview subscribe UI</title>
|
|
||||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=436801">Mozilla Bug 436801</a>
|
|
||||||
<p id="display"><iframe id="testFrame" src="bug436801-data.xml"></iframe></p>
|
|
||||||
<div id="content" style="display: none">
|
|
||||||
</div>
|
|
||||||
<pre id="test">
|
|
||||||
<script class="testbody" type="text/javascript">
|
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
|
|
||||||
addLoadEvent(function() {
|
|
||||||
var doc = SpecialPowers.wrap($("testFrame")).contentDocument;
|
|
||||||
|
|
||||||
checkNode(doc.getElementById("feedTitleText"), [
|
|
||||||
"ELEMENT", "h1", [
|
|
||||||
["TEXT", "Example of a "],
|
|
||||||
["ELEMENT", "em", [
|
|
||||||
["TEXT", "special"],
|
|
||||||
]],
|
|
||||||
["TEXT", " feed ("],
|
|
||||||
["ELEMENT", "img", { "src": "baz.png" }],
|
|
||||||
["TEXT", ")"],
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
checkNode(doc.getElementById("feedSubtitleText"), [
|
|
||||||
"ELEMENT", "h2", [
|
|
||||||
["TEXT", "With a "],
|
|
||||||
["ELEMENT", "em", [
|
|
||||||
["TEXT", "special"],
|
|
||||||
]],
|
|
||||||
["TEXT", " subtitle ("],
|
|
||||||
["ELEMENT", "img", { "src": "baz.png" }],
|
|
||||||
["TEXT", ")"],
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
checkNode(doc.querySelector(".entry").firstChild.firstChild.firstChild, [
|
|
||||||
"ELEMENT", "span", [
|
|
||||||
["TEXT", "Some "],
|
|
||||||
["ELEMENT", "abbr", { title: "Extensible Hyper-text Mark-up Language" }, [
|
|
||||||
["TEXT", "XHTML"],
|
|
||||||
]],
|
|
||||||
["TEXT", " examples ("],
|
|
||||||
["ELEMENT", "img", { "src": "baz.png" }],
|
|
||||||
["TEXT", ")"],
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
checkNode(doc.querySelectorAll(".entry")[1].firstChild.firstChild.firstChild, [
|
|
||||||
"ELEMENT", "span", [
|
|
||||||
["TEXT", "Some "],
|
|
||||||
["ELEMENT", "abbr", { title: "Hyper-text Mark-up Language" }, [
|
|
||||||
["TEXT", "HTML"],
|
|
||||||
]],
|
|
||||||
["TEXT", " examples ("],
|
|
||||||
["ELEMENT", "img", { "src": "baz.png" }],
|
|
||||||
["TEXT", ")"],
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
addLoadEvent(SimpleTest.finish);
|
|
||||||
|
|
||||||
function checkNode(node, schema) {
|
|
||||||
var typeName = schema.shift() + "_NODE";
|
|
||||||
var type = Node[typeName];
|
|
||||||
is(node.nodeType, type, "Node should be expected type " + typeName);
|
|
||||||
if (type == Node.TEXT_NODE) {
|
|
||||||
var text = schema.shift();
|
|
||||||
is(node.data, text, "Text should match");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// type == Node.ELEMENT_NODE
|
|
||||||
var tag = schema.shift();
|
|
||||||
is(node.localName, tag, "Element should have expected tag");
|
|
||||||
while (schema.length) {
|
|
||||||
let val = schema.shift();
|
|
||||||
if (Array.isArray(val))
|
|
||||||
var childSchema = val;
|
|
||||||
else
|
|
||||||
var attrSchema = val;
|
|
||||||
}
|
|
||||||
if (attrSchema) {
|
|
||||||
var nsTable = {
|
|
||||||
xml: "http://www.w3.org/XML/1998/namespace",
|
|
||||||
};
|
|
||||||
for (var name in attrSchema) {
|
|
||||||
var [ns, nsName] = name.split(":");
|
|
||||||
let val = nsName ? node.getAttributeNS(nsTable[ns], nsName) :
|
|
||||||
node.getAttribute(name);
|
|
||||||
is(val, attrSchema[name], "Attribute " + name + " should match");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (childSchema) {
|
|
||||||
var numChildren = node.childNodes.length;
|
|
||||||
is(childSchema.length, numChildren,
|
|
||||||
"Element should have expected number of children");
|
|
||||||
for (var i = 0; i < numChildren; i++)
|
|
||||||
checkNode(node.childNodes[i], childSchema[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<!--
|
|
||||||
https://bugzilla.mozilla.org/show_bug.cgi?id=494328
|
|
||||||
-->
|
|
||||||
<head>
|
|
||||||
<title>Test for bug 494328</title>
|
|
||||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=494328">Mozilla Bug 494328</a>
|
|
||||||
<p id="display"><iframe id="testFrame" src="bug494328-data.xml"></iframe></p>
|
|
||||||
<div id="content" style="display: none">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<pre id="test">
|
|
||||||
<script class="testbody" type="text/javascript">
|
|
||||||
|
|
||||||
/** Test for Bug 494328 **/
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
|
|
||||||
addLoadEvent(function() {
|
|
||||||
var links = SpecialPowers.wrap($("testFrame")).contentDocument.getElementById("feedContent").querySelectorAll("div.enclosure > a");
|
|
||||||
is(links[0].textContent, "Episode 1", "filename decoded incorrectly");
|
|
||||||
is(links[1].textContent, "Episode #2", "filename decoded incorrectly");
|
|
||||||
is(links[2].textContent, "http://www.example.com/podcasts/Episode #3/", "filename decoded incorrectly");
|
|
||||||
is(links[3].textContent, "Is This Episode #4?", "filename decoded incorrectly");
|
|
||||||
});
|
|
||||||
addLoadEvent(SimpleTest.finish);
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
||||||
|
|
||||||
<title>Example Feed</title>
|
|
||||||
<link href="http://example.org/"/>
|
|
||||||
<updated>2010-08-22T18:30:02Z</updated>
|
|
||||||
|
|
||||||
<author>
|
|
||||||
<name>John Doe</name>
|
|
||||||
</author>
|
|
||||||
<id>urn:uuid:e2df8375-99be-4848-b05e-b9d407555267</id>
|
|
||||||
|
|
||||||
<entry>
|
|
||||||
|
|
||||||
<title>Item</title>
|
|
||||||
<link href="http://example.org/first"/>
|
|
||||||
<id>urn:uuid:9e0f4bed-33d3-4a9d-97ab-ecaa31b3f14a</id>
|
|
||||||
<updated>2010-08-22T18:30:02Z</updated>
|
|
||||||
|
|
||||||
<summary>Some text.</summary>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
</feed>
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 512 bytes!
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
-->
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
||||||
|
|
||||||
<title>Example Feed</title>
|
|
||||||
<link href="http://example.org/"/>
|
|
||||||
<updated>2010-08-22T18:30:02Z</updated>
|
|
||||||
|
|
||||||
<author>
|
|
||||||
<name>John Doe</name>
|
|
||||||
</author>
|
|
||||||
<id>urn:uuid:e2df8375-99be-4848-b05e-b9d407555267</id>
|
|
||||||
|
|
||||||
<entry>
|
|
||||||
|
|
||||||
<title>Item</title>
|
|
||||||
<link href="http://example.org/first"/>
|
|
||||||
<id>urn:uuid:9e0f4bed-33d3-4a9d-97ab-ecaa31b3f14a</id>
|
|
||||||
<updated>2010-08-22T18:30:02Z</updated>
|
|
||||||
|
|
||||||
<summary>Some text.</summary>
|
|
||||||
</entry>
|
|
||||||
|
|
||||||
</feed>
|
|
||||||
|
|
@ -500,7 +500,6 @@ const listeners = {
|
||||||
"AsyncPrefs:ResetPref": ["AsyncPrefs"],
|
"AsyncPrefs:ResetPref": ["AsyncPrefs"],
|
||||||
// PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN AsyncPrefs.init
|
// PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN AsyncPrefs.init
|
||||||
|
|
||||||
"FeedConverter:addLiveBookmark": ["Feeds"],
|
|
||||||
"webrtc:UpdateGlobalIndicators": ["webrtcUI"],
|
"webrtc:UpdateGlobalIndicators": ["webrtcUI"],
|
||||||
"webrtc:UpdatingIndicators": ["webrtcUI"],
|
"webrtc:UpdatingIndicators": ["webrtcUI"],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,7 @@ var gAppManagerDialog = {
|
||||||
window);
|
window);
|
||||||
|
|
||||||
const appDescElem = document.getElementById("appDescription");
|
const appDescElem = document.getElementById("appDescription");
|
||||||
if (this.handlerInfo.type == TYPE_MAYBE_FEED) {
|
if (this.handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) {
|
||||||
document.l10n.setAttributes(appDescElem, "app-manager-handle-webfeeds");
|
|
||||||
} else if (this.handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) {
|
|
||||||
document.l10n.setAttributes(appDescElem, "app-manager-handle-file", {
|
document.l10n.setAttributes(appDescElem, "app-manager-handle-file", {
|
||||||
type: this.handlerInfo.typeDescription,
|
type: this.handlerInfo.typeDescription,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,6 @@ XPCOMUtils.defineLazyServiceGetters(this, {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Constants & Enumeration Values
|
// Constants & Enumeration Values
|
||||||
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
|
|
||||||
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
|
|
||||||
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
|
|
||||||
const TYPE_PDF = "application/pdf";
|
const TYPE_PDF = "application/pdf";
|
||||||
|
|
||||||
const PREF_PDFJS_DISABLED = "pdfjs.disabled";
|
const PREF_PDFJS_DISABLED = "pdfjs.disabled";
|
||||||
|
|
@ -46,38 +43,6 @@ const PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS =
|
||||||
// Strings to identify ExtensionSettingsStore overrides
|
// Strings to identify ExtensionSettingsStore overrides
|
||||||
const CONTAINERS_KEY = "privacy.containers";
|
const CONTAINERS_KEY = "privacy.containers";
|
||||||
|
|
||||||
/*
|
|
||||||
* Preferences where we store handling information about the feed type.
|
|
||||||
*
|
|
||||||
* browser.feeds.handler
|
|
||||||
* - "bookmarks", "reader" (clarified further using the .default preference),
|
|
||||||
* or "ask" -- indicates the default handler being used to process feeds;
|
|
||||||
* "bookmarks" is obsolete; to specify that the handler is bookmarks,
|
|
||||||
* set browser.feeds.handler.default to "bookmarks";
|
|
||||||
*
|
|
||||||
* browser.feeds.handler.default
|
|
||||||
* - "bookmarks" or "client" -- indicates the chosen feed reader used
|
|
||||||
* to display feeds, either transiently (i.e., when the "use as default"
|
|
||||||
* checkbox is unchecked, corresponds to when browser.feeds.handler=="ask")
|
|
||||||
* or more permanently (i.e., the item displayed in the dropdown in Feeds
|
|
||||||
* preferences)
|
|
||||||
*
|
|
||||||
* browser.feeds.handlers.application
|
|
||||||
* - nsIFile, stores the current client-side feed reading app if one has
|
|
||||||
* been chosen
|
|
||||||
*/
|
|
||||||
const PREF_FEED_SELECTED_APP = "browser.feeds.handlers.application";
|
|
||||||
const PREF_FEED_SELECTED_ACTION = "browser.feeds.handler";
|
|
||||||
const PREF_FEED_SELECTED_READER = "browser.feeds.handler.default";
|
|
||||||
|
|
||||||
const PREF_VIDEO_FEED_SELECTED_APP = "browser.videoFeeds.handlers.application";
|
|
||||||
const PREF_VIDEO_FEED_SELECTED_ACTION = "browser.videoFeeds.handler";
|
|
||||||
const PREF_VIDEO_FEED_SELECTED_READER = "browser.videoFeeds.handler.default";
|
|
||||||
|
|
||||||
const PREF_AUDIO_FEED_SELECTED_APP = "browser.audioFeeds.handlers.application";
|
|
||||||
const PREF_AUDIO_FEED_SELECTED_ACTION = "browser.audioFeeds.handler";
|
|
||||||
const PREF_AUDIO_FEED_SELECTED_READER = "browser.audioFeeds.handler.default";
|
|
||||||
|
|
||||||
// The nsHandlerInfoAction enumeration values in nsIHandlerInfo identify
|
// The nsHandlerInfoAction enumeration values in nsIHandlerInfo identify
|
||||||
// the actions the application can take with content of various types.
|
// the actions the application can take with content of various types.
|
||||||
// But since nsIHandlerInfo doesn't support plugins, there's no value
|
// But since nsIHandlerInfo doesn't support plugins, there's no value
|
||||||
|
|
@ -88,7 +53,7 @@ const ICON_URL_APP = AppConstants.platform == "linux" ?
|
||||||
"moz-icon://dummy.exe?size=16" :
|
"moz-icon://dummy.exe?size=16" :
|
||||||
"chrome://browser/skin/preferences/application.png";
|
"chrome://browser/skin/preferences/application.png";
|
||||||
|
|
||||||
// For CSS. Can be one of "ask", "save", "plugin" or "feed". If absent, the icon URL
|
// For CSS. Can be one of "ask", "save" or "plugin". If absent, the icon URL
|
||||||
// was set by us to a custom handler icon and CSS should not try to override it.
|
// was set by us to a custom handler icon and CSS should not try to override it.
|
||||||
const APP_ICON_ATTR_NAME = "appHandlerIcon";
|
const APP_ICON_ATTR_NAME = "appHandlerIcon";
|
||||||
|
|
||||||
|
|
@ -179,18 +144,6 @@ Preferences.addAll([
|
||||||
{ id: "layers.acceleration.disabled", type: "bool", inverted: true },
|
{ id: "layers.acceleration.disabled", type: "bool", inverted: true },
|
||||||
|
|
||||||
// Files and Applications
|
// Files and Applications
|
||||||
{ id: "browser.feeds.handler", type: "string" },
|
|
||||||
{ id: "browser.feeds.handler.default", type: "string" },
|
|
||||||
{ id: "browser.feeds.handlers.application", type: "file" },
|
|
||||||
|
|
||||||
{ id: "browser.videoFeeds.handler", type: "string" },
|
|
||||||
{ id: "browser.videoFeeds.handler.default", type: "string" },
|
|
||||||
{ id: "browser.videoFeeds.handlers.application", type: "file" },
|
|
||||||
|
|
||||||
{ id: "browser.audioFeeds.handler", type: "string" },
|
|
||||||
{ id: "browser.audioFeeds.handler.default", type: "string" },
|
|
||||||
{ id: "browser.audioFeeds.handlers.application", type: "file" },
|
|
||||||
|
|
||||||
{ id: "pref.downloads.disable_button.edit_actions", type: "bool" },
|
{ id: "pref.downloads.disable_button.edit_actions", type: "bool" },
|
||||||
|
|
||||||
// DRM content
|
// DRM content
|
||||||
|
|
@ -549,17 +502,6 @@ var gMainPane = {
|
||||||
// the view when they change.
|
// the view when they change.
|
||||||
Services.prefs.addObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
|
Services.prefs.addObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
|
||||||
Services.prefs.addObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
|
Services.prefs.addObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
|
||||||
Services.prefs.addObserver(PREF_FEED_SELECTED_APP, this);
|
|
||||||
Services.prefs.addObserver(PREF_FEED_SELECTED_ACTION, this);
|
|
||||||
Services.prefs.addObserver(PREF_FEED_SELECTED_READER, this);
|
|
||||||
|
|
||||||
Services.prefs.addObserver(PREF_VIDEO_FEED_SELECTED_APP, this);
|
|
||||||
Services.prefs.addObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this);
|
|
||||||
Services.prefs.addObserver(PREF_VIDEO_FEED_SELECTED_READER, this);
|
|
||||||
|
|
||||||
Services.prefs.addObserver(PREF_AUDIO_FEED_SELECTED_APP, this);
|
|
||||||
Services.prefs.addObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this);
|
|
||||||
Services.prefs.addObserver(PREF_AUDIO_FEED_SELECTED_READER, this);
|
|
||||||
|
|
||||||
setEventListener("filter", "command", gMainPane.filter);
|
setEventListener("filter", "command", gMainPane.filter);
|
||||||
setEventListener("typeColumn", "click", gMainPane.sort);
|
setEventListener("typeColumn", "click", gMainPane.sort);
|
||||||
|
|
@ -1333,17 +1275,6 @@ var gMainPane = {
|
||||||
window.removeEventListener("unload", this);
|
window.removeEventListener("unload", this);
|
||||||
Services.prefs.removeObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
|
Services.prefs.removeObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
|
||||||
Services.prefs.removeObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
|
Services.prefs.removeObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
|
||||||
Services.prefs.removeObserver(PREF_FEED_SELECTED_APP, this);
|
|
||||||
Services.prefs.removeObserver(PREF_FEED_SELECTED_ACTION, this);
|
|
||||||
Services.prefs.removeObserver(PREF_FEED_SELECTED_READER, this);
|
|
||||||
|
|
||||||
Services.prefs.removeObserver(PREF_VIDEO_FEED_SELECTED_APP, this);
|
|
||||||
Services.prefs.removeObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this);
|
|
||||||
Services.prefs.removeObserver(PREF_VIDEO_FEED_SELECTED_READER, this);
|
|
||||||
|
|
||||||
Services.prefs.removeObserver(PREF_AUDIO_FEED_SELECTED_APP, this);
|
|
||||||
Services.prefs.removeObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this);
|
|
||||||
Services.prefs.removeObserver(PREF_AUDIO_FEED_SELECTED_READER, this);
|
|
||||||
|
|
||||||
Services.prefs.removeObserver(PREF_CONTAINERS_EXTENSION, this);
|
Services.prefs.removeObserver(PREF_CONTAINERS_EXTENSION, this);
|
||||||
},
|
},
|
||||||
|
|
@ -1392,23 +1323,11 @@ var gMainPane = {
|
||||||
// Composed Model Construction
|
// Composed Model Construction
|
||||||
|
|
||||||
_loadData() {
|
_loadData() {
|
||||||
this._loadFeedHandler();
|
|
||||||
this._loadInternalHandlers();
|
this._loadInternalHandlers();
|
||||||
this._loadPluginHandlers();
|
this._loadPluginHandlers();
|
||||||
this._loadApplicationHandlers();
|
this._loadApplicationHandlers();
|
||||||
},
|
},
|
||||||
|
|
||||||
_loadFeedHandler() {
|
|
||||||
this._handledTypes[TYPE_MAYBE_FEED] = feedHandlerInfo;
|
|
||||||
feedHandlerInfo.handledOnlyByPlugin = false;
|
|
||||||
|
|
||||||
this._handledTypes[TYPE_MAYBE_VIDEO_FEED] = videoFeedHandlerInfo;
|
|
||||||
videoFeedHandlerInfo.handledOnlyByPlugin = false;
|
|
||||||
|
|
||||||
this._handledTypes[TYPE_MAYBE_AUDIO_FEED] = audioFeedHandlerInfo;
|
|
||||||
audioFeedHandlerInfo.handledOnlyByPlugin = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load higher level internal handlers so they can be turned on/off in the
|
* Load higher level internal handlers so they can be turned on/off in the
|
||||||
* applications menu.
|
* applications menu.
|
||||||
|
|
@ -1675,12 +1594,7 @@ var gMainPane = {
|
||||||
{
|
{
|
||||||
var askMenuItem = document.createXULElement("menuitem");
|
var askMenuItem = document.createXULElement("menuitem");
|
||||||
askMenuItem.setAttribute("action", Ci.nsIHandlerInfo.alwaysAsk);
|
askMenuItem.setAttribute("action", Ci.nsIHandlerInfo.alwaysAsk);
|
||||||
let label;
|
let label = gMainPane._prefsBundle.getString("alwaysAsk");
|
||||||
if (isFeedType(handlerInfo.type))
|
|
||||||
label = gMainPane._prefsBundle.getFormattedString("previewInApp",
|
|
||||||
[this._brandShortName]);
|
|
||||||
else
|
|
||||||
label = gMainPane._prefsBundle.getString("alwaysAsk");
|
|
||||||
askMenuItem.setAttribute("label", label);
|
askMenuItem.setAttribute("label", label);
|
||||||
askMenuItem.setAttribute("tooltiptext", label);
|
askMenuItem.setAttribute("tooltiptext", label);
|
||||||
askMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
|
askMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
|
||||||
|
|
@ -1689,10 +1603,8 @@ var gMainPane = {
|
||||||
|
|
||||||
// Create a menu item for saving to disk.
|
// Create a menu item for saving to disk.
|
||||||
// Note: this option isn't available to protocol types, since we don't know
|
// Note: this option isn't available to protocol types, since we don't know
|
||||||
// what it means to save a URL having a certain scheme to disk, nor is it
|
// what it means to save a URL having a certain scheme to disk.
|
||||||
// available to feeds, since the feed code doesn't implement the capability.
|
if ((handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo)) {
|
||||||
if ((handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) &&
|
|
||||||
!isFeedType(handlerInfo.type)) {
|
|
||||||
var saveMenuItem = document.createXULElement("menuitem");
|
var saveMenuItem = document.createXULElement("menuitem");
|
||||||
saveMenuItem.setAttribute("action", Ci.nsIHandlerInfo.saveToDisk);
|
saveMenuItem.setAttribute("action", Ci.nsIHandlerInfo.saveToDisk);
|
||||||
let label = gMainPane._prefsBundle.getString("saveFile");
|
let label = gMainPane._prefsBundle.getString("saveFile");
|
||||||
|
|
@ -1702,18 +1614,6 @@ var gMainPane = {
|
||||||
menuPopup.appendChild(saveMenuItem);
|
menuPopup.appendChild(saveMenuItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is the feed type, add a Live Bookmarks item.
|
|
||||||
if (isFeedType(handlerInfo.type)) {
|
|
||||||
internalMenuItem = document.createXULElement("menuitem");
|
|
||||||
internalMenuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
|
|
||||||
let label = gMainPane._prefsBundle.getFormattedString("addLiveBookmarksInApp",
|
|
||||||
[this._brandShortName]);
|
|
||||||
internalMenuItem.setAttribute("label", label);
|
|
||||||
internalMenuItem.setAttribute("tooltiptext", label);
|
|
||||||
internalMenuItem.setAttribute(APP_ICON_ATTR_NAME, "feed");
|
|
||||||
menuPopup.appendChild(internalMenuItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a separator to distinguish these items from the helper app items
|
// Add a separator to distinguish these items from the helper app items
|
||||||
// that follow them.
|
// that follow them.
|
||||||
let menuseparator = document.createXULElement("menuseparator");
|
let menuseparator = document.createXULElement("menuseparator");
|
||||||
|
|
@ -1950,10 +1850,11 @@ var gMainPane = {
|
||||||
|
|
||||||
// Whether or not we are currently storing the action selected by the user.
|
// Whether or not we are currently storing the action selected by the user.
|
||||||
// We use this to suppress notification-triggered updates to the list when
|
// We use this to suppress notification-triggered updates to the list when
|
||||||
// we make changes that may spawn such updates, specifically when we change
|
// we make changes that may spawn such updates.
|
||||||
// the action for the feed type, which results in feed preference updates,
|
// XXXgijs: this was definitely necessary when we changed feed preferences
|
||||||
// which spawn "pref changed" notifications that would otherwise cause us
|
// from within _storeAction and its calltree. Now, it may still be
|
||||||
// to rebuild the view unnecessarily.
|
// necessary, either to avoid calling _rebuildView or to avoid the plugin-
|
||||||
|
// related prefs change code. bug 1499350 has more details.
|
||||||
_storingAction: false,
|
_storingAction: false,
|
||||||
|
|
||||||
onSelectAction(aActionItem) {
|
onSelectAction(aActionItem) {
|
||||||
|
|
@ -2058,14 +1959,7 @@ var gMainPane = {
|
||||||
var params = {};
|
var params = {};
|
||||||
var handlerInfo = this.selectedHandlerListItem.handlerInfoWrapper;
|
var handlerInfo = this.selectedHandlerListItem.handlerInfoWrapper;
|
||||||
|
|
||||||
if (isFeedType(handlerInfo.type)) {
|
params.mimeInfo = handlerInfo.wrappedHandlerInfo;
|
||||||
// MIME info will be null, create a temp object.
|
|
||||||
params.mimeInfo = gMIMEService.getFromTypeAndExtension(handlerInfo.type,
|
|
||||||
handlerInfo.primaryExtension);
|
|
||||||
} else {
|
|
||||||
params.mimeInfo = handlerInfo.wrappedHandlerInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
params.title = gMainPane._prefsBundle.getString("fpTitleChooseApp");
|
params.title = gMainPane._prefsBundle.getString("fpTitleChooseApp");
|
||||||
params.description = handlerInfo.description;
|
params.description = handlerInfo.description;
|
||||||
params.filename = null;
|
params.filename = null;
|
||||||
|
|
@ -2454,10 +2348,6 @@ function getLocalHandlerApp(aFile) {
|
||||||
return localHandlerApp;
|
return localHandlerApp;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isFeedType(t) {
|
|
||||||
return t == TYPE_MAYBE_FEED || t == TYPE_MAYBE_VIDEO_FEED || t == TYPE_MAYBE_AUDIO_FEED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
let gHandlerListItemFragment = MozXULElement.parseXULToFragment(`
|
let gHandlerListItemFragment = MozXULElement.parseXULToFragment(`
|
||||||
<richlistitem>
|
<richlistitem>
|
||||||
|
|
@ -2618,12 +2508,8 @@ class HandlerInfoWrapper {
|
||||||
*/
|
*/
|
||||||
get actionDescription() {
|
get actionDescription() {
|
||||||
// alwaysAskBeforeHandling overrides the preferred action, so if that flag
|
// alwaysAskBeforeHandling overrides the preferred action, so if that flag
|
||||||
// is set, then describe that behavior instead. For most types, this is
|
// is set, then describe that behavior instead.
|
||||||
// the "alwaysAsk" string, but for the feed type we show something special.
|
|
||||||
if (this.alwaysAskBeforeHandling) {
|
if (this.alwaysAskBeforeHandling) {
|
||||||
if (isFeedType(this.type))
|
|
||||||
return gMainPane._prefsBundle.getFormattedString("previewInApp",
|
|
||||||
[gMainPane._brandShortName]);
|
|
||||||
return gMainPane._prefsBundle.getString("alwaysAsk");
|
return gMainPane._prefsBundle.getString("alwaysAsk");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2641,12 +2527,6 @@ class HandlerInfoWrapper {
|
||||||
return gMainPane._prefsBundle.getFormattedString("useApp", [name]);
|
return gMainPane._prefsBundle.getFormattedString("useApp", [name]);
|
||||||
|
|
||||||
case Ci.nsIHandlerInfo.handleInternally:
|
case Ci.nsIHandlerInfo.handleInternally:
|
||||||
// For the feed type, handleInternally means live bookmarks.
|
|
||||||
if (isFeedType(this.type)) {
|
|
||||||
return gMainPane._prefsBundle.getFormattedString("addLiveBookmarksInApp",
|
|
||||||
[gMainPane._brandShortName]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this instanceof InternalHandlerInfoWrapper) {
|
if (this instanceof InternalHandlerInfoWrapper) {
|
||||||
return gMainPane._prefsBundle.getFormattedString("previewInApp",
|
return gMainPane._prefsBundle.getFormattedString("previewInApp",
|
||||||
[gMainPane._brandShortName]);
|
[gMainPane._brandShortName]);
|
||||||
|
|
@ -2688,9 +2568,7 @@ class HandlerInfoWrapper {
|
||||||
return "save";
|
return "save";
|
||||||
|
|
||||||
case Ci.nsIHandlerInfo.handleInternally:
|
case Ci.nsIHandlerInfo.handleInternally:
|
||||||
if (isFeedType(this.type)) {
|
if (this instanceof InternalHandlerInfoWrapper) {
|
||||||
return "feed";
|
|
||||||
} else if (this instanceof InternalHandlerInfoWrapper) {
|
|
||||||
return "ask";
|
return "ask";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2944,269 +2822,6 @@ class HandlerInfoWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This object implements nsIHandlerInfo for the feed types. It's a separate
|
|
||||||
* object because we currently store handling information for the feed type
|
|
||||||
* in a set of preferences rather than the nsIHandlerService-managed datastore.
|
|
||||||
*
|
|
||||||
* This object inherits from HandlerInfoWrapper in order to get functionality
|
|
||||||
* that isn't special to the feed type.
|
|
||||||
*/
|
|
||||||
class FeedHandlerInfo extends HandlerInfoWrapper {
|
|
||||||
constructor(aMIMEType, properties) {
|
|
||||||
super(aMIMEType, null);
|
|
||||||
Object.assign(this, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
get description() {
|
|
||||||
return gMainPane._prefsBundle.getString(this._appPrefLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
get preferredApplicationHandler() {
|
|
||||||
switch (Preferences.get(this._prefSelectedReader).value) {
|
|
||||||
case "client":
|
|
||||||
var file = Preferences.get(this._prefSelectedApp).value;
|
|
||||||
if (file)
|
|
||||||
return getLocalHandlerApp(file);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
|
|
||||||
case "bookmarks":
|
|
||||||
default:
|
|
||||||
// When the pref is set to bookmarks, we handle feeds internally,
|
|
||||||
// we don't forward them to a local or web handler app, so there is
|
|
||||||
// no preferred handler.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set preferredApplicationHandler(aNewValue) {
|
|
||||||
if (aNewValue instanceof Ci.nsILocalHandlerApp) {
|
|
||||||
Preferences.get(this._prefSelectedApp).value = aNewValue.executable;
|
|
||||||
Preferences.get(this._prefSelectedReader).value = "client";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get possibleApplicationHandlers() {
|
|
||||||
if (this._possibleApplicationHandlers)
|
|
||||||
return this._possibleApplicationHandlers;
|
|
||||||
|
|
||||||
// A minimal implementation of nsIMutableArray. It only supports the two
|
|
||||||
// methods its callers invoke, namely appendElement and nsIArray::enumerate.
|
|
||||||
this._possibleApplicationHandlers = {
|
|
||||||
_inner: [],
|
|
||||||
_removed: [],
|
|
||||||
|
|
||||||
QueryInterface: ChromeUtils.generateQI(["nsIMutableArray", "nsIArray"]),
|
|
||||||
|
|
||||||
get length() {
|
|
||||||
return this._inner.length;
|
|
||||||
},
|
|
||||||
|
|
||||||
enumerate() {
|
|
||||||
return this._inner.values();
|
|
||||||
},
|
|
||||||
|
|
||||||
appendElement(aHandlerApp, aWeak) {
|
|
||||||
this._inner.push(aHandlerApp);
|
|
||||||
},
|
|
||||||
|
|
||||||
removeElementAt(aIndex) {
|
|
||||||
this._removed.push(this._inner[aIndex]);
|
|
||||||
this._inner.splice(aIndex, 1);
|
|
||||||
},
|
|
||||||
|
|
||||||
queryElementAt(aIndex, aInterface) {
|
|
||||||
return this._inner[aIndex].QueryInterface(aInterface);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add the selected local app if it's different from the OS default handler.
|
|
||||||
// Unlike for other types, we can store only one local app at a time for the
|
|
||||||
// feed type, since we store it in a preference that historically stores
|
|
||||||
// only a single path. But we display all the local apps the user chooses
|
|
||||||
// while the prefpane is open, only dropping the list when the user closes
|
|
||||||
// the prefpane, for maximum usability and consistency with other types.
|
|
||||||
var preferredAppFile = Preferences.get(this._prefSelectedApp).value;
|
|
||||||
if (preferredAppFile) {
|
|
||||||
let preferredApp = getLocalHandlerApp(preferredAppFile);
|
|
||||||
let defaultApp = this._defaultApplicationHandler;
|
|
||||||
if (!defaultApp || !defaultApp.equals(preferredApp))
|
|
||||||
this._possibleApplicationHandlers.appendElement(preferredApp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._possibleApplicationHandlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
get _defaultApplicationHandler() {
|
|
||||||
if (typeof this.__defaultApplicationHandler != "undefined")
|
|
||||||
return this.__defaultApplicationHandler;
|
|
||||||
|
|
||||||
var defaultFeedReader = null;
|
|
||||||
if (AppConstants.HAVE_SHELL_SERVICE) {
|
|
||||||
try {
|
|
||||||
defaultFeedReader = getShellService().defaultFeedReader;
|
|
||||||
} catch (ex) {
|
|
||||||
// no default reader or getShellService() is null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defaultFeedReader) {
|
|
||||||
let handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
|
|
||||||
createInstance(Ci.nsIHandlerApp);
|
|
||||||
handlerApp.name = getFileDisplayName(defaultFeedReader);
|
|
||||||
handlerApp.QueryInterface(Ci.nsILocalHandlerApp);
|
|
||||||
handlerApp.executable = defaultFeedReader;
|
|
||||||
|
|
||||||
this.__defaultApplicationHandler = handlerApp;
|
|
||||||
} else {
|
|
||||||
this.__defaultApplicationHandler = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.__defaultApplicationHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
get hasDefaultHandler() {
|
|
||||||
if (AppConstants.HAVE_SHELL_SERVICE) {
|
|
||||||
try {
|
|
||||||
if (getShellService().defaultFeedReader)
|
|
||||||
return true;
|
|
||||||
} catch (ex) {
|
|
||||||
// no default reader or getShellService() is null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
get defaultDescription() {
|
|
||||||
if (this.hasDefaultHandler)
|
|
||||||
return this._defaultApplicationHandler.name;
|
|
||||||
|
|
||||||
// Should we instead return null?
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// What to do with content of this type.
|
|
||||||
get preferredAction() {
|
|
||||||
switch (Preferences.get(this._prefSelectedAction).value) {
|
|
||||||
|
|
||||||
case "bookmarks":
|
|
||||||
return Ci.nsIHandlerInfo.handleInternally;
|
|
||||||
|
|
||||||
case "reader": {
|
|
||||||
let preferredApp = this.preferredApplicationHandler;
|
|
||||||
let defaultApp = this._defaultApplicationHandler;
|
|
||||||
|
|
||||||
// If we have a valid preferred app, return useSystemDefault if it's
|
|
||||||
// the default app; otherwise return useHelperApp.
|
|
||||||
if (gMainPane.isValidHandlerApp(preferredApp)) {
|
|
||||||
if (defaultApp && defaultApp.equals(preferredApp))
|
|
||||||
return Ci.nsIHandlerInfo.useSystemDefault;
|
|
||||||
|
|
||||||
return Ci.nsIHandlerInfo.useHelperApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The pref is set to "reader", but we don't have a valid preferred app.
|
|
||||||
// What do we do now? Not sure this is the best option (perhaps we
|
|
||||||
// should direct the user to the default app, if any), but for now let's
|
|
||||||
// direct the user to live bookmarks.
|
|
||||||
return Ci.nsIHandlerInfo.handleInternally;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the action is "ask", then alwaysAskBeforeHandling will override
|
|
||||||
// the action, so it doesn't matter what we say it is, it just has to be
|
|
||||||
// something that doesn't cause the controller to hide the type.
|
|
||||||
case "ask":
|
|
||||||
default:
|
|
||||||
return Ci.nsIHandlerInfo.handleInternally;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set preferredAction(aNewValue) {
|
|
||||||
switch (aNewValue) {
|
|
||||||
|
|
||||||
case Ci.nsIHandlerInfo.handleInternally:
|
|
||||||
Preferences.get(this._prefSelectedReader).value = "bookmarks";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Ci.nsIHandlerInfo.useHelperApp:
|
|
||||||
Preferences.get(this._prefSelectedAction).value = "reader";
|
|
||||||
// The controller has already set preferredApplicationHandler
|
|
||||||
// to the new helper app.
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Ci.nsIHandlerInfo.useSystemDefault:
|
|
||||||
Preferences.get(this._prefSelectedAction).value = "reader";
|
|
||||||
this.preferredApplicationHandler = this._defaultApplicationHandler;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get alwaysAskBeforeHandling() {
|
|
||||||
return Preferences.get(this._prefSelectedAction).value == "ask";
|
|
||||||
}
|
|
||||||
|
|
||||||
set alwaysAskBeforeHandling(aNewValue) {
|
|
||||||
if (aNewValue)
|
|
||||||
Preferences.get(this._prefSelectedAction).value = "ask";
|
|
||||||
else
|
|
||||||
Preferences.get(this._prefSelectedAction).value = "reader";
|
|
||||||
}
|
|
||||||
|
|
||||||
get primaryExtension() {
|
|
||||||
return "xml";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Changes to the preferred action and handler take effect immediately
|
|
||||||
// (we write them out to the preferences right as they happen),
|
|
||||||
// so we when the controller calls store() after modifying the handlers,
|
|
||||||
// the only thing we need to store is the removal of possible handlers
|
|
||||||
// XXX Should we hold off on making the changes until this method gets called?
|
|
||||||
store() {
|
|
||||||
for (let app of this._possibleApplicationHandlers._removed) {
|
|
||||||
if (app instanceof Ci.nsILocalHandlerApp) {
|
|
||||||
let pref = Preferences.get(PREF_FEED_SELECTED_APP);
|
|
||||||
var preferredAppFile = pref.value;
|
|
||||||
if (preferredAppFile) {
|
|
||||||
let preferredApp = getLocalHandlerApp(preferredAppFile);
|
|
||||||
if (app.equals(preferredApp))
|
|
||||||
pref.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._possibleApplicationHandlers._removed = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
get smallIcon() {
|
|
||||||
return this._smallIcon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var feedHandlerInfo = new FeedHandlerInfo(TYPE_MAYBE_FEED, {
|
|
||||||
_prefSelectedApp: PREF_FEED_SELECTED_APP,
|
|
||||||
_prefSelectedAction: PREF_FEED_SELECTED_ACTION,
|
|
||||||
_prefSelectedReader: PREF_FEED_SELECTED_READER,
|
|
||||||
_smallIcon: "chrome://browser/skin/feeds/feedIcon16.png",
|
|
||||||
_appPrefLabel: "webFeed",
|
|
||||||
});
|
|
||||||
|
|
||||||
var videoFeedHandlerInfo = new FeedHandlerInfo(TYPE_MAYBE_VIDEO_FEED, {
|
|
||||||
_prefSelectedApp: PREF_VIDEO_FEED_SELECTED_APP,
|
|
||||||
_prefSelectedAction: PREF_VIDEO_FEED_SELECTED_ACTION,
|
|
||||||
_prefSelectedReader: PREF_VIDEO_FEED_SELECTED_READER,
|
|
||||||
_smallIcon: "chrome://browser/skin/feeds/videoFeedIcon16.png",
|
|
||||||
_appPrefLabel: "videoPodcastFeed",
|
|
||||||
});
|
|
||||||
|
|
||||||
var audioFeedHandlerInfo = new FeedHandlerInfo(TYPE_MAYBE_AUDIO_FEED, {
|
|
||||||
_prefSelectedApp: PREF_AUDIO_FEED_SELECTED_APP,
|
|
||||||
_prefSelectedAction: PREF_AUDIO_FEED_SELECTED_ACTION,
|
|
||||||
_prefSelectedReader: PREF_AUDIO_FEED_SELECTED_READER,
|
|
||||||
_smallIcon: "chrome://browser/skin/feeds/audioFeedIcon16.png",
|
|
||||||
_appPrefLabel: "audioPodcastFeed",
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InternalHandlerInfoWrapper provides a basic mechanism to create an internal
|
* InternalHandlerInfoWrapper provides a basic mechanism to create an internal
|
||||||
* mime type handler that can be enabled/disabled in the applications preference
|
* mime type handler that can be enabled/disabled in the applications preference
|
||||||
|
|
|
||||||
|
|
@ -684,9 +684,3 @@ nsGNOMEShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACStr
|
||||||
const char* specStr = spec.get();
|
const char* specStr = spec.get();
|
||||||
return process->Run(false, &specStr, 1);
|
return process->Run(false, &specStr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsGNOMEShellService::GetDefaultFeedReader(nsIFile** _retval)
|
|
||||||
{
|
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -92,9 +92,4 @@ interface nsIShellService : nsISupports
|
||||||
* The uri to be loaded by the application
|
* The uri to be loaded by the application
|
||||||
*/
|
*/
|
||||||
void openApplicationWithURI(in nsIFile aApplication, in ACString aURI);
|
void openApplicationWithURI(in nsIFile aApplication, in ACString aURI);
|
||||||
|
|
||||||
/**
|
|
||||||
* The default system handler for web feeds
|
|
||||||
*/
|
|
||||||
readonly attribute nsIFile defaultFeedReader;
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -383,42 +383,3 @@ nsMacShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACStrin
|
||||||
|
|
||||||
return err != noErr ? NS_ERROR_FAILURE : NS_OK;
|
return err != noErr ? NS_ERROR_FAILURE : NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsMacShellService::GetDefaultFeedReader(nsIFile** _retval)
|
|
||||||
{
|
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
|
||||||
*_retval = nullptr;
|
|
||||||
|
|
||||||
CFStringRef defaultHandlerID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("feed"));
|
|
||||||
if (!defaultHandlerID) {
|
|
||||||
defaultHandlerID = ::CFStringCreateWithCString(kCFAllocatorDefault,
|
|
||||||
SAFARI_BUNDLE_IDENTIFIER,
|
|
||||||
kCFStringEncodingASCII);
|
|
||||||
}
|
|
||||||
|
|
||||||
CFURLRef defaultHandlerURL = nullptr;
|
|
||||||
OSStatus status = ::LSFindApplicationForInfo(kLSUnknownCreator,
|
|
||||||
defaultHandlerID,
|
|
||||||
nullptr, // inName
|
|
||||||
nullptr, // outAppRef
|
|
||||||
&defaultHandlerURL);
|
|
||||||
|
|
||||||
if (status == noErr && defaultHandlerURL) {
|
|
||||||
nsCOMPtr<nsILocalFileMac> defaultReader =
|
|
||||||
do_CreateInstance("@mozilla.org/file/local;1", &rv);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
rv = defaultReader->InitWithCFURL(defaultHandlerURL);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
NS_ADDREF(*_retval = defaultReader);
|
|
||||||
rv = NS_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::CFRelease(defaultHandlerURL);
|
|
||||||
}
|
|
||||||
|
|
||||||
::CFRelease(defaultHandlerID);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -760,50 +760,3 @@ nsWindowsShellService::OpenApplicationWithURI(nsIFile* aApplication,
|
||||||
const char* specStr = spec.get();
|
const char* specStr = spec.get();
|
||||||
return process->Run(false, &specStr, 1);
|
return process->Run(false, &specStr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsWindowsShellService::GetDefaultFeedReader(nsIFile** _retval)
|
|
||||||
{
|
|
||||||
*_retval = nullptr;
|
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
nsCOMPtr<nsIWindowsRegKey> regKey =
|
|
||||||
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT,
|
|
||||||
NS_LITERAL_STRING("feed\\shell\\open\\command"),
|
|
||||||
nsIWindowsRegKey::ACCESS_READ);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsAutoString path;
|
|
||||||
rv = regKey->ReadStringValue(EmptyString(), path);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
if (path.IsEmpty())
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
if (path.First() == '"') {
|
|
||||||
// Everything inside the quotes
|
|
||||||
path = Substring(path, 1, path.FindChar('"', 1) - 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Everything up to the first space
|
|
||||||
path = Substring(path, 0, path.FindChar(' '));
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> defaultReader =
|
|
||||||
do_CreateInstance("@mozilla.org/file/local;1", &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = defaultReader->InitWithPath(path);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
bool exists;
|
|
||||||
rv = defaultReader->Exists(&exists);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
if (!exists)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
NS_ADDREF(*_retval = defaultReader);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ MockShellService.prototype = {
|
||||||
openApplication(aApplication) {},
|
openApplication(aApplication) {},
|
||||||
desktopBackgroundColor: 0,
|
desktopBackgroundColor: 0,
|
||||||
openApplicationWithURI(aApplication, aURI) {},
|
openApplicationWithURI(aApplication, aURI) {},
|
||||||
defaultFeedReader: 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var mockShellService = new MockObjectRegisterer("@mozilla.org/browser/shell-service;1",
|
var mockShellService = new MockObjectRegisterer("@mozilla.org/browser/shell-service;1",
|
||||||
|
|
|
||||||
|
|
@ -176,8 +176,6 @@
|
||||||
@BINPATH@/components/nsDNSServiceDiscovery.js
|
@BINPATH@/components/nsDNSServiceDiscovery.js
|
||||||
#endif
|
#endif
|
||||||
@RESPATH@/browser/components/BrowserFeeds.manifest
|
@RESPATH@/browser/components/BrowserFeeds.manifest
|
||||||
@RESPATH@/browser/components/FeedConverter.js
|
|
||||||
@RESPATH@/browser/components/FeedWriter.js
|
|
||||||
@RESPATH@/browser/components/WebContentConverter.js
|
@RESPATH@/browser/components/WebContentConverter.js
|
||||||
@RESPATH@/browser/components/BrowserComponents.manifest
|
@RESPATH@/browser/components/BrowserComponents.manifest
|
||||||
@RESPATH@/browser/components/nsBrowserContentHandler.js
|
@RESPATH@/browser/components/nsBrowserContentHandler.js
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@ app-manager-remove =
|
||||||
.label = Remove
|
.label = Remove
|
||||||
.accesskey = R
|
.accesskey = R
|
||||||
|
|
||||||
app-manager-handle-webfeeds = The following applications can be used to handle Web Feeds.
|
|
||||||
|
|
||||||
# Variables:
|
# Variables:
|
||||||
# $type (String) - the URI scheme of the link (e.g. mailto:)
|
# $type (String) - the URI scheme of the link (e.g. mailto:)
|
||||||
app-manager-handle-protocol = The following applications can be used to handle { $type } links.
|
app-manager-handle-protocol = The following applications can be used to handle { $type } links.
|
||||||
|
|
|
||||||
|
|
@ -1,10 +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/. -->
|
|
||||||
|
|
||||||
<!ENTITY feedPage.title
|
|
||||||
"Viewing Feed">
|
|
||||||
<!ENTITY feedSubscribeNow
|
|
||||||
"Subscribe Now">
|
|
||||||
<!ENTITY feedLiveBookmarks
|
|
||||||
"Live Bookmarks">
|
|
||||||
|
|
@ -2,49 +2,6 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
linkTitleTextFormat=Go to %S
|
|
||||||
addHandler=Add “%S” (%S) as a Feed Reader?
|
|
||||||
addHandlerAddButton=Add Feed Reader
|
|
||||||
addHandlerAddButtonAccesskey=A
|
|
||||||
handlerRegistered=“%S” is already registered as a Feed Reader
|
|
||||||
liveBookmarks=Live Bookmarks
|
|
||||||
subscribeNow=Subscribe Now
|
|
||||||
chooseApplicationMenuItem=Choose Application…
|
|
||||||
chooseApplicationDialogTitle=Choose Application
|
|
||||||
alwaysUse=Always use %S to subscribe to feeds
|
|
||||||
mediaLabel=Media files
|
|
||||||
|
|
||||||
# LOCALIZATION NOTE: The next string is for the size of the enclosed media.
|
|
||||||
# e.g. enclosureSizeText : "50.23 MB"
|
|
||||||
# %1$S = size (in bytes or megabytes, ...)
|
|
||||||
# %2$S = unit of measure (bytes, KB, MB, ...)
|
|
||||||
enclosureSizeText=%1$S %2$S
|
|
||||||
|
|
||||||
bytes=bytes
|
|
||||||
kilobyte=KB
|
|
||||||
megabyte=MB
|
|
||||||
gigabyte=GB
|
|
||||||
|
|
||||||
# LOCALIZATION NOTE: The next three strings explains to the user what they're
|
|
||||||
# doing.
|
|
||||||
# e.g. alwaysUseForVideoPodcasts : "Always use Miro to subscribe to video podcasts."
|
|
||||||
# %S = application to use (Miro, iTunes, ...)
|
|
||||||
alwaysUseForFeeds=Always use %S to subscribe to feeds.
|
|
||||||
alwaysUseForAudioPodcasts=Always use %S to subscribe to podcasts.
|
|
||||||
alwaysUseForVideoPodcasts=Always use %S to subscribe to video podcasts.
|
|
||||||
|
|
||||||
subscribeFeedUsing=Subscribe to this feed using
|
|
||||||
subscribeAudioPodcastUsing=Subscribe to this podcast using
|
|
||||||
subscribeVideoPodcastUsing=Subscribe to this video podcast using
|
|
||||||
|
|
||||||
feedSubscriptionFeed1=This is a “feed” of frequently changing content on this site.
|
|
||||||
feedSubscriptionAudioPodcast1=This is a “podcast” of frequently changing content on this site.
|
|
||||||
feedSubscriptionVideoPodcast1=This is a “video podcast” of frequently changing content on this site.
|
|
||||||
|
|
||||||
feedSubscriptionFeed2=You can subscribe to this feed to receive updates when this content changes.
|
|
||||||
feedSubscriptionAudioPodcast2=You can subscribe to this podcast to receive updates when this content changes.
|
|
||||||
feedSubscriptionVideoPodcast2=You can subscribe to this video podcast to receive updates when this content changes.
|
|
||||||
|
|
||||||
# LOCALIZATION NOTE (addProtocolHandlerMessage):
|
# LOCALIZATION NOTE (addProtocolHandlerMessage):
|
||||||
# Message displayed when adding a protocol handler:
|
# Message displayed when adding a protocol handler:
|
||||||
# %1$S is the application's domain, %2$S is the type of protocol
|
# %1$S is the application's domain, %2$S is the type of protocol
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@
|
||||||
locale/browser/safebrowsing/phishing-afterload-warning-message.dtd (%chrome/browser/safebrowsing/phishing-afterload-warning-message.dtd)
|
locale/browser/safebrowsing/phishing-afterload-warning-message.dtd (%chrome/browser/safebrowsing/phishing-afterload-warning-message.dtd)
|
||||||
locale/browser/safebrowsing/report-phishing.dtd (%chrome/browser/safebrowsing/report-phishing.dtd)
|
locale/browser/safebrowsing/report-phishing.dtd (%chrome/browser/safebrowsing/report-phishing.dtd)
|
||||||
locale/browser/safebrowsing/safebrowsing.properties (%chrome/browser/safebrowsing/safebrowsing.properties)
|
locale/browser/safebrowsing/safebrowsing.properties (%chrome/browser/safebrowsing/safebrowsing.properties)
|
||||||
locale/browser/feeds/subscribe.dtd (%chrome/browser/feeds/subscribe.dtd)
|
|
||||||
locale/browser/feeds/subscribe.properties (%chrome/browser/feeds/subscribe.properties)
|
locale/browser/feeds/subscribe.properties (%chrome/browser/feeds/subscribe.properties)
|
||||||
locale/browser/migration/migration.dtd (%chrome/browser/migration/migration.dtd)
|
locale/browser/migration/migration.dtd (%chrome/browser/migration/migration.dtd)
|
||||||
locale/browser/migration/migration.properties (%chrome/browser/migration/migration.properties)
|
locale/browser/migration/migration.properties (%chrome/browser/migration/migration.properties)
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 686 B |
|
|
@ -1,185 +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/. */
|
|
||||||
|
|
||||||
html {
|
|
||||||
background: -moz-Dialog;
|
|
||||||
font: 3mm tahoma,arial,helvetica,sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
#subscribeUsingDescription,
|
|
||||||
#subscribeButton {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#subscribeUsingDescription {
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#subscribeButton {
|
|
||||||
margin-top: 0.5em;
|
|
||||||
margin-inline-start: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedBody {
|
|
||||||
border: 1px solid THreeDShadow;
|
|
||||||
padding: 3em;
|
|
||||||
padding-inline-start: 30px;
|
|
||||||
margin: 2em auto;
|
|
||||||
background: -moz-Field;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeaderContainer {
|
|
||||||
border: 1px solid ThreeDShadow;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin: -4em auto 0 auto;
|
|
||||||
background-color: InfoBackground;
|
|
||||||
-moz-appearance: -moz-gtk-info-bar;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeaderContainerSpacer {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeader {
|
|
||||||
margin-top: 4.9em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
margin-inline-start: 1.4em;
|
|
||||||
margin-inline-end: 1em;
|
|
||||||
padding-inline-start: 2.9em;
|
|
||||||
font-size: 110%;
|
|
||||||
color: -moz-gtk-info-bar-text;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedBackground {
|
|
||||||
background: url("chrome://browser/skin/feeds/feedIcon.png") 0% 10% no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
.videoPodcastBackground {
|
|
||||||
background: url("chrome://browser/skin/feeds/videoFeedIcon.png") 0% 10% no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
.audioPodcastBackground {
|
|
||||||
background: url("chrome://browser/skin/feeds/audioFeedIcon.png") 0% 10% no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeader[dir="rtl"] {
|
|
||||||
background-position: 100% 10%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedIntroText {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeader[firstrun="true"] #feedIntroText {
|
|
||||||
padding-top: 0.1em;
|
|
||||||
padding-inline-start: 0.6em;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeader[firstrun="true"] > #feedSubscribeLine {
|
|
||||||
padding-inline-start: 1.8em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedSubscribeLine {
|
|
||||||
padding-top: 0.2em;
|
|
||||||
padding-inline-start: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't print subscription UI */
|
|
||||||
@media print {
|
|
||||||
#feedHeaderContainer {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0 3em;
|
|
||||||
color: -moz-fieldText;
|
|
||||||
font: message-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 160%;
|
|
||||||
border-bottom: 2px solid ThreeDLightShadow;
|
|
||||||
margin: 0 0 .2em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
color: GrayText;
|
|
||||||
font-size: 110%;
|
|
||||||
font-weight: normal;
|
|
||||||
margin: 0 0 .6em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTitleLink {
|
|
||||||
float: right;
|
|
||||||
margin-inline-start: .6em;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a[href] img {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTitleContainer {
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: .6em;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTitleImage {
|
|
||||||
margin-inline-start: .6em;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
max-width: 300px;
|
|
||||||
max-height: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedEntryContent {
|
|
||||||
font-size: 110%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
|
||||||
color: #0000FF;
|
|
||||||
text-decoration: underline;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link:hover:active {
|
|
||||||
color: #FF0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lastUpdated {
|
|
||||||
font-size: 85%;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.type-icon {
|
|
||||||
vertical-align: bottom;
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.enclosures {
|
|
||||||
border: 1px solid THreeDShadow;
|
|
||||||
padding: 1em;
|
|
||||||
margin: 1em auto;
|
|
||||||
background: -moz-Dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
.enclosure {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-left: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.handlersMenuList > .menulist-label-box > .menulist-icon {
|
|
||||||
max-width: 16px;
|
|
||||||
max-height: 16px;
|
|
||||||
}
|
|
||||||
|
|
@ -13,7 +13,6 @@ browser.jar:
|
||||||
skin/classic/browser/monitor_16-10.png
|
skin/classic/browser/monitor_16-10.png
|
||||||
* skin/classic/browser/pageInfo.css
|
* skin/classic/browser/pageInfo.css
|
||||||
skin/classic/browser/pageInfo.png
|
skin/classic/browser/pageInfo.png
|
||||||
skin/classic/browser/page-livemarks.png
|
|
||||||
* skin/classic/browser/searchbar.css
|
* skin/classic/browser/searchbar.css
|
||||||
skin/classic/browser/setDesktopBackground.css
|
skin/classic/browser/setDesktopBackground.css
|
||||||
skin/classic/browser/slowStartup-16.png
|
skin/classic/browser/slowStartup-16.png
|
||||||
|
|
@ -22,9 +21,6 @@ browser.jar:
|
||||||
* skin/classic/browser/customizableui/panelUI.css (customizableui/panelUI.css)
|
* skin/classic/browser/customizableui/panelUI.css (customizableui/panelUI.css)
|
||||||
* skin/classic/browser/downloads/allDownloadsView.css (downloads/allDownloadsView.css)
|
* skin/classic/browser/downloads/allDownloadsView.css (downloads/allDownloadsView.css)
|
||||||
* skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
|
* skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
|
||||||
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
|
|
||||||
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
|
|
||||||
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
|
|
||||||
skin/classic/browser/notification-icons/geo-blocked.svg (notification-icons/geo-blocked.svg)
|
skin/classic/browser/notification-icons/geo-blocked.svg (notification-icons/geo-blocked.svg)
|
||||||
skin/classic/browser/notification-icons/geo-detailed.svg (notification-icons/geo-detailed.svg)
|
skin/classic/browser/notification-icons/geo-detailed.svg (notification-icons/geo-detailed.svg)
|
||||||
skin/classic/browser/notification-icons/geo.svg (notification-icons/geo.svg)
|
skin/classic/browser/notification-icons/geo.svg (notification-icons/geo.svg)
|
||||||
|
|
@ -46,8 +42,3 @@ browser.jar:
|
||||||
skin/classic/browser/window-controls/restore.svg (window-controls/restore.svg)
|
skin/classic/browser/window-controls/restore.svg (window-controls/restore.svg)
|
||||||
|
|
||||||
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
|
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
|
||||||
|
|
||||||
% override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png
|
|
||||||
% override chrome://browser/skin/feeds/audioFeedIcon16.png chrome://browser/skin/feeds/feedIcon16.png
|
|
||||||
% override chrome://browser/skin/feeds/videoFeedIcon.png chrome://browser/skin/feeds/feedIcon.png
|
|
||||||
% override chrome://browser/skin/feeds/videoFeedIcon16.png chrome://browser/skin/feeds/feedIcon16.png
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 638 B |
|
|
@ -40,10 +40,6 @@
|
||||||
-moz-image-region: rect(0px, 64px, 32px, 32px)
|
-moz-image-region: rect(0px, 64px, 32px, 32px)
|
||||||
}
|
}
|
||||||
|
|
||||||
#feedTab {
|
|
||||||
-moz-image-region: rect(0px, 96px, 32px, 64px)
|
|
||||||
}
|
|
||||||
|
|
||||||
#permTab {
|
#permTab {
|
||||||
-moz-image-region: rect(0px, 128px, 32px, 96px)
|
-moz-image-region: rect(0px, 128px, 32px, 96px)
|
||||||
}
|
}
|
||||||
|
|
@ -136,39 +132,6 @@ treechildren::-moz-tree-cell-text(broken) {
|
||||||
color: graytext;
|
color: graytext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Feeds Tab */
|
|
||||||
#feedPanel {
|
|
||||||
margin-left: 2px;
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedtree {
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedListbox richlistitem {
|
|
||||||
padding-top: 6px;
|
|
||||||
padding-bottom: 6px;
|
|
||||||
padding-inline-start: 7px;
|
|
||||||
padding-inline-end: 7px;
|
|
||||||
min-height: 25px;
|
|
||||||
border-bottom: 1px dotted ThreeDShadow;
|
|
||||||
color: -moz-FieldText;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedListbox richlistitem[selected="true"] {
|
|
||||||
background-color: -moz-Dialog;
|
|
||||||
color: -moz-DialogText;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedListbox {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedTitle {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Permissions Tab */
|
/* Permissions Tab */
|
||||||
|
|
||||||
#permList {
|
#permList {
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,6 @@ menuitem[appHandlerIcon="save"] {
|
||||||
list-style-image: url("moz-icon://stock/gtk-save?size=menu");
|
list-style-image: url("moz-icon://stock/gtk-save?size=menu");
|
||||||
}
|
}
|
||||||
|
|
||||||
richlistitem[appHandlerIcon="feed"],
|
|
||||||
menuitem[appHandlerIcon="feed"] {
|
|
||||||
list-style-image: url("chrome://browser/skin/page-livemarks.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
richlistitem[appHandlerIcon="plugin"],
|
richlistitem[appHandlerIcon="plugin"],
|
||||||
menuitem[appHandlerIcon="plugin"] {
|
menuitem[appHandlerIcon="plugin"] {
|
||||||
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric.svg");
|
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric.svg");
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 762 B |
|
|
@ -1,178 +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/. */
|
|
||||||
|
|
||||||
html {
|
|
||||||
background: -moz-Dialog;
|
|
||||||
font: 3mm tahoma,arial,helvetica,sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
#subscribeUsingDescription,
|
|
||||||
#subscribeButton {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#subscribeUsingDescription {
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#subscribeButton {
|
|
||||||
margin-top: 0.5em;
|
|
||||||
margin-inline-start: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedBody {
|
|
||||||
border: 1px solid THreeDShadow;
|
|
||||||
padding: 3em;
|
|
||||||
padding-inline-start: 30px;
|
|
||||||
margin: 2em auto;
|
|
||||||
background: -moz-Field;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeaderContainer {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeaderContainerSpacer {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeader {
|
|
||||||
border: 1px solid ThreeDShadow;
|
|
||||||
border-radius: 10px;
|
|
||||||
padding-top: 4em;
|
|
||||||
padding-bottom: .3em;
|
|
||||||
padding-inline-start: .3em;
|
|
||||||
padding-inline-end: .3em;
|
|
||||||
margin: -4em auto 0 auto;
|
|
||||||
font-size: 110%;
|
|
||||||
color: InfoText;
|
|
||||||
padding: 5em 3em 0 3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedBackground {
|
|
||||||
background: url("chrome://browser/skin/feeds/feedIcon.png") 1.4em 5.9em no-repeat rgb(255,255,225);
|
|
||||||
}
|
|
||||||
|
|
||||||
.videoPodcastBackground {
|
|
||||||
background: url("chrome://browser/skin/feeds/videoFeedIcon.png") 1.4em 5.9em no-repeat rgb(255,255,225);
|
|
||||||
}
|
|
||||||
|
|
||||||
.audioPodcastBackground {
|
|
||||||
background: url("chrome://browser/skin/feeds/audioFeedIcon.png") 1.4em 5.9em no-repeat rgb(255,255,225);
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeader[firstrun="true"] #feedIntroText {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedIntroText {
|
|
||||||
display: none;
|
|
||||||
margin-inline-start: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedSubscribeLine {
|
|
||||||
padding: 0 1em 1em 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeader[firstrun="true"] #feedSubscribeLine {
|
|
||||||
padding-left: 3.7em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't print subscription UI */
|
|
||||||
@media print {
|
|
||||||
#feedHeaderContainer {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0 3em;
|
|
||||||
color: -moz-fieldText;
|
|
||||||
font: message-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 160%;
|
|
||||||
border-bottom: 2px solid ThreeDLightShadow;
|
|
||||||
margin: 0 0 .2em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
color: #C0C0C0;
|
|
||||||
font-size: 110%;
|
|
||||||
font-weight: normal;
|
|
||||||
margin: 0 0 .6em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTitleLink {
|
|
||||||
float: right;
|
|
||||||
margin-inline-start: .6em;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a[href] img {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTitleContainer {
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: .6em;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTitleImage {
|
|
||||||
margin-inline-start: .6em;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
max-width: 300px;
|
|
||||||
max-height: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedEntryContent {
|
|
||||||
font-size: 110%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
|
||||||
color: #0000FF;
|
|
||||||
text-decoration: underline;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-top: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link:hover:active {
|
|
||||||
color: #FF0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lastUpdated {
|
|
||||||
font-size: 85%;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.type-icon {
|
|
||||||
vertical-align: bottom;
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.enclosures {
|
|
||||||
border: 1px solid THreeDShadow;
|
|
||||||
padding: 1em;
|
|
||||||
margin: 1em auto;
|
|
||||||
background: -moz-Dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
.enclosure {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-left: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.handlersMenuList > .menulist-label-box > .menulist-icon {
|
|
||||||
max-width: 16px;
|
|
||||||
max-height: 16px;
|
|
||||||
}
|
|
||||||
|
|
@ -14,7 +14,6 @@ browser.jar:
|
||||||
skin/classic/browser/panel-expander-open.png
|
skin/classic/browser/panel-expander-open.png
|
||||||
skin/classic/browser/panel-expander-open@2x.png
|
skin/classic/browser/panel-expander-open@2x.png
|
||||||
skin/classic/browser/panel-plus-sign.png
|
skin/classic/browser/panel-plus-sign.png
|
||||||
skin/classic/browser/page-livemarks.png
|
|
||||||
* skin/classic/browser/pageInfo.css
|
* skin/classic/browser/pageInfo.css
|
||||||
* skin/classic/browser/searchbar.css
|
* skin/classic/browser/searchbar.css
|
||||||
skin/classic/browser/slowStartup-16.png
|
skin/classic/browser/slowStartup-16.png
|
||||||
|
|
@ -25,9 +24,6 @@ browser.jar:
|
||||||
* skin/classic/browser/customizableui/panelUI.css (customizableui/panelUI.css)
|
* skin/classic/browser/customizableui/panelUI.css (customizableui/panelUI.css)
|
||||||
* skin/classic/browser/downloads/allDownloadsView.css (downloads/allDownloadsView.css)
|
* skin/classic/browser/downloads/allDownloadsView.css (downloads/allDownloadsView.css)
|
||||||
* skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
|
* skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
|
||||||
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
|
|
||||||
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
|
|
||||||
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
|
|
||||||
skin/classic/browser/setDesktopBackground.css
|
skin/classic/browser/setDesktopBackground.css
|
||||||
skin/classic/browser/monitor.png
|
skin/classic/browser/monitor.png
|
||||||
skin/classic/browser/monitor_16-10.png
|
skin/classic/browser/monitor_16-10.png
|
||||||
|
|
@ -52,8 +48,4 @@ browser.jar:
|
||||||
skin/classic/browser/tabbrowser/tabDragIndicator@2x.png (tabbrowser/tabDragIndicator@2x.png)
|
skin/classic/browser/tabbrowser/tabDragIndicator@2x.png (tabbrowser/tabDragIndicator@2x.png)
|
||||||
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
|
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
|
||||||
|
|
||||||
% override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png
|
|
||||||
% override chrome://browser/skin/feeds/audioFeedIcon16.png chrome://browser/skin/feeds/feedIcon16.png
|
|
||||||
% override chrome://browser/skin/feeds/videoFeedIcon.png chrome://browser/skin/feeds/feedIcon.png
|
|
||||||
% override chrome://browser/skin/feeds/videoFeedIcon16.png chrome://browser/skin/feeds/feedIcon16.png
|
|
||||||
% override chrome://browser/skin/notification-icons/geo-detailed.svg chrome://browser/skin/notification-icons/geo.svg
|
% override chrome://browser/skin/notification-icons/geo-detailed.svg chrome://browser/skin/notification-icons/geo.svg
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 606 B |
|
|
@ -109,29 +109,6 @@ treechildren::-moz-tree-cell-text(broken) {
|
||||||
color: graytext;
|
color: graytext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Feeds Tab */
|
|
||||||
#feedtree {
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedListbox richlistitem {
|
|
||||||
padding-top: 6px;
|
|
||||||
padding-bottom: 6px;
|
|
||||||
padding-inline-start: 7px;
|
|
||||||
padding-inline-end: 7px;
|
|
||||||
min-height: 25px;
|
|
||||||
border-bottom: 1px dotted ThreeDShadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedListbox richlistitem[selected="true"] {
|
|
||||||
background-color: -moz-Dialog;
|
|
||||||
color: -moz-DialogText;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedTitle {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Permissions Tab */
|
/* Permissions Tab */
|
||||||
#permList {
|
#permList {
|
||||||
margin: .5em;
|
margin: .5em;
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,6 @@ menuitem[appHandlerIcon="save"] {
|
||||||
list-style-image: url("chrome://browser/skin/preferences/saveFile.png");
|
list-style-image: url("chrome://browser/skin/preferences/saveFile.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
richlistitem[appHandlerIcon="feed"],
|
|
||||||
menuitem[appHandlerIcon="feed"] {
|
|
||||||
list-style-image: url("chrome://browser/skin/page-livemarks.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
richlistitem[appHandlerIcon="plugin"],
|
richlistitem[appHandlerIcon="plugin"],
|
||||||
menuitem[appHandlerIcon="plugin"] {
|
menuitem[appHandlerIcon="plugin"] {
|
||||||
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric.svg");
|
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric.svg");
|
||||||
|
|
|
||||||
|
|
@ -882,11 +882,6 @@ notification[value="translation"] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bookmarks roots menu-items */
|
/* Bookmarks roots menu-items */
|
||||||
#subscribeToPageMenuitem:not([disabled]),
|
|
||||||
#subscribeToPageMenupopup {
|
|
||||||
list-style-image: url("chrome://browser/skin/feeds/feedIcon16.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
#bookmarksToolbarFolderMenu,
|
#bookmarksToolbarFolderMenu,
|
||||||
#BMB_bookmarksToolbar,
|
#BMB_bookmarksToolbar,
|
||||||
#panelMenu_bookmarksToolbar {
|
#panelMenu_bookmarksToolbar {
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 743 B |
|
|
@ -1,184 +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/. */
|
|
||||||
|
|
||||||
html {
|
|
||||||
background: -moz-Dialog;
|
|
||||||
font: 3mm tahoma,arial,helvetica,sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
#subscribeUsingDescription,
|
|
||||||
#subscribeButton {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#subscribeUsingDescription {
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#subscribeButton {
|
|
||||||
margin-top: 0.5em;
|
|
||||||
margin-inline-start: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedBody {
|
|
||||||
border: 1px solid THreeDShadow;
|
|
||||||
padding: 3em;
|
|
||||||
padding-inline-start: 30px;
|
|
||||||
margin: 2em auto;
|
|
||||||
background: -moz-Field;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeaderContainer {
|
|
||||||
border: 1px solid ThreeDShadow;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin: -4em auto 0 auto;
|
|
||||||
background-color: InfoBackground;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeaderContainerSpacer {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeader {
|
|
||||||
margin-top: 4.9em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
margin-inline-start: 1.4em;
|
|
||||||
margin-inline-end: 1em;
|
|
||||||
padding-inline-start: 2.9em;
|
|
||||||
font-size: 110%;
|
|
||||||
color: InfoText;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedIntroText {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedBackground {
|
|
||||||
background: url("chrome://browser/skin/feeds/feedIcon.png") 0% 10% no-repeat InfoBackground;
|
|
||||||
}
|
|
||||||
|
|
||||||
.videoPodcastBackground {
|
|
||||||
background: url("chrome://browser/skin/feeds/videoFeedIcon.png") 0% 10% no-repeat InfoBackground;
|
|
||||||
}
|
|
||||||
|
|
||||||
.audioPodcastBackground {
|
|
||||||
background: url("chrome://browser/skin/feeds/audioFeedIcon.png") 0% 10% no-repeat InfoBackground;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeader[dir="rtl"] {
|
|
||||||
background-position: 100% 10%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeader[firstrun="true"] #feedIntroText {
|
|
||||||
padding-top: 0.1em;
|
|
||||||
padding-inline-start: 0.6em;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedHeader[firstrun="true"] > #feedSubscribeLine {
|
|
||||||
padding-inline-start: 1.8em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedSubscribeLine {
|
|
||||||
padding-top: 0.2em;
|
|
||||||
padding-inline-start: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't print subscription UI */
|
|
||||||
@media print {
|
|
||||||
#feedHeaderContainer {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0 3em;
|
|
||||||
color: -moz-fieldText;
|
|
||||||
font: message-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 160%;
|
|
||||||
border-bottom: 2px solid ThreeDLightShadow;
|
|
||||||
margin: 0 0 .2em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
color: GrayText;
|
|
||||||
font-size: 110%;
|
|
||||||
font-weight: normal;
|
|
||||||
margin: 0 0 .6em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTitleLink {
|
|
||||||
float: right;
|
|
||||||
margin-inline-start: .6em;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a[href] img {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTitleContainer {
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: .6em;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTitleImage {
|
|
||||||
margin-inline-start: .6em;
|
|
||||||
margin-inline-end: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
max-width: 300px;
|
|
||||||
max-height: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedEntryContent {
|
|
||||||
font-size: 110%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
|
||||||
color: #0000FF;
|
|
||||||
text-decoration: underline;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link:hover:active {
|
|
||||||
color: #FF0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lastUpdated {
|
|
||||||
font-size: 85%;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.type-icon {
|
|
||||||
vertical-align: bottom;
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.enclosures {
|
|
||||||
border: 1px solid THreeDShadow;
|
|
||||||
padding: 1em;
|
|
||||||
margin: 1em auto;
|
|
||||||
background: -moz-Dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
.enclosure {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-left: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.handlersMenuList > .menulist-label-box > .menulist-icon {
|
|
||||||
max-width: 16px;
|
|
||||||
max-height: 16px;
|
|
||||||
}
|
|
||||||
|
|
@ -21,9 +21,6 @@ browser.jar:
|
||||||
* skin/classic/browser/customizableui/panelUI.css (customizableui/panelUI.css)
|
* skin/classic/browser/customizableui/panelUI.css (customizableui/panelUI.css)
|
||||||
* skin/classic/browser/downloads/allDownloadsView.css (downloads/allDownloadsView.css)
|
* skin/classic/browser/downloads/allDownloadsView.css (downloads/allDownloadsView.css)
|
||||||
* skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
|
* skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
|
||||||
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
|
|
||||||
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
|
|
||||||
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
|
|
||||||
skin/classic/browser/notification-icons/geo-blocked.svg (notification-icons/geo-blocked.svg)
|
skin/classic/browser/notification-icons/geo-blocked.svg (notification-icons/geo-blocked.svg)
|
||||||
skin/classic/browser/notification-icons/geo-detailed.svg (notification-icons/geo-detailed.svg)
|
skin/classic/browser/notification-icons/geo-detailed.svg (notification-icons/geo-detailed.svg)
|
||||||
skin/classic/browser/notification-icons/geo.svg (notification-icons/geo.svg)
|
skin/classic/browser/notification-icons/geo.svg (notification-icons/geo.svg)
|
||||||
|
|
@ -55,9 +52,3 @@ browser.jar:
|
||||||
skin/classic/browser/window-controls/restore-highcontrast.svg (window-controls/restore-highcontrast.svg)
|
skin/classic/browser/window-controls/restore-highcontrast.svg (window-controls/restore-highcontrast.svg)
|
||||||
skin/classic/browser/window-controls/restore-themes.svg (window-controls/restore-themes.svg)
|
skin/classic/browser/window-controls/restore-themes.svg (window-controls/restore-themes.svg)
|
||||||
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
|
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
|
||||||
|
|
||||||
% override chrome://browser/skin/page-livemarks.png chrome://browser/skin/feeds/feedIcon16.png
|
|
||||||
% override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png
|
|
||||||
% override chrome://browser/skin/feeds/audioFeedIcon16.png chrome://browser/skin/feeds/feedIcon16.png
|
|
||||||
% override chrome://browser/skin/feeds/videoFeedIcon.png chrome://browser/skin/feeds/feedIcon.png
|
|
||||||
% override chrome://browser/skin/feeds/videoFeedIcon16.png chrome://browser/skin/feeds/feedIcon16.png
|
|
||||||
|
|
|
||||||
|
|
@ -58,15 +58,6 @@
|
||||||
-moz-image-region: rect(32px, 64px, 64px, 32px)
|
-moz-image-region: rect(32px, 64px, 64px, 32px)
|
||||||
}
|
}
|
||||||
|
|
||||||
#feedTab {
|
|
||||||
-moz-image-region: rect(0px, 96px, 32px, 64px)
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTab:hover,
|
|
||||||
#feedTab[selected="true"] {
|
|
||||||
-moz-image-region: rect(32px, 96px, 64px, 64px)
|
|
||||||
}
|
|
||||||
|
|
||||||
#permTab {
|
#permTab {
|
||||||
-moz-image-region: rect(0px, 128px, 32px, 96px)
|
-moz-image-region: rect(0px, 128px, 32px, 96px)
|
||||||
}
|
}
|
||||||
|
|
@ -161,29 +152,6 @@ treechildren::-moz-tree-cell-text(broken) {
|
||||||
color: graytext;
|
color: graytext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Feeds Tab */
|
|
||||||
#feedtree {
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedListbox richlistitem {
|
|
||||||
padding-top: 6px;
|
|
||||||
padding-bottom: 6px;
|
|
||||||
padding-inline-start: 7px;
|
|
||||||
padding-inline-end: 7px;
|
|
||||||
min-height: 25px;
|
|
||||||
border-bottom: 1px dotted ThreeDShadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedListbox richlistitem[selected="true"] {
|
|
||||||
background-color: -moz-Dialog;
|
|
||||||
color: -moz-DialogText;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedTitle {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Permissions Tab */
|
/* Permissions Tab */
|
||||||
#permList {
|
#permList {
|
||||||
margin: .5em;
|
margin: .5em;
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,6 @@ menuitem[appHandlerIcon="save"] {
|
||||||
list-style-image: url("chrome://browser/skin/preferences/saveFile.png");
|
list-style-image: url("chrome://browser/skin/preferences/saveFile.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
richlistitem[appHandlerIcon="feed"],
|
|
||||||
menuitem[appHandlerIcon="feed"] {
|
|
||||||
list-style-image: url("chrome://browser/skin/page-livemarks.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
richlistitem[appHandlerIcon="plugin"],
|
richlistitem[appHandlerIcon="plugin"],
|
||||||
menuitem[appHandlerIcon="plugin"] {
|
menuitem[appHandlerIcon="plugin"] {
|
||||||
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric.svg");
|
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric.svg");
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#include "js/TypeDecls.h"
|
|
||||||
#include "nsContentUtils.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
|
|
||||||
struct FeedWriterEnabled {
|
|
||||||
static bool IsEnabled(JSContext* cx, JSObject* aGlobal)
|
|
||||||
{
|
|
||||||
return nsContentUtils::IsSpecificAboutPage(aGlobal, "about:feeds");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -129,7 +129,6 @@ if CONFIG['MOZ_WEBRTC']:
|
||||||
|
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
'CORSMode.h',
|
'CORSMode.h',
|
||||||
'FeedWriterEnabled.h',
|
|
||||||
'FlushType.h',
|
'FlushType.h',
|
||||||
'FullscreenChange.h',
|
'FullscreenChange.h',
|
||||||
'RangeBoundary.h',
|
'RangeBoundary.h',
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
[JSImplementation="@mozilla.org/browser/feeds/result-writer;1",
|
|
||||||
Func="mozilla::FeedWriterEnabled::IsEnabled",
|
|
||||||
Constructor]
|
|
||||||
interface BrowserFeedWriter {
|
|
||||||
/**
|
|
||||||
* Writes the feed content, assumes that the feed writer is initialized.
|
|
||||||
*/
|
|
||||||
void writeContent();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uninitialize the feed writer.
|
|
||||||
*/
|
|
||||||
void close();
|
|
||||||
};
|
|
||||||
|
|
@ -1091,11 +1091,6 @@ if CONFIG['MOZ_WEBSPEECH']:
|
||||||
'SpeechSynthesisEvent.webidl',
|
'SpeechSynthesisEvent.webidl',
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['MOZ_BUILD_APP'] in ['browser', 'xulrunner'] or CONFIG['MOZ_SUITE']:
|
|
||||||
WEBIDL_FILES += [
|
|
||||||
'BrowserFeedWriter.webidl',
|
|
||||||
]
|
|
||||||
|
|
||||||
if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']:
|
if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']:
|
||||||
WEBIDL_FILES += [
|
WEBIDL_FILES += [
|
||||||
'External.webidl',
|
'External.webidl',
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ module.exports = {
|
||||||
"globals": {
|
"globals": {
|
||||||
"AddonManagerPermissions": false,
|
"AddonManagerPermissions": false,
|
||||||
"BroadcastChannel": false,
|
"BroadcastChannel": false,
|
||||||
"BrowserFeedWriter": false,
|
|
||||||
"CSSAnimation": false,
|
"CSSAnimation": false,
|
||||||
"CSSPrimitiveValue": false,
|
"CSSPrimitiveValue": false,
|
||||||
"CSSValueList": false,
|
"CSSValueList": false,
|
||||||
|
|
|
||||||