code: function getDetails(addonPath) {
    return readManifest(addonPath).then(function(doc) {
      var em = getNamespaceId(doc, 'http://www.mozilla.org/2004/em-rdf#');
      var rdf = getNamespaceId(
          doc, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
  
      var description = doc[rdf + 'RDF'][rdf + 'Description'][0];
      var details = {
        id: getNodeText(description, em + 'id'),
        name: getNodeText(description, em + 'name'),
        version: getNodeText(description, em + 'version'),
        unpack: getNodeText(description, em + 'unpack') || false
      };
  
      if (typeof details.unpack === 'string') {
        details.unpack = details.unpack.toLowerCase() === 'true';
      }
  
      if (!details.id) {
        throw new AddonFormatError('Could not find add-on ID for ' + addonPath);
      }
  
      return details;
    });
  
    function getNodeText(node, name) {
      return node[name] && node[name][0] || '';
    }
  
    function getNamespaceId(doc, url) {
      var keys = Object.keys(doc);
      if (keys.length !== 1) {
        throw new AddonFormatError('Malformed manifest for add-on ' + addonPath);
      }
  
      var namespaces = doc[keys[0]].$;
      var id = '';
      Object.keys(namespaces).some(function(ns) {
        if (namespaces[ns] !== url) {
          return false;
        }
  
        if (ns.indexOf(':') != -1) {
          id = ns.split(':')[1] + ':';
        }
        return true;
      });
      return id;
    }
  }
docs: Extracts the details needed to install an add-on.
  @param {string} addonPath Path to the extension directory.
  @return {!promise.Promise.<!AddonDetails>} A promise for the add-on details.