简体   繁体   中英

Firefox Restartless Addon: What information are available to the addon from AddonManager?

Certain information are passed to a restartless add-on

function startup(data, reason) { }

data = {
  id: "***********",
  version: "1.0",
  installPath: XPCWrappedNative_NoHelper, // nsIFile
  resourceURI: XPCWrappedNative_NoHelper, // nsIURI
  oldVersion: "1.0"
};

Are the above the only available data? Is it possible to get the Addon Name without accessing the AddonManager ?

My experience with AddonManager.jsm has proved it to be bulky and slow.[1]

In case above are the only available data, what is the best way to get a nsIURI for install.rdf in restartless addons (to be accessed with XHR)?

In overlay addons, I add a resource link pointing to the install.rdf . However, resource is not available in restartless addons and setting the following is not desirable

content   addon   ./

[1] Update: clarification/Correction:
The timed XHR fetch did not include XML parsing and data extraction. Therefore the overall operation (XHR, callback, responseXML, grab data) would take much longer.

Are the above the only available data?

Yes, apparently. Documentation , btw.

Is it possible to get the Addon Name without accessing the AddonManager?

No. (Well, you talk about parsing the install.rdf yourself, which would be a possibility, but IMHO a crappy one. AddonManager is the supported and recommended way; eg consider corner cases the meta-data, eg the meta-data incl. the name might have been refreshed from an online source).

My experience with AddonManager.jsm has proved it to be bulky and slow. For example, asynchronously parsing install.rdf with XHR takes about 1ms while getting the same data through AddonManager.jsm took 160-170ms. That is 160-170 times slower.

I honestly doubt your numbers. 1ms XHR?! Even the XHR setup takes longer than that, and even if the XPI (or flat install.rdf ) is already internally cached or at least in the OS disk cache, the I/O would take longer, even if you didn't parse it as XML and Regexp out what you need from the text contents.

Also, please note that the AddonManager has not necessarily initialized the meta data database when calling your startup() method. Calling any AddonManager query method at this point will force the initialization once , which means the first call can be a bit slow.

In general, you shouldn't request any data, eg the add-on name, until you actually need it, in particular during the startup.

In case above are the only available data, what is the best way to get a nsIURI for install.rdf in restartless addons (to be accessed with XHR)?

Using __SCRIPT_URI_SPEC__ or data.resourceURI :

const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");

// Using proper URI parsing
let selfURI = Services.io.newURI(__SCRIPT_URI_SPEC__, null, null);
let installRDF = Services.io.newURI("install.rdf", null, selfURI).spec;
Cu.reportError(installRDF);

// Or using string manipulation
let baseURISPEC = __SCRIPT_URI_SPEC__.substr(
    0,
    __SCRIPT_URI_SPEC__.length - "bootstrap.js".length
    );
let installRDF2 = baseURISPEC + "install.rdf";
Cu.reportError(installRDF2);
Cu.reportError((installRDF == installRDF2).toString()); // true

let installRDF = Services.io.newURI("install.rdf", null, selfURI).spec;
Cu.reportError(installRDF);

function startup(data) {
    // Or using bootstrap data
    let installRDF3 =
        Services.io.newURI("install.rdf", null, data.resourceURI).spec;
    Cu.reportError(installRDF3);
    Cu.reportError((installRDF == installRDF3).toString()); // true
}

__SCRIPT_URI_SPEC__ has the advantage that it is available immediately, not just in the entry point methods.

Edit I got curious, and time stuff.

[LOG] AM: 177, 18, 1, 1, 0, 0, 0, 0, 0, 1
[LOG] AM: avg 0.4
[LOG] AM: 168, 18, 1, 0, 0, 1, 0, 0, 0, 0
[LOG] AM: avg 0.3
[LOG] AM: 169, 21, 1, 0, 1, 0, 0, 0, 0, 0
[LOG] AM: avg 0.3


[LOG] XX: 160, 25, 25, 4, 1, 2, 2, 3, 1, 1
[LOG] XX: avg 30.9
[LOG] XX: 137, 20, 19, 4, 1, 2, 3, 2, 0, 1
[LOG] XX: avg 26.0
[LOG] XX: 145, 22, 25, 3, 2, 2, 2, 2, 1, 1
[LOG] XX: avg 25.1

So it turns out XHR isn't exactly faster. A tiny bit on the first access, a little worse on some subsequent runs (can be explained because it is somewhat costly and runs during startup where a lot of other stuff consumes resources as well), and after that the difference is negligible. But with XHR you still need to get the name from the DOM, while with AM it is just addon.name .

Here is my stupid micro benchmark:

const {classes: Cc, interfaces: Ci, utils: Cu, Constructor: CC} = Components;
Cu.import("resource://gre/modules/Services.jsm");

// Using proper URI parsing
let selfURI = Services.io.newURI(__SCRIPT_URI_SPEC__, null, null);
let installRDF = Services.io.newURI("install.rdf", null, selfURI).spec;
Cu.reportError(installRDF);

const XMLHttpRequest =
    CC("@mozilla.org/xmlextras/xmlhttprequest;1", "nsIXMLHttpRequest");

function log(s) {
    dump("[LOG] " + s + "\n");
}

function print(name, diffs) {
    log(name + ": " + diffs.join(", "));

    // Average, disregarding single best, and two worst
    diffs.sort();
    diffs.shift();
    diffs.pop();
    diffs.pop();
    let avg = diffs.reduce((c,p) => c + p, 0) / diffs.length;
    log(name + ": avg " + avg.toFixed(1));
}

function timeAM(id) {
    Cu.import("resource://gre/modules/AddonManager.jsm");
    let diffs = [];
    var run = function(x) {
        x = x || 0;
        let start = Date.now();
        AddonManager.getAddonByID(id, function(addon) {
            let d = Date.now() - start;
            diffs.push(d);
            if (++x == 10) {
                print("AM", diffs);
                return;
            }
            run(x);
        });
    };
    run();
}

function timeXHRXML() {
    Cu.import("resource://gre/modules/AddonManager.jsm");
    let diffs = [];
    let run = function(x) {
        x = x || 0;
        let start = Date.now();
        let r = new XMLHttpRequest();
        r.overrideMimeType("text/xml");
        r.open("GET", installRDF);
        r.onloadend = function() {
            let d = Date.now() - start;
            diffs.push(d);
            if (++x == 10) {
                print("XX", diffs);
                return;
            }
            run(x);
        };
        r.send();
    };
    run();
}

function startup(data) {
    Cu.reportError("in");
    //timeAM(data.id);
    timeXHRXML(data.id);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM