2013-08-21 15 views
5

Ich habe eine bootstrapped Erweiterung für Firefox. Und jetzt möchte ich nsIContentPolicy XPCOM-Komponente implementieren. Ich habe einen Komponentenmodul-Code geschrieben. Und jetzt möchte ich diese Komponente registrieren. Der Grund, warum ich die Komponente registrieren möchte, ist, dass ich meine Komponente nsICategoryManager.addCategoryEntry mit der Kategorie "content-policy" hinzufügen möchte.Wie zu implementieren XPCOM-Komponente (NSIContentPolicy) in bootstrapped Firefox-Erweiterung

var {Cc, Ci, Cu} = require("chrome"); 

Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 

//console.error("Running interceptor"); 

function Interceptor() 
} 

Interceptor.prototype = { 

    classDescription: "DeferredTo HTTP requests Interceptor", 
    classID: "{B5B3D9A0-08FC-11E3-8253-5EF06188709B}", 
    contractID: "@deferredto.com/Interceptor;1", 
    QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy]), 

    shouldLoad : function dt_shouldLoad(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra) { 
     console.log("dt_shouldLoad"); 

     if (contentLocation.scheme != "http" && contentLocation.scheme != "https") 
      return Ci.nsIContentPolicy.ACCEPT; 

     let result = Ci.nsIContentPolicy.ACCEPT; 

     // we should check for TYPE_SUBDOCUMENT as well if we want frames. 
     if ((Ci.nsIContentPolicy.TYPE_DOCUMENT == aContentType) && 
      SOME_REGULAR_EXPRESSION.test(aContentLocation.spec)) { 
      // do stuff here, possibly changing result. 
     } 
     return result; 
    }, 

    shouldProcess: function ILO_shouldProcess() Ci.nsIContentPolicy.ACCEPT, 

    _xpcom_categories: [ 
     { category: "content-policy", service: true } 
    ], 
    classInfo: XPCOMUtils.generateCI(
    {classID: Components.ID("{B5B3D9A0-08FC-11E3-8253-5EF06188709B}"), 
    contractID: "@deferredto.com/Interceptor;1", 
    classDescription: "Interceptor implements nsIContentPolicy to block images that are not yet at screen @DeferredTo", 
    interfaces: [ 
        Ci.nsIContentPolicy, 
        ], 
    flags: Ci.nsIClassInfo.SINGLETON}) 
} 

var components = [Interceptor]; 

var NSGetFactory = XPCOMUtils.generateNSGetFactory([Interceptor]); 

Fragen:

  • Ist es möglich, die Komponente von Bootstrap-Erweiterung registrieren?
  • Ist es möglich, die Komponente von der Neustart-Erweiterung zu registrieren?
  • Ist es möglich, nsICategoryManager.addCategoryEntry "content-policy" ohne Komponente zu verwenden?
  • Wie die Komponente in bootstrapped Erweiterung registrieren oder irgendwie hinzufügen neue "Content-Policy" Kategorie Eintrag?

Ich habe hinzugefügt zu nutzen-options.js

"requirements": { 
"sdk/page-mod": "sdk/page-mod", 
"sdk/self": "sdk/self", 
"chrome": "chrome"}, 

Das ist, wie ich versuche Modul zu importieren:

var {Cc, Ci, Cu} = require("chrome"); 
Cu.import("resource://deferredto/lib/interceptor.js"); 

ich viele Wege))) Aber keiner habe versucht‘ funktioniert. Der Ressourceneintrag in der Datei chrome.manifest ist für Bootstrapped-Erweiterungen nicht zulässig. Der Weg zur Komponentenmodul-Datei ist: resources/deferredto/lib/interceptor.js

Antwort

3

Jetzt sieht meine nsIContentPolicy SDK-basierte Komponente so aus. Datei interceptor.js:

'use strict'; 

var { Class } = require('sdk/core/heritage'); 
var xpcom = require('sdk/platform/xpcom'); 
var { Cc, Ci, Cu, Cm } = require('chrome'); 
var categoryManager = Cc["@mozilla.org/categorymanager;1"] 
         .getService(Ci.nsICategoryManager); 


// nsIDOMNode 
const TYPE_DOCUMENT_NODE  = Ci.nsIDOMNode.DOCUMENT_NODE; 


/// Interceptor 


var contractId = "@deferredto.com/Interceptor;1"; 

