[Solved] How to use dependent libraries in XPCOM

Talk about add-ons and extension development.
HoSpiTaL_gHoSt
Posts: 19
Joined: March 18th, 2009, 2:36 am

[Solved] How to use dependent libraries in XPCOM

Post by HoSpiTaL_gHoSt »

Hello,

I've developed a Firefox Extension which includes a C++ XPCOM object. This XPCOM object references 2 other DLLs, and those DLLs need to be for example in system32 to be automatically found.

Now my question is: is there a way to install a Firefox Extension the usual way (by using InstallTrigger.install method), but instead of only installing the extension itself, also installing 2 extra DLL's that should go in system32? Or is there a way to package the needed DLLs in the XPI package so that the XPCOM DLL can find them?

NOTE 1: I don't want to use 2 seperate installers: one to install the DLL's and then the .XPI to install the extension itself.

NOTE 2: The install method I'm looking for has to be something that works on Windows, Mac OSX and Linux (on the non-windows platforms DYLIB files or SO files are referenced instead of DLLs of course)

Many thanks in advance to anyone who wants to help! I can't seem to find any information on the Internet about my problem...
Stephanie

EDIT: I edited the title of this topic because it represents my question better. I would like to know how I can build the code offered by this sample https://developer.mozilla.org/en/Using_Dependent_Libraries_In_Extension_Components without building the Mozilla source. I built the code successfully using Visual Studio, but now the stub DLL won't register in Firefox. Does anybody know what could be the reason for this?
Last edited by HoSpiTaL_gHoSt on May 12th, 2009, 12:56 am, edited 2 times in total.
Crazy-EyE
Posts: 397
Joined: February 24th, 2008, 6:27 am
Location: Moscow, Russia

Re: How to install Firefox Extension as exe

Post by Crazy-EyE »

Why can't you just put these libraries to the /components directory. If these libs are written by you it should be OK. However if you try to do it with msvcrtXX.dll it will show "can't load" message every time Firefox tries to register it.

Also on Linux and on some Windows systems (possible on Mac too, I don't know) there is not enough privileges to write to the system library directory.

Anyway you can try the following workaround. If your extension doesn't require these libs immediately after Firefox starts you can put libs somewhere in the extension package and copy them of first run.
HoSpiTaL_gHoSt
Posts: 19
Joined: March 18th, 2009, 2:36 am

Re: How to install Firefox Extension as exe

Post by HoSpiTaL_gHoSt »

Thanks for your reply Crazy-EyE.

That was the first thing I tried, but apparently my XPCOM DLL didn't get registered in Firefox if there were other non-XPCOM DLLs present in /components (I didn't write the other DLLs myself, one of them is the OpenSSL library). I only gave this a quick try, but because it didn't work, I assumed Firefox tried to register every DLL it found in /components as XPCOM object, and because some DLLs are not XPCOM objects, the XPCOM dll didn't get registered either (at least that's what I think). But I'll check it again, just to make sure, that would definitely be the best and easiest solution.

And yeah, manually copying the files to system32 or /usr/lib will probably fail because of the privileges needed...

I found another post on this forum about automatically running an .exe out of the .xpi extension... That way I could make a Windows installer to install the DLLs and call that installer to start when the extension gets installed... I've only been trying this for a few hours today, it seemed to work on Windows, but not on Mac where I tried to run an installer package (.pkg). I'll definitely try some more and post a solution once I've found one.
Crazy-EyE
Posts: 397
Joined: February 24th, 2008, 6:27 am
Location: Moscow, Russia

Re: How to install Firefox Extension as exe

Post by Crazy-EyE »

Firefox should explicitly write to the JS console something like "Registration failed: <filename>" for your component dll (if related dev prefs are enabled). Try Troubleshooting XPCOM components registration
HoSpiTaL_gHoSt
Posts: 19
Joined: March 18th, 2009, 2:36 am

Re: How to install Firefox Extension as exe

Post by HoSpiTaL_gHoSt »

Thanks, I tried to put the other DLLs in the /components directory, and as a result my XPCOM dll wouldn't register anymore in Firefox, this is the error I got in the Javascript console:

Failed to load XPCOM component: D:\Stephanie\myclientextension\components\MyClientExtension.dll
Failed to load XPCOM component: D:\Stephanie\myclientextension\components\libeay32_0_9_8g.dll

where MyClientExtension.dll is an XPCOM component and the other one is not.

By following your Troubleshooting link, I found this link:
https://developer.mozilla.org/en/Using_ ... Components
At first sight, this looks like exactly what I need! I'm going to check this out tomorrow to see if this works, but it definitely seems like a solution! Thanks for making me click the Troubleshooting link, lol.

It seems to me that the Mozilla documentation for writing extensions and installing them is actually really complete, but sometimes it's really hard to find what you need! I've had problems before, then I post a topic about it and someone else posts a link to the Mozilla documentation with exactly what I need! But I had googled and searched a lot and hadn't found that link...
Crazy-EyE
Posts: 397
Joined: February 24th, 2008, 6:27 am
Location: Moscow, Russia

Re: How to install Firefox Extension as exe

Post by Crazy-EyE »

Maybe it doesn't work anymore because it assumes other libs are in WINDIR\system32 (though it normally shouldn't happen)?

