{"id":4294,"date":"2012-02-16T16:33:06","date_gmt":"2012-02-17T00:33:06","guid":{"rendered":"http:\/\/blog.mozilla.org\/addons\/?p=4294"},"modified":"2012-02-21T07:30:47","modified_gmt":"2012-02-21T15:30:47","slug":"using-jsm-modules-in-the-sdk","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/","title":{"rendered":"Using Javascript ( *.jsm ) modules in the SDK"},"content":{"rendered":"<p>The ability of developers using the SDK <a href=\"https:\/\/addons.mozilla.org\/en-US\/developers\/docs\/sdk\/1.4\/dev-guide\/addon-development\/xul-migration.html#xpcom\" target=\"_blank\">to get chrome authority<\/a> and access xpcom services is a key feature. The SDK was designed from the start with the assumption that some developers will always need access to the underlying Mozilla platform. While xpcom is the main way to access low level apis, a lot of functionality in Firefox is instead implemented as <a href=\"https:\/\/developer.mozilla.org\/en\/JavaScript_code_modules\" target=\"_blank\">JavaScript Modules<\/a>, and can be used in your code much more naturally than xpcom services because they are just JavaScript, and from a design perspective quite similar to CommonJS modules.<\/p>\n<p>Here&#8217;s a code snippet that you can use to import a jsm into your code:<\/p>\n<pre lang=\"javascript\">\r\nconst { Cu } = require(\"chrome\");\r\n\r\nlet AddonManager = Cu.import(\"resource:\/\/gre\/modules\/AddonManager.jsm\").AddonManager;\r\n\r\nAddonManager.getAddonsByTypes([\"extension\"], function(addons) {\r\n    var addonData = [];\r\n\r\n    for (let i in addons) {\r\n\t\tlet cur = addons[i];\r\n\t\taddonData.push({\r\n\t\t\tid: cur.id.toString(),\r\n\t\t\tname: cur.name,\r\n\t\t});\r\n\t};\r\n\tconsole.log(JSON.stringify(addonData, null, '   '));\r\n});\r\n<\/pre>\n<p><!--more--><br \/>\nThe code requires chrome in order to get the Cu object ( Components.Utils ) and then imports the AddonManager module. Nice and easy! The only real problem with adding code like this to your add-on is that getting chrome authority to access Cu has review implications on AMO, and we in the Jetpack team want to do everything we can to get your add-ons reviewed as quickly as possible.<\/p>\n<p>With that in mind, we have been considering including a utility function in the SDK that allows developers to import jsm modules without having to get chrome authority. <a href=\"https:\/\/wiki.mozilla.org\/User:BenB\" target=\"_blank\">Ben Buksch<\/a>  contributed this code snippet <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=725412#c4\" target=\"_blank\">in a bug<\/a> that neatly abstracts the small amount of chrome-level code into a single function:<\/p>\n<pre lang=\"javascript\">\r\nconst { Cu } = require(\"chrome\");\r\n\/**\r\n * Imports a JS Module using Components.utils.import()\r\n * and returns the scope, similar to Jetpack require().\r\n *\r\n * @param targetScope {Object} (optional)\r\n *     If null, the scope will just be returned\r\n *     and *not* added to the global scope.\r\n *     If given, all functions\/objects from the JSM will be\r\n *     imported directly in |targetScope|, so that you\r\n *     can do e.g.\r\n *       requireJSM(\"url\", this)\r\n *       someFuncFromJSM();\r\n *     which will have the same effect as\r\n *       Components.utils.import(\"url\");\r\n *       someFuncFromJSM();\r\n *     in normal Mozilla code, but the latter won't work in Jetpack code.\r\n *\/\r\nfunction requireJSM(url, targetScope)\r\n{\r\n  var scope = targetScope ? targetScope : {};\r\n  return Cu.import(url, scope);\r\n  return scope;\r\n}\r\n<\/pre>\n<p>I&#8217;ve created a Jetpack module on Builder that you can use to load Javascript modules using Ben&#8217;s code:<\/p>\n<p><a href=\"https:\/\/builder.addons.mozilla.org\/library\/1040049\/latest\" target=\"_blank\">https:\/\/builder.addons.mozilla.org\/library\/1040049\/latest<\/a><\/p>\n<p>I&#8217;ve also created this example addon that uses my module:<\/p>\n<p><a href=\"https:\/\/builder.addons.mozilla.org\/addon\/1040048\/latest\/\" target=\"_blank\">https:\/\/builder.addons.mozilla.org\/addon\/1040048\/latest\/<\/a><\/p>\n<p>Here is the above code, re-factored to use my module:<\/p>\n<pre lang=\"javascript\">\r\n\r\nlet requireJSM = require(\"jsmutils\/jsmutils\").requireJSM;\r\nlet AddonManager = requireJSM(\"resource:\/\/gre\/modules\/AddonManager.jsm\").AddonManager;\r\n\r\nAddonManager.getAddonsByTypes([\"extension\"], function(addons) {\r\n\tvar addonData = [];\r\n\r\n\tfor (let i in addons) {\r\n\t\tlet cur = addons[i];\r\n\t\taddonData.push({\r\n\t\t\tid: cur.id.toString(),\r\n\t\t\tname: cur.name,\r\n\t\t});\r\n\t};\r\n\tconsole.log(JSON.stringify(addonData, null, '   '));\r\n});\r\n<\/pre>\n<p>I know what you&#8217;re thinking &#8211; there isn&#8217;t really any less code involved using the abstracted module. I would argue that the advantage is instead that I have isolated the part of my code that needs chrome authority to a single, small file that is very easy to understand. This is better separation and greatly aids the ability of our add-on reviewers to quickly understand your code and any security implications it might have.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The ability of developers using the SDK to get chrome authority and access xpcom services is a key feature. The SDK was designed from the start with the assumption that &hellip; <a class=\"go\" href=\"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/\">Read more<\/a><\/p>\n","protected":false},"author":316,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[44,588,742],"tags":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Using Javascript ( *.jsm ) modules in the SDK - Mozilla Add-ons Community Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeff Griffiths\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/\",\"url\":\"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/\",\"name\":\"Using Javascript ( *.jsm ) modules in the SDK - Mozilla Add-ons Community Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#website\"},\"datePublished\":\"2012-02-17T00:33:06+00:00\",\"dateModified\":\"2012-02-21T15:30:47+00:00\",\"author\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/e2f4c71eb45392ea29162432c3f1d433\"},\"breadcrumb\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.mozilla.org\/addons\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using Javascript ( *.jsm ) modules in the SDK\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#website\",\"url\":\"https:\/\/blog.mozilla.org\/addons\/\",\"name\":\"Mozilla Add-ons Community Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.mozilla.org\/addons\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/e2f4c71eb45392ea29162432c3f1d433\",\"name\":\"Jeff Griffiths\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b07ae75dd1a5414bf30d7f773ccfc894?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b07ae75dd1a5414bf30d7f773ccfc894?s=96&d=mm&r=g\",\"caption\":\"Jeff Griffiths\"},\"description\":\"Jeff is Product Manager for the Firefox Developer Tools and occasional Open Web hacker, based in Vancouver, BC.\",\"sameAs\":[\"http:\/\/canuckistani.ca\/\",\"https:\/\/x.com\/canuckistani\"],\"url\":\"https:\/\/blog.mozilla.org\/addons\/author\/jgriffithsmozilla-com\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Using Javascript ( *.jsm ) modules in the SDK - Mozilla Add-ons Community Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/","twitter_misc":{"Written by":"Jeff Griffiths","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/","url":"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/","name":"Using Javascript ( *.jsm ) modules in the SDK - Mozilla Add-ons Community Blog","isPartOf":{"@id":"https:\/\/blog.mozilla.org\/addons\/#website"},"datePublished":"2012-02-17T00:33:06+00:00","dateModified":"2012-02-21T15:30:47+00:00","author":{"@id":"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/e2f4c71eb45392ea29162432c3f1d433"},"breadcrumb":{"@id":"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.mozilla.org\/addons\/2012\/02\/16\/using-jsm-modules-in-the-sdk\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.mozilla.org\/addons\/"},{"@type":"ListItem","position":2,"name":"Using Javascript ( *.jsm ) modules in the SDK"}]},{"@type":"WebSite","@id":"https:\/\/blog.mozilla.org\/addons\/#website","url":"https:\/\/blog.mozilla.org\/addons\/","name":"Mozilla Add-ons Community Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.mozilla.org\/addons\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/e2f4c71eb45392ea29162432c3f1d433","name":"Jeff Griffiths","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/b07ae75dd1a5414bf30d7f773ccfc894?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b07ae75dd1a5414bf30d7f773ccfc894?s=96&d=mm&r=g","caption":"Jeff Griffiths"},"description":"Jeff is Product Manager for the Firefox Developer Tools and occasional Open Web hacker, based in Vancouver, BC.","sameAs":["http:\/\/canuckistani.ca\/","https:\/\/x.com\/canuckistani"],"url":"https:\/\/blog.mozilla.org\/addons\/author\/jgriffithsmozilla-com\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/posts\/4294"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/users\/316"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/comments?post=4294"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/posts\/4294\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/media?parent=4294"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/categories?post=4294"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/tags?post=4294"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}