📜 ⬆️ ⬇️

How to write a component to Firefox in C ++

How to write a component for Firefox in C ++ so that it can then be used from a javascript extension or even from a regular web page.

Prehistory


I needed to make a toolbar for IE and Firefox. Everything was complicated by the fact that some non-standard binary protocol was used, implemented by C-dlka. Using it from C # (on which I wrote a toolbar for IE) was not a problem, but for FF I had to write a Wrapper - an XPCOM component that I could turn to from javascript, which would transfer the data to dll and return the result.
XPCOM is an analogue of Microsoft COM from Mozilla, which differs from COM by almost nothing. In general, it is not very clear why Mozilla, instead of the well-described and familiar COM, decided to invent its own bike, but it just so happened that we, the developers, will have to accept everything as it is.
Open Source is fine, but until you come across documentation and the lack of working examples. I found, by the way, examples of XPCOM components on the Internet as many as 4, none of which have worked. In addition, the most recent of them was dated 2006, the descriptions included the old version of XULRunner, and in the discussion, for example, there were questions about compatibility with “new Firefox 1.3” and several dozen questions “how to get it work?”.

Go!


  1. First, let's deal with the environment.
    Run the command line subst o: d:\myworkfolder\_firefox - in this folder we will add all the necessary files.
    You can even write this command to the bat-file.
  2. Download the latest XULRunner (now it is 1.9.0.6) - releases.mozilla.org/pub/mozilla.org/xulrunner/releases
    We need an SDK. Download and unpack it in O: \ xulrunner-sdk
  3. Create O: \ console.bat as follows:
    set path=%path%;O:\xulrunner-sdk\bin;O:\xulrunner-sdk\sdk\bin
    cmd.exe

    (just in case, suddenly you need to do something with your hands)
  4. Create a folder O: \ dll-src, and in it - IDemo.idl
    #include "nsISupports.idl"
    #include "nsrootidl.idl"

    [ scriptable , uuid ( CB934085 - D019 - 47d5 - A6F0 - 623885873281 ) ]

    interface IDemo : nsISupports
    {
    long func1 ( in long inP , out long outP ) ;

    long func2 ( in wstring inP , out wstring outP ) ;
    } ;


  5. In the same place we create two bat-files, build-pre.bat and build-post.bat. The second is left empty, and in the first we write:
    set path=%path%;O:\xulrunner-sdk\bin;O:\xulrunner-sdk\sdk\bin
    xpidl -IO:\xulrunner-sdk\idl -m header IDemo.idl
    xpidl -IO:\xulrunner-sdk\idl -m typelib IDemo.idl

    According to our idl-files, using xpidl, the header and xpt-description of the interface will be automatically generated (analogous to the mayrosoft .tlb file)
  6. Create a new Win32 / Dll project library / empty

  7. Run build-pre.bat and transfer the resulting IDemo.h into our project.
  8. Create a file Demo.h in VS and copy our template from IDemo.h. We bring it to the human form:
    #ifndef _DEMO_H_
    #define _DEMO_H_

    #include "IDemo.h"

    #define DEMO_CONTRACTID "@demo.com/XPCOMDemo/Demo;1"
    #define DEMO_CLASSNAME "XPCOM Demo LOL"
    #define DEMO_CID { 0xcb934086 , 0xd019 , 0x47d5 , { 0xa6 , 0xf0 , 0x62 , 0x38 , 0x85 , 0x87 , 0x32 , 0x81 } }

    class Demo : public IDemo
    {
    public :
    NS_DECL_ISUPPORTS
    NS_DECL_IDEMO

    Demo ( ) ;

    virtual ~ Demo ( ) ;
    } ;

    #endif


  9. Create a Demo.cpp file in VS and copy the commented part from IDemo.h there - there is already an implementation template. Change the class name.
    #include "Demo.h"
    #include < nsMemory . h >
    #include < nsStringAPI . h >

    NS_IMPL_ISUPPORTS1 ( Demo , IDemo )

    Demo : : Demo ( ) {
    }

    Demo : : ~ Demo ( ) {

    }
    NS_IMETHODIMP Demo : : Func1 ( PRInt32 inP , PRInt32 * outP , PRInt32 * _retval ) {
    if ( inP > 100 ) {
    * _retval = 1 ;
    * outP = 0 ;
    } else {
    * _retval = 0 ;
    * outP = inP * 2 ;
    }
    return NS_OK ;
    }
    NS_IMETHODIMP Demo : : Func2 ( const PRUnichar * inP , PRUnichar * * outP , PRInt32 * _retval ) {
    const wchar_t * msg = L "" ;
    * outP = ( PRUnichar * ) nsMemory : : Clone ( msg , ( wcslen ( msg ) + 1 ) * sizeof ( wchar_t ) ) ;

    * _retval = 0 ;
    return NS_OK ;
    }

  10. Create a DemoModule.cpp file in VS:
    This is our main file and entry point to our application. Here we give the XPCOM kernel the components that our module implements.
    #include "nsIGenericFactory.h"
    #include "Demo.h"

    NS_GENERIC_FACTORY_CONSTRUCTOR ( Demo )

    static nsModuleComponentInfo components [ ] =

    {
    {
    DEMO_CLASSNAME ,
    DEMO_CID ,
    DEMO_CONTRACTID ,
    DemoConstructor ,

    }
    } ;

    NS_IMPL_NSGETMODULE ( "DemoModule" , components )



  11. Open project properties
    C / C ++ - General - Additional Include Directories write O: \ xulrunner-sdk \ sdk \ include; O: \ xulrunner-sdk \ include
    C / C ++ - Preprocessor - Preprocessor Definitions add; XPCOM_GLUE
    C / C ++ - Advanced - Force Includes write mozilla-config.h
    Linker - Additional Library Directories write O: \ xulrunner-sdk \ sdk \ lib
    Linker - Input - Additional Dependencies - write xpcom.lib nspr4.lib xpcomglue_s.lib
    Build events - Pre-build event - Command Line - we write O: \ dll-src \ build-pre.bat there
    Build events - Post-build event - Command Line - we write O: \ dll-src \ build-post.bat there
  12. It's time to create a shortcut for firefox.
    We do it and in the properties we write: "C: \ Program Files \ Mozilla Firefox \ firefox.exe" -no-remote -P dev
    We start. The Profile Manager has opened - we create the dev profile and manually specify the folder for it: C: \ Documents and settings \ test \ Application Data \ Mozilla \ Firefox \ Profiles \ dev1 (create using the "create" button).
    Firefox starts, and when it starts, we close it.
  13. Now edit the build-post.bat.
    set path=%path%;O:\xulrunner-sdk\bin;O:\xulrunner-sdk\sdk\bin

    del /f "C:\Documents and Settings\test\Application Data\Mozilla\Firefox\Profiles\dev\xpti.dat"
    del /f "C:\Documents and Settings\test\Application Data\Mozilla\Firefox\Profiles\dev\compreg.dat"

    copy /Y IDemo.xpt "C:\Program Files\Mozilla Firefox\components\"
    copy /Y debug\Demo.dll "C:\Program Files\Mozilla Firefox\components\"

  14. Build a project!
  15. Create a file O: \ demo.html
    (the code is given partially)
    netscape . security . PrivilegeManager . enablePrivilege ( "UniversalXPConnect" ) ;
    obj = Components . classes [ "@demo.com/XPCOMDemo/Demo;1" ] . createInstance ( ) ; // ? Demo.h

    myobject = obj . QueryInterface ( Components . interfaces . IDemo ) ;
    var x = { } ;

    var res = myobject . func1 ( 10 , x ) ;
    alert ( 'func1(10,x) returned ' + res + '. x is ' + x . value ) ;

    res = myobject . func2 ( "asd" , x ) ;
    alert ( 'func2("ads",x) returned ' + res + '. x is ' + x . value ) ;

  16. Firefox through our shortcut and open file: // o: \ demo.html
  17. We press on the button, we agree with the question about UNSAFE, we look at the results.
    The question about UNSAFE arises on the line with “PrivilegeManager.enablePrivilege” - this line asks for permission to work with XPCOM components and, of course, should not be included in web pages.
    If we make the Firefox Extension - some toolbar - then we are already allowed to work with XPCOM. Therefore, there should be no extension in the code of this line, no warning appears and everything works silently.
  18. Hooray! Works!

')
Ps1. All project files can be downloaded from this link (82 kb)
PS2. We have an “interface” (or several) and there is a “component” that this interface implements. Each of them has its own UID. To generate the UID we need Guidgen from VS, it usually lies in "C: \ Program Files \ Microsoft SDKs \ Windows \ v6.0A \ Bin \ guidgen.exe". To generate other UIDs that are different from those in my example, you need to run guidgen, select the third option there, copy it and paste it into IDemo.idl with your hands. Then generate another ID and copy to already in Demo.h. You will need to do this if you do not stop at the Demo component and make your component.
PS3. The idl files for XPCOM are different from the idl files for COM, so the microsoft utilities tlbimp and midl do not understand these idl files. If you decide to add IDemo.idl to your project, do not forget to set it to “do not compile”.

Source: https://habr.com/ru/post/53312/


All Articles