Also Firefox definitely has some SSL implementation. Of course, changing the whole code is not a good idea.
HoSpiTaL_gHoSt
Posts: 19
Joined: March 18th, 2009, 2:36 am

Re: How to install Firefox Extension as exe

Post by HoSpiTaL_gHoSt »

I just read this topic about dependent DLLs: viewtopic.php?f=19&t=452317&st=0&sk=t&sd=a and that person also had the problem that putting the DLLs in /components didn't work, so I'll have to try the article I mentioned before: https://developer.mozilla.org/en/Using_ ... Components

But there is something I don't get in the article:
Sample code is below, and can be built by placing the two files in extensions/stub and configuring with --enable-extensions=stub


Where can I find the extensions/stub folder he mentions? In the Firefox install directory or the Profile directory? Or somewhere else even? And what does he mean by configuring with --enable-extensions=stub?



EDIT: I mailed the author of the example about this and apparently the /extensions folder he refers to is located in the Mozilla source code. So you have to build his sample by building Firefox.
HoSpiTaL_gHoSt
Posts: 19
Joined: March 18th, 2009, 2:36 am

Re: How to install Firefox Extension as exe

Post by HoSpiTaL_gHoSt »

Unfortunately, I didn't build the Mozilla source to develop my extension, so could anybody tell me how to build the sample cpp file from his sample in Visual Studio? I managed to build it as a dll, but the dll won't register in Firefox. I'm not sure if the stub dll is also an XPCOM component, but I think it is. Could anybody help me with the correct settings in Visual Studio (or in general the correct settings to build this stub dll without building the Mozilla source)?

Any help would be greatly appreciated!
HoSpiTaL_gHoSt
Posts: 19
Joined: March 18th, 2009, 2:36 am

Re: How to use dependent libraries in XPCOM

Post by HoSpiTaL_gHoSt »

OK, I managed to make the stub DLL work and I built it using Visual Studio. I didn't have to make any special settings to the Visual Studio project, I just had to make sure the Gecko lib and include dirs were added to the project to make it compile.

The mistake I made was the following:
Because in Visual Studio I had to define certain constants myself to make the stub example work, I gave them the following value on Windows:

#define MOZ_DLL_PREFIX ""
#define MOZ_DLL_SUFFIX "dll"

The correct values for these constants on Windows are:

#define MOZ_DLL_PREFIX ""
#define MOZ_DLL_SUFFIX ".dll" => mind the dot!

I found the error I made by adding logging info:

PRLogModuleInfo * myLm = PR_NewLogModule("myExtensionStubLoader");
PR_LogPrint("start NSGetModule");

To see the logging info I used the following mechanism in cmd:

set NSPR_LOG_MODULES=myExtensionStubLoader:5
set NSPR_LOG_FILE=c:\Path\to\logfile
c:\Program Files\Mozilla Firefox\firefox.exe
dino750
Posts: 84
Joined: April 6th, 2009, 11:28 pm

Re: [Solved] How to use dependent libraries in XPCOM

Post by dino750 »

Hi HoSpiTaL_gHoSt,

I think I am facing the same problem as you did, need to put dll into System32 folder so that the extension can see it automatically during install.

It looks like you got it work by using https://developer.mozilla.org/en/Using_Dependent_Libraries_In_Extension_Components you mentioned above, but it is confusing to me.

1. For that Makefile.in, do I simply put it under extensions/stub/Makefile.in? Will FireFox install manager parse and execute it automatically?
2. For the cpp file, how to I compile it? What configurations are need to set up Visual Studio? Where is .h file? After I get it compiled, how can I use it?
HoSpiTaL_gHoSt
Posts: 19
Joined: March 18th, 2009, 2:36 am

