{"id":7769,"date":"2016-04-26T09:27:03","date_gmt":"2016-04-26T16:27:03","guid":{"rendered":"http:\/\/blog.mozilla.org\/addons\/?p=7769"},"modified":"2016-09-29T08:12:35","modified_gmt":"2016-09-29T15:12:35","slug":"migrating-popup-alt-attribute-from-xulxpcom-to-webextensions","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/","title":{"rendered":"Migrating Popup ALT Attribute from XUL\/XPCOM to WebExtensions"},"content":{"rendered":"<p><strong><em>Today\u2019s post comes from <a href=\"https:\/\/mozillians.org\/u\/Piro\/\" target=\"_blank\">Piro<\/a>, the developer of <a href=\"https:\/\/addons.mozilla.org\/firefox\/addon\/popup-alt-attribute\" target=\"_blank\">Popup ALT Attribute<\/a>, in addition to <a href=\"https:\/\/addons.mozilla.org\/firefox\/user\/piro-piro_or\/\" target=\"_blank\">40 other add-ons<\/a>. He shares his thoughts about migrating XUL\/XPCOM add-ons to WebExtensions, and shows us how he did it with Popup ALT Attribute. You can see the <a href=\"http:\/\/piro.sakura.ne.jp\/latest\/blosxom\/mozilla\/xul\/2016-04-19_webextensions.htm\" target=\"_blank\">full text<\/a> of this post on his personal blog.<\/em><\/strong><\/p>\n<p>***<\/p>\n<p>Hello, add-on developers. My name is <a href=\"https:\/\/github.com\/piroor\/\" target=\"_blank\">YUKI Hiroshi aka Piro<\/a>, a developer of Firefox add-ons. For many years I developed Firefox and Thunderbird add-ons <a href=\"https:\/\/addons.mozilla.org\/firefox\/user\/piro-piro_or\/#my-submissions\" target=\"_blank\">personally<\/a> and <a href=\"https:\/\/addons.mozilla.org\/firefox\/user\/clearcode-inc\/#my-submissions\" target=\"_blank\">for business<\/a>, based on XUL and XPCOM.<\/p>\n<p>I recently started to research the <a href=\"https:\/\/docs.google.com\/spreadsheets\/d\/1gn8fFl4iseOqLEz_UIEbHCEZ7R01VW2eDlxJaFRNKEo\" target=\"_blank\">APIs<\/a> are required to migrate my add-ons to WebExtensions, because Mozilla <a href=\"https:\/\/wiki.mozilla.org\/Add-ons\/developer\/communication\" target=\"_blank\">announced<\/a> that XUL\/XPCOM add-ons will be deprecated at the end of 2017. I realized that only some add-ons can be migrated with <a href=\"https:\/\/developer.mozilla.org\/Add-ons\/WebExtensions\" target=\"_blank\">currently available APIs<\/a>, and<br \/>\n<a href=\"https:\/\/addons.mozilla.org\/firefox\/addon\/popup-alt-attribute\" target=\"_blank\">Popup ALT Attribute<\/a> is one such add-on.<\/p>\n<p>Here is the story of how <a href=\"https:\/\/github.com\/piroor\/popupalt\/tree\/webextensions\" target=\"_blank\">I migrated it<\/a>.<\/p>\n<h2 id=\"toc_0\">What&#8217;s the add-on?<\/h2>\n<p>Popup ALT Attribute is an ancient add-on <a href=\"http:\/\/piro.sakura.ne.jp\/xul\/_popupalt.html.en#focused-folding-item%28folding-item-history-1%29\" target=\"_blank\">started in 2002<\/a>, to show what is written in the <code>alt<\/code> attribute of <code>img<\/code> HTML elements on web pages. By default, Firefox shows only the <code>title<\/code> attribute as a tooltip.<\/p>\n<p>Initially, the add-on was implemented to <a href=\"https:\/\/github.com\/piroor\/popupalt\/blob\/3615892354fe05f2cae6bab89708ee62854f36b8\/content\/popupalt\/popupalt.xul\" target=\"_blank\">replace<\/a> an internal function <code>FillInHTMLTooltip()<\/code> of Firefox itself.<\/p>\n<p>In February 2016, I migrated it to be e10s-compatible. It is worth noting that depending on your add-on, if you can migrate it directly to WebExtensions, it will be e10s-compatible by default.<\/p>\n<h2 id=\"toc_1\">Re-formatting in the WebExtensions style<\/h2>\n<p>I read the <a href=\"https:\/\/developer.mozilla.org\/Add-ons\/WebExtensions\/Your_first_WebExtension\" target=\"_blank\">tutorial<\/a> on how to build a new simple WebExtensions-based add-on from scratch before migration, and I realized that <a href=\"https:\/\/developer.mozilla.org\/Add-ons\/Bootstrapped_extensions\" target=\"_blank\">bootstrapped extensions<\/a> are similar to WebExtensions add-ons:<\/p>\n<ul>\n<li>They are dynamically installed and uninstalled.<\/li>\n<li>They are mainly based on JavaScript code and some static manifest files.<\/li>\n<\/ul>\n<p>My add-on was easily re-formatted as a WebExtensions add-on, because I already migrated it to bootstrapped.<\/p>\n<p>This is the initial version of the <code>manifest.json<\/code> I wrote. There were no localization and options UI:<\/p>\n<div>\n<pre><code class=\"language-none\">{\r\n  \"manifest_version\": 2,\r\n  \"name\": \"Popup ALT Attribute\",\r\n  \"version\": \"4.0a1\",\r\n  \"description\": \"Popups alternate texts of images or others like NetscapeCommunicator(Navigator) 4.x, and show long descriptions in the multi-row tooltip.\",\r\n  \"icons\": { \"32\": \"icons\/icon.png\" },\r\n  \"applications\": {\r\n    \"gecko\": { \"id\": \"{61FD08D8-A2CB-46c0-B36D-3F531AC53C12}\",\r\n               \"strict_min_version\": \"48.0a1\" }\r\n  },\r\n  \"content_scripts\": [\r\n    { \"all_frames\": true,\r\n      \"matches\": [\"&lt;all_urls&gt;\"],\r\n      \"js\": [\"content_scripts\/content.js\"],\r\n      \"run_at\": \"document_start\" }\r\n  ]\r\n}<\/code><\/pre>\n<\/div>\n<p>I had already separated the main script to <a href=\"https:\/\/github.com\/piroor\/popupalt\/blob\/ec119f8b56fb5b9680030ab1f25f5ff3f170dfbe\/content\/content-utils.js\" target=\"_blank\">a frame script<\/a> and <a href=\"https:\/\/github.com\/piroor\/popupalt\/blob\/ec119f8b56fb5b9680030ab1f25f5ff3f170dfbe\/modules\/popupalt.js\" target=\"_blank\">a loader for it<\/a>. On the other hand, <code>manifest.json<\/code> can have some manifest keys to describe how scripts are loaded. It means that I don&#8217;t need to put my custom loaders in the package anymore. Actually, a script for any web page can be loaded with the <code>content_scripts<\/code> rule in the above sample. See the <a href=\"https:\/\/developer.mozilla.org\/Add-ons\/WebExtensions\/manifest.json\/content_scripts\" target=\"_blank\">documentation<\/a> for <code>content_scripts<\/code> for more details.<\/p>\n<p>So finally only 3 files were left.<\/p>\n<p>Before:<\/p>\n<div>\n<pre><code class=\"language-none\">+ install.rdf\r\n+ icon.png\r\n+ [components]\r\n+ [modules]\r\n+ [content]\r\n    + content-utils.js<\/code><\/pre>\n<\/div>\n<p>And after:<\/p>\n<div>\n<pre><code class=\"language-none\">+ manifest.json (migrated from install.rdf)\r\n+ [icons]\r\n|   + icon.png (moved)\r\n+ [content_scripts]\r\n    + content.js (moved and migrated from content-utils.js)<\/code><\/pre>\n<\/div>\n<p>And I still had to isolate <a href=\"https:\/\/github.com\/piroor\/popupalt\/blob\/ec119f8b56fb5b9680030ab1f25f5ff3f170dfbe\/content\/content-utils.js\" target=\"_blank\">my frame script<\/a> from XPCOM.<\/p>\n<ul>\n<li>The script touched <code>nsIPrefBranch<\/code> and some XPCOM components via XPConnect, so they were temporarily commented out.<\/li>\n<li>User preferences were not available and only default configurations were there as fixed values.<\/li>\n<li>Some constant properties accessed, like <code>Ci.nsIDOMNode.ELEMENT_NODE<\/code>, had to be replaced as <code>Node.ELEMENT_NODE<\/code>.<\/li>\n<li>The listener for <code>mousemove<\/code> events from web pages was attached to the global namespace for a frame script, but it was re-attached to the <code>document<\/code> itself of each web page, because the script was now executed on each web page directly.<\/li>\n<\/ul>\n<h2 id=\"toc_2\">Localization<\/h2>\n<p>For the old <code>install.rdf<\/code> I had a localized description. In WebExtensions add-ons I had to do it in different way. See <a href=\"https:\/\/developer.mozilla.org\/Add-ons\/WebExtensions\/Internationalization\" target=\"_blank\">how to localize messages<\/a> for details. In short I did the following:<\/p>\n<p>Added files to define localized descriptions:<\/p>\n<div>\n<pre><code class=\"language-none\">+ manifest.json\r\n+ [icons]\r\n+ [content_scripts]\r\n+ [_locales]\r\n    + [en_US]\r\n    |   + messages.json (added)\r\n    + [ja]\r\n        + messages.json (added)<\/code><\/pre>\n<\/div>\n<p>Note, <code>en_US<\/code> is different from <code>en-US<\/code> in <code>install.rdf<\/code>.<\/p>\n<p>English locale, <code>_locales\/en_US\/messages.json<\/code> was:<\/p>\n<div>\n<pre><code class=\"language-none\">{\r\n  \"name\": { \"message\": \"Popup ALT Attribute\" },\r\n  \"description\": { \"message\": \"Popups alternate texts of images or others like NetscapeCommunicator(Navigator) 4.x, and show long descriptions in the multi-row tooltip.\" }\r\n}<\/code><\/pre>\n<\/div>\n<p>Japanese locale, <code>_locales\/ja\/messages.json<\/code> was also included. And, I had to update my <code>manifest.json<\/code> to embed localized messages:<\/p>\n<div>\n<pre><code class=\"language-none\">{\r\n  \"manifest_version\": 2,\r\n  \"name\": \"__MSG_name__\",\r\n  \"version\": \"4.0a1\",\r\n  \"description\": \"__MSG_description__\",\r\n  \"default_locale\": \"en_US\",\r\n  ...<\/code><\/pre>\n<\/div>\n<p><code>__MSG_****__<\/code> in string values are automatically replaced to localized messages. You need to specify the default locale manually via the <code>default_locale<\/code> key.<\/p>\n<p>Sadly, Firefox 45 does not support the localization feature, so you need to use Nightly 48.0a1 or newer to try localization.<\/p>\n<h2 id=\"toc_3\">User preferences<\/h2>\n<p>Currently, WebExtensions does not provide any feature completely compatible to <code>nsIPrefBranch<\/code>. Instead, there are <a href=\"https:\/\/developer.mozilla.org\/Add-ons\/WebExtensions\/API\/storage\" target=\"_blank\">simple storage APIs<\/a>. It can be used like an alternative of <code>nsIPrefBranch<\/code> to set\/get user preferences. This add-on had no configuration UI but had some secret preferences to control its advanced features, so I did it for future migrations of my other add-ons, as a trial.<\/p>\n<p>Then I encountered a large limitation: <em>the storage API is <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=1197346\" target=\"_blank\">not available in content scripts<\/a>.<\/em> I had to create a background script just to access the storage, and communicate with it via the <a href=\"https:\/\/developer.mozilla.org\/Add-ons\/WebExtensions\/API\/runtime\" target=\"_blank\">inter-sandboxes messaging system<\/a>. <em>[Updated 4\/27\/16: <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=1197346\" target=\"_blank\">bug 1197346<\/a> has been fixed on Nightly 49.0a1, so now you don&#8217;t need any hack to access the storage system from content scripts anymore. Now, my library (Configs.js) just provides easy access for configuration values instead of the native storage API.]<\/em><\/p>\n<p>Finally, I created a <a href=\"https:\/\/github.com\/piroor\/webextensions-lib-configs\" target=\"_blank\">tiny library<\/a> to do that. I don&#8217;t describe how I did it here, but if you hope to know details, please see <a href=\"https:\/\/github.com\/piroor\/webextensions-lib-configs\/blob\/master\/Configs.js\" target=\"_blank\">the source<\/a>. There are just 177 lines.<\/p>\n<p>I had to update my <code>manifest.json<\/code> to use the library from both the background page and the content script, like:<\/p>\n<div>\n<pre><code class=\"language-none\">  \"background\": {\r\n    \"scripts\": [\r\n      \"common\/Configs.js\", \/* the library itself *\/\r\n      \"common\/common.js\"   \/* codes to use the library *\/\r\n    ]\r\n  },\r\n  \"content_scripts\": [\r\n    { \"all_frames\": true,\r\n      \"matches\": [\"&lt;all_urls&gt;\"],\r\n      \"js\": [\r\n        \"common\/Configs.js\", \/* the library itself *\/\r\n        \"common\/common.js\",  \/* codes to use the library *\/\r\n        \"content_scripts\/content.js\"\r\n      ],\r\n      \"run_at\": \"document_start\" }\r\n  ]<\/code><\/pre>\n<\/div>\n<p>Scripts listed in the same section share a namespace for the section. I didn&#8217;t have to write any code like <code>require()<\/code> to load a script from others. Instead, I had to be careful about the listing order of scripts, and wrote a script requiring a library after the library itself, in each list.<\/p>\n<p>One last problem was: how to do something like the <code>about:config<\/code> or the <a href=\"https:\/\/developer.mozilla.org\/docs\/MCD,_Mission_Control_Desktop_AKA_AutoConfig\" target=\"_blank\">MCD<\/a>\u00a0\u2014 general methods to control secret preferences across add-ons.<\/p>\n<p>For my business clients, I usually provide add-ons and use MCD to lock their configurations. (There are some common requirements for business use of Firefox, so combinations of add-ons and MCD are more reasonable than creating private builds of Firefox with different configurations for each client.)<\/p>\n<p>I think I still have to research around this point.<\/p>\n<h2 id=\"toc_4\">Options UI<\/h2>\n<p>WebExtensions provides a feature to <a href=\"https:\/\/developer.mozilla.org\/Add-ons\/WebExtensions\/manifest.json\/options_ui\" target=\"_blank\">create options pages<\/a> for add-ons. It is also not supported on Firefox 45, so you need to use Nightly 48.0a1 for now. As I previously said, this add-on didn&#8217;t have its configuration UI, but I implemented it as a trial.<\/p>\n<p>In XUL\/XPCOM add-ons, rich UI elements like <code>&lt;checkbox&gt;<\/code>, <code>&lt;textbox&gt;<\/code>, <code>&lt;menulist&gt;<\/code>, and more are available, but these are going away at the end of next year. So I had to implement a custom configuration UI based on pure HTML and JavaScript. (If you need more rich UI elements, some known libraries for web applications will help you.)<\/p>\n<p>On this step I created two libraries:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/piroor\/webextensions-lib-options\" target=\"_blank\">A helper to bind configurations to UI elements<\/a>.<\/li>\n<li><a href=\"https:\/\/github.com\/piroor\/webextensions-lib-l10n\" target=\"_blank\">A helper to apply localized messages to a static HTML<\/a>.<\/li>\n<\/ul>\n<h2 id=\"toc_5\">Conclusion<\/h2>\n<p>I&#8217;ve successfully migrated my Popup ALT Attribute add-on from XUL\/XPCOM to WebExtensions. Now it is <a href=\"https:\/\/github.com\/piroor\/popupalt\/tree\/webextensions\" target=\"_blank\">just a branch<\/a> but I&#8217;ll release it after Firefox 48 is available.<\/p>\n<p>Here are reasons why I could do it:<\/p>\n<ul>\n<li>It was a bootstrapped add-on, so I had already isolated the add-on from all destructive changes.<\/li>\n<li>The core implementation of the add-on was similar to a simple user script. Essential actions of the add-on were enclosed inside the content area, and no privilege was required to do that.<\/li>\n<\/ul>\n<p>However, it is a rare case for me. My other 40+ add-ons require some privilege, and\/or they work outside the content area. Most of my cases are such <a href=\"https:\/\/docs.google.com\/spreadsheets\/d\/1gn8fFl4iseOqLEz_UIEbHCEZ7R01VW2eDlxJaFRNKEo\" target=\"_blank\">non-typical add-ons<\/a>.<\/p>\n<p>I have to do triage, plan, and request <a href=\"https:\/\/wiki.mozilla.org\/WebExtensions\/NewAPIs\" target=\"_blank\">new APIs<\/a> not only for me but for other XUL\/XPCOM add-on developers also.<\/p>\n<p>Thank you for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today\u2019s post comes from Piro, the developer of Popup ALT Attribute, in addition to 40 other add-ons. He shares his thoughts about migrating XUL\/XPCOM add-ons to WebExtensions, and shows us &hellip; <a class=\"go\" href=\"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/\">Read more<\/a><\/p>\n","protected":false},"author":377,"featured_media":7917,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[44,278890,7119,742,278886],"tags":[9406,52],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Migrating Popup ALT Attribute from XUL\/XPCOM to WebExtensions - 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\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Amy Tsay\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/\",\"url\":\"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/\",\"name\":\"Migrating Popup ALT Attribute from XUL\/XPCOM to WebExtensions - Mozilla Add-ons Community Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blog.mozilla.org\/addons\/files\/2016\/04\/piro.png\",\"datePublished\":\"2016-04-26T16:27:03+00:00\",\"dateModified\":\"2016-09-29T15:12:35+00:00\",\"author\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/becbc6e5c1f9ed8217c36233bc1a7bec\"},\"breadcrumb\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/#primaryimage\",\"url\":\"https:\/\/blog.mozilla.org\/addons\/files\/2016\/04\/piro.png\",\"contentUrl\":\"https:\/\/blog.mozilla.org\/addons\/files\/2016\/04\/piro.png\",\"width\":800,\"height\":800},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.mozilla.org\/addons\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Migrating Popup ALT Attribute from XUL\/XPCOM to WebExtensions\"}]},{\"@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\/becbc6e5c1f9ed8217c36233bc1a7bec\",\"name\":\"Amy Tsay\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/db8d681801f2c6406fb3e53d48db2909?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/db8d681801f2c6406fb3e53d48db2909?s=96&d=mm&r=g\",\"caption\":\"Amy Tsay\"},\"description\":\"Lead for Firefox Add-ons at Mozilla.\",\"sameAs\":[\"https:\/\/x.com\/catchingamy\"],\"url\":\"https:\/\/blog.mozilla.org\/addons\/author\/atsaymozilla-com\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Migrating Popup ALT Attribute from XUL\/XPCOM to WebExtensions - 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\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/","twitter_misc":{"Written by":"Amy Tsay","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/","url":"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/","name":"Migrating Popup ALT Attribute from XUL\/XPCOM to WebExtensions - Mozilla Add-ons Community Blog","isPartOf":{"@id":"https:\/\/blog.mozilla.org\/addons\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/#primaryimage"},"image":{"@id":"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.mozilla.org\/addons\/files\/2016\/04\/piro.png","datePublished":"2016-04-26T16:27:03+00:00","dateModified":"2016-09-29T15:12:35+00:00","author":{"@id":"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/becbc6e5c1f9ed8217c36233bc1a7bec"},"breadcrumb":{"@id":"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/#primaryimage","url":"https:\/\/blog.mozilla.org\/addons\/files\/2016\/04\/piro.png","contentUrl":"https:\/\/blog.mozilla.org\/addons\/files\/2016\/04\/piro.png","width":800,"height":800},{"@type":"BreadcrumbList","@id":"https:\/\/blog.mozilla.org\/addons\/2016\/04\/26\/migrating-popup-alt-attribute-from-xulxpcom-to-webextensions\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.mozilla.org\/addons\/"},{"@type":"ListItem","position":2,"name":"Migrating Popup ALT Attribute from XUL\/XPCOM to WebExtensions"}]},{"@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\/becbc6e5c1f9ed8217c36233bc1a7bec","name":"Amy Tsay","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/db8d681801f2c6406fb3e53d48db2909?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/db8d681801f2c6406fb3e53d48db2909?s=96&d=mm&r=g","caption":"Amy Tsay"},"description":"Lead for Firefox Add-ons at Mozilla.","sameAs":["https:\/\/x.com\/catchingamy"],"url":"https:\/\/blog.mozilla.org\/addons\/author\/atsaymozilla-com\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/posts\/7769"}],"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\/377"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/comments?post=7769"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/posts\/7769\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/media\/7917"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/media?parent=7769"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/categories?post=7769"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/tags?post=7769"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}