var Interceptor = Class({ 
    extends: xpcom.Unknown, 
    interfaces: [ 'nsIContentPolicy' ], 
    get wrappedJSObject() this, 

    shouldLoad : function dt_shouldLoad(contentType, contentLocation, requestOrigin, context, mimeTypeGuess, extra) { 

     let result = Ci.nsIContentPolicy.ACCEPT; 

     return result; 
    }, 

    shouldProcess: function() Ci.nsIContentPolicy.ACCEPT 
}); 

var factory = xpcom.Factory({ 
    contract: contractId, 
    Component: Interceptor, 
    unregister: false // see https://bugzilla.mozilla.org/show_bug.cgi?id=753687 
}); 

/// unload 
var unload = require("sdk/system/unload"); 

unload.when(function() { 
    function trueUnregister() { 
    categoryManager.deleteCategoryEntry("content-policy", contractId, false); 
    try { 
     console.log("xpcom.isRegistered(factory)=" + xpcom.isRegistered(factory)); 
     console.log("trueUnregister"); 
     xpcom.unregister(factory); 
     console.log("xpcom.isRegistered(factory)=" + xpcom.isRegistered(factory)); 
    } catch (ex) { 
     Cu.reportError(ex); 
    }  
    } 
    if ("dispatch" in Cu) { 
    console.log('"dispatch" in Cu'); 
    Cu.dispatch(trueUnregister, trueUnregister); 
    } else { 
    console.log('"dispatch" not! in Cu'); 
    Cu.import("resource://gre/modules/Services.jsm"); 
    Services.tm.mainThread.dispatch(trueUnregister, 0); 
    } 
}); 


//xpcom.register(factory); 

var interceptor = Cc[contractId].createInstance(Ci.nsIContentPolicy); 

categoryManager.deleteCategoryEntry("content-policy", contractId, false); 
categoryManager.addCategoryEntry("content-policy", contractId, contractId, false, true); 

Und Sie können es von sdk wie folgt verwenden:

var interceptor = require("./interceptor"); 
3

Adblock Plus, die restartless ist aber das SDK nicht verwenden, registers an nsIContentPolicy implementation zur Laufzeit, wie Ihr SDK würde. Es gibt wahrscheinlich ein paar SDK-Add-Ons, die zur Laufzeit Komponenten registrieren, aber ich kenne keine Open-Source-Versionen, die ich aus der Höhe meines Kopfes heraus empfehlen würde.

Einige Punkte in Bezug auf die ABP Implementierung und was zu ändern, um es mit dem SDK funktioniert:

  • Der Category Manager über Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager) zur Verfügung steht.
  • Der Komponenten-Registrar sollte verfügbar sein, indem auch components vom Modul chrome und dann components.manager.getService(Ci.nsIComponentRegistrar) angefordert werden.
  • Als Adblock Plus müssen Sie Ihre Komponente selbst abmelden on unload.
  • Das Entladen Teil ist leider auch ein wenig Tricking, da Sie Ihre Komponente und den Kategorieeintrag nicht synchron abmelden können, wegen Bug 753687. Adblock Plus macht es daher async mit Util.runAsync, die nur eine runnable (event, wenn Sie möchten) an den Haupt-Thread. Ich denke nicht, dass Sie hier irgendwelche SDK-Sachen verwenden können, da das SDK aufräumt, bevor irgendein asynchroner Code eine Chance hat, ausgeführt zu werden, so dass Sie selbst einen Low-Level XPCOM Runable (oder Timer) verwenden müssten.
  • Ihr Code wird Ihre Komponente zur Laufzeit registrieren. Du wirst nicht harness-options oder etwas ähnliches berühren.

(I implementiert auch eine generic component register Funktion selbst, aber das ist wieder nicht SDK-Code und müssten angepasst werden, in dem SDK zu laufen, genau wie der ABP. Es ist auch sehr ähnlich dem ABP ein .)

+2

Schließlich fand ich Firefox Addon SDK Lösung hierfür: [platform/XPCOM Modul] (https: // addons. mozilla.org/en-US/developers/docs/sdk/latest/modules/sdk/platform/xpcom.html). –

+1

War mir nicht bewusst. Gut zu wissen. Die Kommentare zu Kategorien, insbesondere zum Entladen, stehen noch. ;) – nmaier

+0

Wahrscheinlich dieses neue Modul. Ich habe das Problem vorher untersucht und das Add-on-SDK war der erste Ort, um es zu überprüfen. –