Re: [Solved] How to use dependent libraries in XPCOM

Post by HoSpiTaL_gHoSt »

dino750, you sent me an e-mail with the following questions (I'm copying your questions here so that other people will know what I'm answering at):

1. Where do I create the folder extensions/stub?
2. How do I do configuring with --enable-extensions=stub
3. Does extensions/stub/Makefile.in just get parsed and executed by FireFox automatically?
4. Do I compile that sample C++ code into dll? If so, where do I put that dll?
5. Is there any .h file for that .cpp file?
6. When I create a Visual Studio Project for compile that .cpp file, does the project name need to match the .cpp file name?
7. When Makefile.in is executed, does it execute the commands from the output of that .cpp?



I did indeed solve my problem by using the example given in the following article:
https://developer.mozilla.org/en/Using_ ... Components

This example describes how you can load libraries your XPCOM object depends on, without placing them in system32. The author of the example used the Mozilla source to build his code, hence his pretty complicated looking Makefile. If you didn't make your XPCOM object by building the Mozilla source, then you don't even need the Makefile (I also didn't use the Makefile because I never built the Mozilla source to make my XPCOM component, so I don't know anything about that)

Answer to your questions:

1. If you're building the Mozilla source, you should place the stub folder in the /extensions folder of the Mozilla source. If you're not using Mozilla source, you don't need this folder at all.

2. You only need this if you're building the Mozilla source. I didn't use this.

3. No, apparently the Makefile only gets executed when you build the Mozilla source

4. Yes, the only code you need from the example of the article is the .cpp file. You should create a new Visual Studio project with as only file the .cpp file. Make sure to add the Gecko/lib folder to the additional library directories, and the Gecko/include folder to the Include directories. This way you will generate a .dll file. What you should do with the .dll file, is explained in the article. You should place it into the /components folder of your Firefox extension, along with the .XPT file of the XPCOM object you want to load. The XPCOM object itself, along with the libraries it depends on, should go in the /libraries directory of your Firefox Extension.

5. No, there's no .h file

6. No, the project name does not have to match

7. I don't know because I didn't use the Makefile


Here is the copy of the .cpp file I used in the Visual Studio project:
(PRLogModuleInfo and PR_LogPrint are only used for logging)

Code: Select all


// Copyright (c) 2005 Benjamin Smedberg <benjamin@smedbergs.us>

#include "nscore.h"
#include "nsModule.h"
#include "prlink.h"
#include "nsILocalFile.h"
#include "nsStringAPI.h"
#include "nsCOMPtr.h"
#include "prlog.h"

#define MOZ_DLL_PREFIX ""
#define MOZ_DLL_SUFFIX ".dll"

static char const *const kDependentLibraries[] =
{
  // dependent1.dll on windows, libdependent1.so on linux

  MOZ_DLL_PREFIX "libeay32_0_9_8g" MOZ_DLL_SUFFIX, //so my ddl is actually called libeay32_0_9_8g.dll
  MOZ_DLL_PREFIX "FOXDLL-1.6" MOZ_DLL_SUFFIX,
  nsnull

  // NOTE: if the dependent libs themselves depend on other libs, the subdependencies
  // should be listed first.
};

// component.dll on windows, libcomponent.so on linux
static char kRealComponent[] = MOZ_DLL_PREFIX "NameOfYourXPCOMObject" MOZ_DLL_SUFFIX;

