Bug 1351385, part 4 - Move the JSON sniffer out of its own file. r=Honza draft
authorAndrew McCreight <continuation@gmail.com>
Tue, 28 Mar 2017 11:32:34 -0700
changeset 553745 2ea14fbab5265940e9f87c81af179bed72418f41
parent 553744 0ec522ded57624593b2388370fa3d290ebc6a4f6
child 553902 ba42f6e5cfcd3c77ccca1f4682d722319c250541
child 555065 cdefc81affbc221f08f3074980b7eebce2d8ec84
push id51748
push userbmo:continuation@gmail.com
push dateThu, 30 Mar 2017 15:33:10 +0000
reviewersHonza
bugs1351385
milestone55.0a1
Bug 1351385, part 4 - Move the JSON sniffer out of its own file. r=Honza The sniffer is always run. By moving it out of its own file we can avoid importing the devtools loader system at startup, which uses a number of compartments. MozReview-Commit-ID: IoMIzZeRDo2
devtools/client/jsonview/converter-observer.js
devtools/client/jsonview/converter-sniffer.js
devtools/client/jsonview/moz.build
--- a/devtools/client/jsonview/converter-observer.js
+++ b/devtools/client/jsonview/converter-observer.js
@@ -1,16 +1,17 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=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/. */
 
 "use strict";
 
+const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cm = Components.manager;
 const Cr = Components.results;
 const Cu = Components.utils;
 
 const {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
 const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
 
@@ -21,29 +22,98 @@ XPCOMUtils.defineLazyGetter(this, "devto
 });
 
 // Load JsonView services lazily.
 XPCOMUtils.defineLazyGetter(this, "JsonViewService", function () {
   const {JsonViewService} = devtools.require("devtools/client/jsonview/converter-child");
   return JsonViewService;
 });
 
-XPCOMUtils.defineLazyGetter(this, "JsonViewSniffer", function () {
-  const {JsonViewSniffer} = devtools.require("devtools/client/jsonview/converter-sniffer");
-  return JsonViewSniffer;
-});
-
 // Constants
 const JSON_VIEW_PREF = "devtools.jsonview.enabled";
 const JSON_VIEW_MIME_TYPE = "application/vnd.mozilla.json.view";
 const JSON_VIEW_CONTRACT_ID = "@mozilla.org/streamconv;1?from=" +
   JSON_VIEW_MIME_TYPE + "&to=*/*";
 const JSON_VIEW_CLASS_ID = Components.ID("{d8c9acee-dec5-11e4-8c75-1681e6b88ec1}");
 const JSON_VIEW_CLASS_DESCRIPTION = "JSONView converter";
 
