Bug 1420622 - Remove feed and pcast protocols. r=Gijs
authorJonathan Kingston <jkt@mozilla.com>
Tue, 19 Dec 2017 16:12:29 +0000
changeset 448629 cf797408666914e7943f077d11f7fb9a2cfebd1e
parent 448628 e46dd3c8e6001ee821411c15b1466d54fe723f1a
child 448630 1624b88874765bf57e9feba176d30149c748d9d2
child 448631 a9b1ce0a60b0bf3be280524a7eec46380d582c1f
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1420622
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1420622 - Remove feed and pcast protocols. r=Gijs MozReview-Commit-ID: KAC9MmLiuBG
browser/base/content/browser-feeds.js
browser/base/content/test/general/feed_discovery.html
browser/components/feeds/BrowserFeeds.manifest
browser/components/feeds/FeedConverter.js
browser/components/feeds/moz.build
browser/components/feeds/nsFeedSniffer.cpp
browser/modules/test/unit/test_E10SUtils_nested_URIs.js
caps/tests/mochitest/browser_checkloaduri.js
docshell/test/chrome/test_viewsource_forbidden_in_iframe.xul
toolkit/components/telemetry/Histograms.json
--- a/browser/base/content/browser-feeds.js
+++ b/browser/base/content/browser-feeds.js
@@ -203,21 +203,16 @@ var FeedHandler = {
    */
   subscribeToFeed(href, event) {
     // Just load the feed in the content area to either subscribe or show the
     // preview UI
     if (!href)
       href = event.target.getAttribute("feed");
     urlSecurityCheck(href, gBrowser.contentPrincipal,
                      Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
-    let feedURI = makeURI(href, document.characterSet);
-    // Use the feed scheme so X-Moz-Is-Feed will be set
-    // The value doesn't matter
-    if (/^https?$/.test(feedURI.scheme))
-      href = "feed:" + href;
     this.loadFeed(href, event);
   },
 
   loadFeed(href, event) {
     let feeds = gBrowser.selectedBrowser.feeds;
     try {
       openUILink(href, event, { ignoreAlt: true });
     } finally {
@@ -274,16 +269,23 @@ var FeedHandler = {
       this._feedMenupopup.setAttribute("hidden", "true");
     }
   },
 
   addFeed(link, browserForLink) {
     if (!browserForLink.feeds)
       browserForLink.feeds = [];
 
+    urlSecurityCheck(link.href, gBrowser.contentPrincipal,
+                     Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
+
+    let feedURI = makeURI(link.href, document.characterSet);
+    if (!/^https?$/.test(feedURI.scheme))
+      return;
+
     browserForLink.feeds.push({ href: link.href, title: link.title });
 
     // If this addition was for the current browser, update the UI. For
     // background browsers, we'll update on tab switch.
     if (browserForLink == gBrowser.selectedBrowser) {
       // Batch updates to avoid updating the UI for multiple onLinkAdded events
       // fired within 100ms of each other.
       if (this._updateFeedTimeout)
--- a/browser/base/content/test/general/feed_discovery.html
+++ b/browser/base/content/test/general/feed_discovery.html
@@ -7,16 +7,21 @@ https://bugzilla.mozilla.org/show_bug.cg
     <title>Test for feed discovery</title>
     <meta charset="utf-8">
 
     <!-- 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" />
 
+    <!-- invalid protocol -->
+    <link rel="alternate" type="application/atom+xml" title="Bogus non file protocol" href="file://path/1.rss" />
+    <link rel="alternate" type="application/atom+xml" title="Bogus non feed:http protocol" href="feed:http://path/1.rss" />
+    <link rel="alternate" type="application/atom+xml" title="Bogus non pcast protocol" href="pcast://path/1.rss" />
+
     <!-- rel is a space-separated list -->
     <link rel=" alternate " type="application/atom+xml" title="4" href="/4.atom" />
     <link rel="foo alternate" type="application/atom+xml" title="5" href="/5.atom" />
     <link rel="alternate foo" type="application/atom+xml" title="6" href="/6.atom" />
     <link rel="foo alternate foo" type="application/atom+xml" title="7" href="/7.atom" />
     <link rel="meat feed cake" title="8" href="/8.atom" />
 
     <!-- rel is case-insensitive -->
--- a/browser/components/feeds/BrowserFeeds.manifest
+++ b/browser/components/feeds/BrowserFeeds.manifest
@@ -9,17 +9,13 @@
 #   graphene:       {d1bfe7d9-c01e-4237-998b-7b5f960a4314}
 
 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 {4f91ef2e-57ba-472e-ab7a-b4999e42d6c0} FeedConverter.js
-contract @mozilla.org/network/protocol;1?name=feed {4f91ef2e-57ba-472e-ab7a-b4999e42d6c0}
-component {1c31ed79-accd-4b94-b517-06e0c81999d5} FeedConverter.js
-contract @mozilla.org/network/protocol;1?name=pcast {1c31ed79-accd-4b94-b517-06e0c81999d5}
 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
 contract @mozilla.org/embeddor.implemented/web-content-handler-registrar;1 {792a7e82-06a0-437c-af63-b2d12e808acc}
 category app-startup WebContentConverter service,@mozilla.org/embeddor.implemented/web-content-handler-registrar;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66} application={d1bfe7d9-c01e-4237-998b-7b5f960a4314}
--- a/browser/components/feeds/FeedConverter.js
+++ b/browser/components/feeds/FeedConverter.js
@@ -450,128 +450,14 @@ FeedResultService.prototype = {
     if (iid.equals(Ci.nsIFeedResultService) ||
         iid.equals(Ci.nsIFactory) ||
         iid.equals(Ci.nsISupports))
       return this;
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
   },
 };
 
-/**
- * A protocol handler that attempts to deal with the variant forms of feed:
- * URIs that are actually either http or https.
- */
-function GenericProtocolHandler() {
-}
-GenericProtocolHandler.prototype = {
-  _init(scheme) {
-    this._http = Services.io.getProtocolHandler("http");
-    this._scheme = scheme;
-  },
-
-  get scheme() {
-    return this._scheme;
-  },
-
-  get protocolFlags() {
-    let {URI_DANGEROUS_TO_LOAD, ALLOWS_PROXY_HTTP, ALLOWS_PROXY} =
-      Ci.nsIProtocolHandler;
-    return URI_DANGEROUS_TO_LOAD | ALLOWS_PROXY | ALLOWS_PROXY_HTTP;
-  },
-
-  get defaultPort() {
-    return this._http.defaultPort;
-  },
-
-  allowPort(port, scheme) {
-    return this._http.allowPort(port, scheme);
-  },
-
-  _getTelemetrySchemeId() {
-    // Gets a scheme id from 1-8
-    let schemeId;
-    if (!this._telemetrySubScheme) {
-      schemeId = 1;
-    } else {
-      switch (this._telemetryInnerScheme) {
-        case "http":
-          schemeId = 2;
-          break;
-        case "https":
-          schemeId = 3;
-          break;
-        default:
-          // Invalid scheme
-          schemeId = 4;
-      }
-    }
-    if (this._scheme === "pcast") {
-      schemeId += 4;
-    }
-    return schemeId;
-  },
-
-  newURI(spec, originalCharset, baseURI) {
-    // Feed URIs can be either nested URIs of the form feed:realURI (in which
-    // case we create a nested URI for the realURI) or feed://example.com, in
-    // which case we create a nested URI for the real protocol which is http.
-
-    let scheme = this._scheme + ":";
-    if (spec.substr(0, scheme.length) != scheme)
-      throw Cr.NS_ERROR_MALFORMED_URI;
-
-    this._telemetrySubScheme = spec.substr(scheme.length, 2) != "//";
-
-    let prefix = spec.substr(scheme.length, 2) == "//" ? "http:" : "";
-    let inner = Services.io.newURI(spec.replace(scheme, prefix),
-                                   originalCharset, baseURI);
-    this._telemetryInnerScheme = inner.scheme;
-
-
-    if (!["http", "https"].includes(inner.scheme))
-      throw Cr.NS_ERROR_MALFORMED_URI;
-
-    let uri = Services.io.QueryInterface(Ci.nsINetUtil).newSimpleNestedURI(inner);
-    uri.spec = inner.spec.replace(prefix, scheme);
-    return uri;
-  },
-
-  newChannel2(aUri, aLoadInfo) {
-    let inner = aUri.QueryInterface(Ci.nsINestedURI).innerURI;
-    let channel = Services.io.newChannelFromURIWithLoadInfo(inner, aLoadInfo);
-
-    const schemeId = this._getTelemetrySchemeId();
-    Services.telemetry.getHistogramById("FEED_PROTOCOL_USAGE").add(schemeId);
-
-    if (channel instanceof Components.interfaces.nsIHttpChannel)
-      // Set this so we know this is supposed to be a feed
-      channel.setRequestHeader("X-Moz-Is-Feed", "1", false);
-    channel.originalURI = aUri;
-    return channel;
-  },
-
-  QueryInterface(iid) {
-    if (iid.equals(Ci.nsIProtocolHandler) ||
-        iid.equals(Ci.nsISupports))
-      return this;
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
-};
-
-function FeedProtocolHandler() {
-  this._init("feed");
-}
-FeedProtocolHandler.prototype = new GenericProtocolHandler();
-FeedProtocolHandler.prototype.classID = Components.ID("{4f91ef2e-57ba-472e-ab7a-b4999e42d6c0}");
-
-function PodCastProtocolHandler() {
-  this._init("pcast");
-}
-PodCastProtocolHandler.prototype = new GenericProtocolHandler();
-PodCastProtocolHandler.prototype.classID = Components.ID("{1c31ed79-accd-4b94-b517-06e0c81999d5}");
 
 var components = [FeedConverter,
-                  FeedResultService,
-                  FeedProtocolHandler,
-                  PodCastProtocolHandler];
+                  FeedResultService];
 
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
--- a/browser/components/feeds/moz.build
+++ b/browser/components/feeds/moz.build
@@ -1,15 +1,14 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome/chrome.ini']
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 
 JAR_MANIFESTS += ['jar.mn']
 
 XPIDL_SOURCES += [
     'nsIFeedResultService.idl',
     'nsIWebContentConverterRegistrar.idl',
--- a/browser/components/feeds/nsFeedSniffer.cpp
+++ b/browser/components/feeds/nsFeedSniffer.cpp
@@ -241,27 +241,16 @@ nsFeedSniffer::GetMIMETypeFromContent(ns
   // 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);
 
-  // Check to see if this was a feed request from the location bar or from
-  // the feed: protocol. This is also a reliable indication.
-  // The value of the header doesn't matter.
-  if (!noSniff) {
-    nsAutoCString sniffHeader;
-    nsresult foundHeader =
-      channel->GetRequestHeader(NS_LITERAL_CSTRING("X-Moz-Is-Feed"),
-                                sniffHeader);
-    noSniff = NS_SUCCEEDED(foundHeader);
-  }
-
   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
--- a/browser/modules/test/unit/test_E10SUtils_nested_URIs.js
+++ b/browser/modules/test/unit/test_E10SUtils_nested_URIs.js
@@ -24,44 +24,32 @@ var TEST_CASES = [
     nestedURL: "jar:jar:file:///some.file!/!/",
     plainURL: "file:///some.file",
   },
   {
     nestedURL: "jar:http://some.site/file!/",
     plainURL: "http://some.site/file",
   },
   {
-    nestedURL: "feed:http://some.site",
-    plainURL: "http://some.site",
-  },
-  {
-    nestedURL: "pcast:http://some.site",
-    plainURL: "http://some.site",
-  },
-  {
     nestedURL: "view-source:http://some.site",
     plainURL: "http://some.site",
   },
   {
     nestedURL: "view-source:file:///some.file",
     plainURL: "file:///some.file",
   },
   {
     nestedURL: "view-source:about:home",
     plainURL: "about:home",
   },
   {
     nestedURL: "view-source:about:robots",
     plainURL: "about:robots",
   },
   {
-    nestedURL: "view-source:feed:http://some.site",
-    plainURL: "http://some.site",
-  },
-  {
     nestedURL: "view-source:pcast:http://some.site",
     plainURL: "http://some.site",
   },
 ];
 
 function run_test() {
   for (let testCase of TEST_CASES) {
     for (let preferredRemoteType of TEST_PREFERRED_REMOTE_TYPES) {
--- a/caps/tests/mochitest/browser_checkloaduri.js
+++ b/caps/tests/mochitest/browser_checkloaduri.js
@@ -42,74 +42,41 @@ const kAboutPagesRegistered = Promise.al
 const URLs = new Map([
   ["http://www.example.com", [
   // For each of these entries, the booleans represent whether the parent URI can:
   // - load them
   // - load them without principal inheritance
   // - whether the URI can be created at all (some protocol handlers will
   //   refuse to create certain variants)
     ["http://www.example2.com", true, true, true],
-    ["feed:http://www.example2.com", false, false, true],
     ["https://www.example2.com", true, true, true],
     ["moz-icon:file:///foo/bar/baz.exe", false, false, true],
     ["moz-icon://.exe", false, false, true],
     ["chrome://foo/content/bar.xul", false, false, true],
-    ["feed:chrome://foo/content/bar.xul", false, false, false],
     ["view-source:http://www.example2.com", false, false, true],
     ["view-source:https://www.example2.com", false, false, true],
-    ["view-source:feed:http://www.example2.com", false, false, true],
-    ["feed:view-source:http://www.example2.com", false, false, false],
-    ["data:text/html,Hi", true, false, true],
-    ["view-source:data:text/html,Hi", false, false, true],
-    ["javascript:alert('hi')", true, false, true],
-    ["moz://a", false, false, true],
-    ["about:test-chrome-privs", false, false, true],
-    ["about:test-unknown-unlinkable", false, false, true],
-    ["about:test-content-unlinkable", false, false, true],
-    ["about:test-content-linkable", true, true, true],
-    // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
-    ["about:test-unknown-linkable", false, false, true],
-  ]],
-  ["feed:http://www.example.com", [
-    ["http://www.example2.com", true, true, true],
-    ["feed:http://www.example2.com", true, true, true],
-    ["https://www.example2.com", true, true, true],
-    ["moz-icon:file:///foo/bar/baz.exe", false, false, true],
-    ["moz-icon://.exe", false, false, true],
-    ["feed:https://www.example2.com", true, true, true],
-    ["chrome://foo/content/bar.xul", false, false, true],
-    ["feed:chrome://foo/content/bar.xul", false, false, false],
-    ["view-source:http://www.example2.com", false, false, true],
-    ["view-source:https://www.example2.com", false, false, true],
-    ["view-source:feed:http://www.example2.com", false, false, true],
-    ["feed:view-source:http://www.example2.com", false, false, false],
     ["data:text/html,Hi", true, false, true],
     ["view-source:data:text/html,Hi", false, false, true],
     ["javascript:alert('hi')", true, false, true],
     ["moz://a", false, false, true],
     ["about:test-chrome-privs", false, false, true],
     ["about:test-unknown-unlinkable", false, false, true],
     ["about:test-content-unlinkable", false, false, true],
     ["about:test-content-linkable", true, true, true],
     // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
     ["about:test-unknown-linkable", false, false, true],
   ]],
   ["view-source:http://www.example.com", [
     ["http://www.example2.com", true, true, true],
-    ["feed:http://www.example2.com", false, false, true],
     ["https://www.example2.com", true, true, true],
     ["moz-icon:file:///foo/bar/baz.exe", false, false, true],
     ["moz-icon://.exe", false, false, true],
-    ["feed:https://www.example2.com", false, false, true],
     ["chrome://foo/content/bar.xul", false, false, true],
-    ["feed:chrome://foo/content/bar.xul", false, false, false],
     ["view-source:http://www.example2.com", true, true, true],
     ["view-source:https://www.example2.com", true, true, true],
-    ["view-source:feed:http://www.example2.com", false, false, true],
-    ["feed:view-source:http://www.example2.com", false, false, false],
     ["data:text/html,Hi", true, false, true],
     ["view-source:data:text/html,Hi", true, false, true],
     ["javascript:alert('hi')", true, false, true],
     ["moz://a", false, false, true],
     ["about:test-chrome-privs", false, false, true],
     ["about:test-unknown-unlinkable", false, false, true],
     ["about:test-content-unlinkable", false, false, true],
     ["about:test-content-linkable", true, true, true],
@@ -284,21 +251,13 @@ add_task(async function() {
         testURL(contentPrincipal, contentBlobURI, true, true, true, baseFlags);
         testURL(contentPrincipal, contentBlobURI, true, true, true,
                 baseFlags | ssm.DISALLOW_INHERIT_PRINCIPAL);
 
         testURL(contentPrincipal, "view-source:" + contentBlobURI, false, false, true,
                 baseFlags);
         testURL(contentPrincipal, "view-source:" + contentBlobURI, false, false, true,
                 baseFlags | ssm.DISALLOW_INHERIT_PRINCIPAL);
-
-        // Feed URIs for blobs can't be created, so need to pass false as the fourth param.
-        for (let prefix of ["feed:", "view-source:feed:", "feed:view-source:"]) {
-          testURL(contentPrincipal, prefix + contentBlobURI, false, false, false,
-                  baseFlags);
-          testURL(contentPrincipal, prefix + contentBlobURI, false, false, false,
-                  baseFlags | ssm.DISALLOW_INHERIT_PRINCIPAL);
-        }
       }
     );
 
   });
 });
--- a/docshell/test/chrome/test_viewsource_forbidden_in_iframe.xul
+++ b/docshell/test/chrome/test_viewsource_forbidden_in_iframe.xul
@@ -127,44 +127,29 @@ https://bugzilla.mozilla.org/show_bug.cg
   var testCaseIndex = -1;
   testCases = [
     {
       desc: "Test 1: view-source should not be allowed in an iframe",
       protocols: "view-source:http",
       expectedProtocolList: "view-source, http"
     },
     {
-      desc: "Test 2: feed:view-source should not be allowed in an iframe",
-      protocols: "feed:view-source:http",
-      expectedProtocolList: "feed, view-source, http"
-    },
-    {
-      desc: "Test 3: jar:view-source should not be allowed in an iframe",
+      desc: "Test 2: jar:view-source should not be allowed in an iframe",
       protocols: "jar:view-source:http",
       expectedProtocolList: "jar, view-source, http"
     },
     {
-      desc: "Test 4: pcast:view-source should not be allowed in an iframe",
-      protocols: "pcast:view-source:http",
-      expectedProtocolList: "pcast, view-source, http"
-    },
-    {
-      desc: "Test 5: pcast:feed:view-source should not be allowed in an iframe",
-      protocols: "pcast:feed:view-source:http",
-      expectedProtocolList: "pcast, feed, view-source, http"
-    },
-    {
-      desc: "Test 6: if invalid protocol first should report before view-source",
+      desc: "Test 3: if invalid protocol first should report before view-source",
       protocols: "wibble:view-source:http",
       // Nothing after the invalid protocol gets set as a proper nested URI,
       // so the list stops there.
       expectedProtocolList: "wibble"
     },
     {
-      desc: "Test 7: if view-source first should report before invalid protocol",
+      desc: "Test 4: if view-source first should report before invalid protocol",
       protocols: "view-source:wibble:http",
       expectedProtocolList: "view-source, wibble"
     }
   ];
 
   function runNextTestCase() {
     ++testCaseIndex;
     if (testCaseIndex == testCases.length) {
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -864,25 +864,16 @@
     "record_in_processes": ["main", "content"],
     "alert_emails": ["seceng-telemetry@mozilla.com"],
     "expires_in_version": "60",
     "kind": "enumerated",
     "n_values": 16,
     "bug_numbers": [1239166],
     "description": "Status of Family Safety detection and remediation. See nsNSSComponent.cpp."
   },
-  "FEED_PROTOCOL_USAGE": {
-    "record_in_processes": ["main", "content"],
-    "alert_emails": ["jkt@mozilla.com"],
-    "bug_numbers": [1345546],
-    "expires_in_version": "60",
-    "kind": "enumerated",
-    "n_values": 8,
-    "description": "Usage counts of feed protocols used to load a page. (1=feed, 2=feed:http, 3=feed:https, 4=feed:brokenScheme, 5=pcast, 6=pcast:http, 7=pcast:https, 8=pcast:brokenScheme)"
-  },
   "FETCH_IS_MAINTHREAD": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "50",
     "kind": "boolean",
     "description": "Was Fetch request initiated from the main thread?"
   },
   "FORCED_DEVICE_RESET_REASON": {
     "record_in_processes": ["main", "content", "gpu"],