nsresult
NSGetModule(nsIComponentManager* aCompMgr,
            nsIFile* aLocation,
            nsIModule* *aResult)
{
  nsresult rv;


  PRLogModuleInfo * myLm = PR_NewLogModule("YourXPCOMObjectStubLoader");
  PR_LogPrint("Begin van NSGetModule");
  //PR_LogFlush();


  // This is not the real component. We want to load the dependent libraries
  // of the real component, then the component itself, and call NSGetModule on
  // the component.

  // Assume that we're in <extensiondir>/components, and we want to find
  // <extensiondir>/libraries

  nsCOMPtr<nsIFile> libraries;
  rv = aLocation->GetParent(getter_AddRefs(libraries));
  if (NS_FAILED(rv))
    return rv;

  PR_LogPrint("1");

  nsCOMPtr<nsILocalFile> library(do_QueryInterface(libraries));
  if (!library)
    return NS_ERROR_UNEXPECTED;

  PR_LogPrint("2");

  library->SetNativeLeafName(NS_LITERAL_CSTRING("libraries"));
  library->AppendNative(NS_LITERAL_CSTRING("dummy"));

  PR_LogPrint("3");

  // loop through and load dependent libraries
  for (char const *const *dependent = kDependentLibraries;
       *dependent;
       ++dependent) {
   PR_LogPrint("in lus");
    library->SetNativeLeafName(nsDependentCString(*dependent));
    PRLibrary *lib;
    library->Load(&lib);
    // 1) We don't care if this failed!
    // 2) We are going to leak this library. We don't care about that either.
  }

  PR_LogPrint("4");

  library->SetNativeLeafName(NS_LITERAL_CSTRING(kRealComponent));

  PR_LogPrint("5");

  PRLibrary *lib;
  rv = library->Load(&lib);
 
  PR_LogPrint("NSresult van library load: " + rv);

  if (NS_FAILED(rv))
    return rv;

  PR_LogPrint("6");

  nsGetModuleProc getmoduleproc = (nsGetModuleProc)PR_FindFunctionSymbol(lib, NS_GET_MODULE_SYMBOL);

  PR_LogPrint("7");

  if (!getmoduleproc)
    return NS_ERROR_FAILURE;

  PR_LogPrint("8");
  PR_LogFlush();

  return getmoduleproc(aCompMgr, aLocation, aResult);
}



I hope this explains it better, if you have any questions, feel free to ask.
dino750
Posts: 84
Joined: April 6th, 2009, 11:28 pm

Re: [Solved] How to use dependent libraries in XPCOM

Post by dino750 »

Hi HoSpiTaL_gHoSt,

Your reply definitely help me a lot. The solution looks complicated itself, but you found out the essential part for building extension purpose.

Thank you for great help.


Dino
dino750
Posts: 84
Joined: April 6th, 2009, 11:28 pm

Re: [Solved] How to use dependent libraries in XPCOM

Post by dino750 »

Hi HoSpiTaL_gHoSt,

I am trying the solution now. I looked your code, there is one thing I am confused.

If my understanding is correct, dependent.dll would be the 3rd party dll and component.dll would be the XPCOM component. In your code, you put your own component libeay32_0_9_8g.dll in the variable kDependentLibraries block. And you put "NameOfYourXPCOMObject" for variable static char kRealComponent[], which should be your component name by that article. I assume your sample code is the working code, would you tell me how you arranged those variables?

In my case, I have 1 dependent library and 2 XPCOM components, do you have any idea who I should compose the code?

BTW, which versions of Visual Studio and XPCOM SDK are you using? I am using Visual Studio 2005 and xulrunner-1.9.0.7.en-US.win32.sdk. I am really worried about if my setup will work with this solution.
HoSpiTaL_gHoSt
Posts: 19
Joined: March 18th, 2009, 2:36 am

Re: [Solved] How to use dependent libraries in XPCOM

Post by HoSpiTaL_gHoSt »

Hello dino750,

Yes, dependent.dll is the 3rd party dll and component.dll is your own XPCOM component.
In the code I posted, libeay32_0_9_8g.dll and FOXD1.6.dll are the two 3rd party libraries, and NameOfYourXPCOMObject.dll is my own XPCOM object, so it's arranged in the same way as the example in the article (I just changed the real name of my XPCOM component).

If you have 1 dependent library, you should put that one in kDependentLibraries. After that one is loaded, you should load both of your XPCOM components by putting them in kRealComponent. I haven't tested it with 2 XPCOM components, but I think it should work the same way.

I'm using Visual Studio 2008 and Gecko SDK gecko-sdk-win32-msvc-1.8.0.4 (I had to add some header files myself to the Gecko SDK I downloaded because they weren't present, but that is off topic).
dino750
Posts: 84
Joined: April 6th, 2009, 11:28 pm

Re: [Solved] How to use dependent libraries in XPCOM

Post by dino750 »

Hi HoSpiTaL_gHoSt,

Yes, I understand that your actual component name is replaced by "NameOfYourXPCOMObject" for posting. Because you put a comment "//so my ddl is actually called libeay32_0_9_8g.dll" for the line "MOZ_DLL_PREFIX "libeay32_0_9_8g" MOZ_DLL_SUFFIX". I was confused which one is your own XPCOM dll.

I also emailed the author regarding my multiple XPCOM components need. He replied me that it's rare to have multiple XPCOM dlls. So I am assuming that sample code can work with only one XPCOM dll.
Post Reply