+const JSON_SNIFFER_CONTRACT_ID = "@mozilla.org/devtools/jsonview-sniffer;1";
+const JSON_SNIFFER_CLASS_ID = Components.ID("{4148c488-dca1-49fc-a621-2a0097a62422}");
+const JSON_SNIFFER_CLASS_DESCRIPTION = "JSONView content sniffer";
+const JSON_VIEW_TYPE = "JSON View";
+const CONTENT_SNIFFER_CATEGORY = "net-content-sniffers";
+
+/**
+ * This component represents a sniffer (implements nsIContentSniffer
+ * interface) responsible for changing top level 'application/json'
+ * document types to: 'application/vnd.mozilla.json.view'.
+ *
+ * This internal type is consequently rendered by JSON View component
+ * that represents the JSON through a viewer interface.
+ *
+ * This is done in the .js file rather than a .jsm to avoid creating
+ * a compartment at startup when no JSON is being viewed.
+ */
+function JsonViewSniffer() {}
+
+JsonViewSniffer.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentSniffer]),
+
+  get wrappedJSObject() {
+    return this;
+  },
+
+  isTopLevelLoad: function (request) {
+    let loadInfo = request.loadInfo;
+    if (loadInfo && loadInfo.isTopLevelLoad) {
+      return (request.loadFlags & Ci.nsIChannel.LOAD_DOCUMENT_URI);
+    }
+    return false;
+  },
+
+  getMIMETypeFromContent: function (request, data, length) {
+    if (request instanceof Ci.nsIChannel) {
+      // JSON View is enabled only for top level loads only.
+      if (!this.isTopLevelLoad(request)) {
+        return "";
+      }
+      try {
+        if (request.contentDisposition ==
+          Ci.nsIChannel.DISPOSITION_ATTACHMENT) {
+          return "";
+        }
+      } catch (e) {
+        // Channel doesn't support content dispositions
+      }
+
+      // Check the response content type and if it's a valid type
+      // such as application/json or application/manifest+json
+      // change it to new internal type consumed by JSON View.
+      const JSON_TYPES = ["application/json", "application/manifest+json"];
+      if (JSON_TYPES.includes(request.contentType)) {
+        return JSON_VIEW_MIME_TYPE;
+      }
+    }
+
+    return "";
+  }
+};
+
+/*
+ * Create instances of the JSON view sniffer.
+ */
+const JsonSnifferFactory = {
+  createInstance: function (outer, iid) {
+    if (outer) {
+      throw Cr.NS_ERROR_NO_AGGREGATION;
+    }
+    return new JsonViewSniffer();
+  }
+};
+
 /*
  * Create instances of the JSON view converter.
  * This is done in the .js file rather than a .jsm to avoid creating
  * a compartment at startup when no JSON is being viewed.
  */
 const JsonViewFactory = {
   createInstance: function (outer, iid) {
     if (outer) {
@@ -93,31 +163,48 @@ ConverterObserver.prototype = {
     if (this.isEnabled()) {
       this.register();
     } else {
       this.unregister();
     }
   },
 
   register: function () {
-    JsonViewSniffer.register();
+    const registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
 
-    const registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+    if (!registrar.isCIDRegistered(JSON_SNIFFER_CLASS_ID)) {
+      registrar.registerFactory(JSON_SNIFFER_CLASS_ID,
+        JSON_SNIFFER_CLASS_DESCRIPTION,
+        JSON_SNIFFER_CONTRACT_ID,
+        JsonSnifferFactory);
+      const categoryManager = Cc["@mozilla.org/categorymanager;1"]
+        .getService(Ci.nsICategoryManager);
+      categoryManager.addCategoryEntry(CONTENT_SNIFFER_CATEGORY, JSON_VIEW_TYPE,
+        JSON_SNIFFER_CONTRACT_ID, false, false);
+    }
+
     if (!registrar.isCIDRegistered(JSON_VIEW_CLASS_ID)) {
       registrar.registerFactory(JSON_VIEW_CLASS_ID,
         JSON_VIEW_CLASS_DESCRIPTION,
         JSON_VIEW_CONTRACT_ID,
         JsonViewFactory);
     }
   },
 
   unregister: function () {
-    JsonViewSniffer.unregister();
+    const registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
 
-    const registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+    if (registrar.isCIDRegistered(JSON_SNIFFER_CLASS_ID)) {
+      registrar.unregisterFactory(JSON_SNIFFER_CLASS_ID, JsonSnifferFactory);
+      const categoryManager = Cc["@mozilla.org/categorymanager;1"]
+        .getService(Ci.nsICategoryManager);
+      categoryManager.deleteCategoryEntry(CONTENT_SNIFFER_CATEGORY,
+        JSON_VIEW_TYPE, false);
+    }
+
     if (registrar.isCIDRegistered(JSON_VIEW_CLASS_ID)) {
       registrar.unregisterFactory(JSON_VIEW_CLASS_ID, JsonViewFactory);
     }
   },
 
   isEnabled: function () {
     return Services.prefs.getBoolPref(JSON_VIEW_PREF);
   },
deleted file mode 100644
--- a/devtools/client/jsonview/converter-sniffer.js
+++ /dev/null
@@ -1,113 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set ft=javascript ts=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/. */
-
-"use strict";
-
-const {Cc, Ci, Cu, Cm, Cr, components} = require("chrome");
-const registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
-const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
-
-const categoryManager = Cc["@mozilla.org/categorymanager;1"]
-  .getService(Ci.nsICategoryManager);
-
-// Constants
-const JSON_TYPES = ["application/json", "application/manifest+json"];
-const JSON_SNIFFER_CONTRACT_ID = "@mozilla.org/devtools/jsonview-sniffer;1";
-const JSON_SNIFFER_CLASS_ID = components.ID("{4148c488-dca1-49fc-a621-2a0097a62422}");
-const JSON_SNIFFER_CLASS_DESCRIPTION = "JSONView content sniffer";
-const JSON_VIEW_MIME_TYPE = "application/vnd.mozilla.json.view";
-const JSON_VIEW_TYPE = "JSON View";
-const CONTENT_SNIFFER_CATEGORY = "net-content-sniffers";
-
-function isTopLevelLoad(request) {
-  let loadInfo = request.loadInfo;
-  if (loadInfo && loadInfo.isTopLevelLoad) {
-    return (request.loadFlags & Ci.nsIChannel.LOAD_DOCUMENT_URI);
-  }
-  return false;
-}
-
-/**
- * This component represents a sniffer (implements nsIContentSniffer
- * interface) responsible for changing top level 'application/json'
- * document types to: 'application/vnd.mozilla.json.view'.
- *
- * This internal type is consequently rendered by JSON View component
- * that represents the JSON through a viewer interface.
- */
-function JsonSniffer() {}
-
-JsonSniffer.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentSniffer]),
-
-  get wrappedJSObject() {
-    return this;
-  },
-
-  getMIMETypeFromContent: function (request, data, length) {
-    if (request instanceof Ci.nsIChannel) {
-      // JSON View is enabled only for top level loads only.
-      if (!isTopLevelLoad(request)) {
-        return "";
-      }
-      try {
-        if (request.contentDisposition ==
-          Ci.nsIChannel.DISPOSITION_ATTACHMENT) {
-          return "";
-        }
-      } catch (e) {
-        // Channel doesn't support content dispositions
-      }
-
-      // Check the response content type and if it's a valid type
-      // such as application/json or application/manifest+json
-      // change it to new internal type consumed by JSON View.
-      if (JSON_TYPES.includes(request.contentType)) {
-        return JSON_VIEW_MIME_TYPE;
-      }
-    }
-
-    return "";
-  }
-};
-
-const JsonSnifferFactory = {
-  createInstance: function (outer, iid) {
-    if (outer) {
-      throw Cr.NS_ERROR_NO_AGGREGATION;
-    }
-    return new JsonSniffer();
-  }
-};
-
-function register() {
-  if (!registrar.isCIDRegistered(JSON_SNIFFER_CLASS_ID)) {
-    registrar.registerFactory(JSON_SNIFFER_CLASS_ID,
-      JSON_SNIFFER_CLASS_DESCRIPTION,
-      JSON_SNIFFER_CONTRACT_ID,
-      JsonSnifferFactory);
-    categoryManager.addCategoryEntry(CONTENT_SNIFFER_CATEGORY, JSON_VIEW_TYPE,
-      JSON_SNIFFER_CONTRACT_ID, false, false);
-    return true;
-  }
-
-  return false;
-}
-
-function unregister() {
-  if (registrar.isCIDRegistered(JSON_SNIFFER_CLASS_ID)) {
-    registrar.unregisterFactory(JSON_SNIFFER_CLASS_ID, JsonSnifferFactory);
-    categoryManager.deleteCategoryEntry(CONTENT_SNIFFER_CATEGORY,
-      JSON_VIEW_TYPE, false);
-    return true;
-  }
-  return false;
-}
-
-exports.JsonViewSniffer = {
-  register: register,
-  unregister: unregister
-};
--- a/devtools/client/jsonview/moz.build
+++ b/devtools/client/jsonview/moz.build
@@ -8,17 +8,16 @@ DIRS += [
     'components',
     'css',
     'lib'
 ]
 
 DevToolsModules(
     'converter-child.js',
     'converter-observer.js',
-    'converter-sniffer.js',
     'json-viewer.js',
     'main.js',
     'utils.js',
     'viewer-config.js'
 )
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']