Firefox: building from source and trying out the incremental build
Task at hand on the job required me to understand how does the Mozilla Firefox's plugin system works in detail.
Although there is a lot of documentation on the protocol used there (it is called NPAPI), the task required not only understanding the interface but to have an opportunity to see what data is passing between some plugin and the browser itself.
So I decided a pretty straightforward way in here - build Firefox from source and debug browser or have some additional logs added to the source.
Building Firefox turned out to be not so scary or complicated - I used the official knowledge base: https://developer.mozilla.org/en-US/docs/Developer_Guide/Build_Instructions
In short:
- I chose not to download the zipped sources over HTTP - using source control system looked more appealing in case if there will be any need in rolling back my changes or pulling new changes from the server.
I simply cloned the main repo of the Firefox:
hg clone mozilla-central
- Downloaded mozilla-build build system
- I had Visual Studio 2010 installed (yes, I'm on Windows and... well... it's just platform to solve problems, isn't it?;))
- Entered mozilla-build command prompt (it runs bash: just use the right .bat from the root - it'll be OK)
- Created .mozille-build (default)
- Ran mach build to build the browser
BTW, Mozilla does not have any "official" IDE for Firefox development so you can choose absolutely anything. I chose FarManager as file search engine, VS2010 as source code editor and standard Windows PowerShell as a shell where I would be able to run build scripts (ability to easily copy and paste makes standard command prompt look ashamed).
Whole rebuild took me about 40 minutes. As soon as my main interest was plugin system, I needed to find the faster way to build only module containing plugin hosting code.
After a few articles about Firefox incremental build (especially this where only ONE module building straight into DLL had to be rebuilt), I decided to hanle this stuff on my own and just looked through the MakeFile to find out the target of the build - it was a static library referenced only in one additional module that targeted xul.dll module in the Firefox main dir.
Here is the script I created to build only plugin lib and xul.dll:
build.sh
cd c:/firefoxdev/release-src/obj-ff-debug/dom/plugins/ipc
c:/firefoxdev/release-src/build/pymake/make.py
cd c:/firefoxdev/release-src/obj-ff-debug/toolkit/library
c:/firefoxdev/release-src/build/pymake/make.py
After looking through the code, it turned out that there is a built-in logging system in there already.
It is pretty wize and easy to use - you just set some environment vars and good to go.
Here is the PowerShell script setting NSPR_LOG_MODULES and NSPR_LOG_FILE environment vars to the values needed to look what happens in plugin modules:
EnablePluginLogging.ps1
[Environment]::SetEnvironmentVariable("NSPR_LOG_MODULES", "IPCPlugins:5,Plugin:5,PluginNPN:5,PluginNPP:5", "Process")
[Environment]::SetEnvironmentVariable("NSPR_LOG_FILE", "c:\FirefoxDev\logfile.txt", "Process")
While the logging system above is good to get the high view on what is happening in plugin system, it has a big deficiency: it cannot format the strings (%s) longer than 100 chars.
While this setting could be set somewhere, I decided not to bother and simply made a very simple logging system.
Here it is:
DebugLog.h
#include "stdio.h"
#define LOG_FILENAME "c:\\FirefoxDev\\logfile.log"
#define BUF_SIZE 512
#define __L(format, ...) { FILE* fp = fopen(LOG_FILENAME, "a+"); if(fp) { char buf[BUF_SIZE]; _snprintf_s(buf, BUF_SIZE, _TRUNCATE, format, __VA_ARGS__); fprintf(fp, buf); fprintf(fp, "\n"); fclose(fp); }}
#define __LW(format, ...) { FILE* fp = fopen(LOG_FILENAME, "a+"); if(fp) { char buf[BUF_SIZE]; _snprintf_s(buf, BUF_SIZE, _TRUNCATE, format, __VA_ARGS__); fprintf(fp, buf); fclose(fp); }}
#define __L_FUNC __L(__FUNCTION__)
#define __L_MTHD __L(__FUNCTION__" [%p]", (void*) this)
I am still in the middle of investigation and can log everything that plugin is asking from the browser but not what browser (for example, JavaScript), can send to plugin.
But initial problem is solved!
Although there is a lot of documentation on the protocol used there (it is called NPAPI), the task required not only understanding the interface but to have an opportunity to see what data is passing between some plugin and the browser itself.
So I decided a pretty straightforward way in here - build Firefox from source and debug browser or have some additional logs added to the source.
Building Firefox turned out to be not so scary or complicated - I used the official knowledge base: https://developer.mozilla.org/en-US/docs/Developer_Guide/Build_Instructions
In short:
- I chose not to download the zipped sources over HTTP - using source control system looked more appealing in case if there will be any need in rolling back my changes or pulling new changes from the server.
I simply cloned the main repo of the Firefox:
hg clone mozilla-central
- Downloaded mozilla-build build system
- I had Visual Studio 2010 installed (yes, I'm on Windows and... well... it's just platform to solve problems, isn't it?;))
- Entered mozilla-build command prompt (it runs bash: just use the right .bat from the root - it'll be OK)
- Created .mozille-build (default)
- Ran mach build to build the browser
BTW, Mozilla does not have any "official" IDE for Firefox development so you can choose absolutely anything. I chose FarManager as file search engine, VS2010 as source code editor and standard Windows PowerShell as a shell where I would be able to run build scripts (ability to easily copy and paste makes standard command prompt look ashamed).
Whole rebuild took me about 40 minutes. As soon as my main interest was plugin system, I needed to find the faster way to build only module containing plugin hosting code.
After a few articles about Firefox incremental build (especially this where only ONE module building straight into DLL had to be rebuilt), I decided to hanle this stuff on my own and just looked through the MakeFile to find out the target of the build - it was a static library referenced only in one additional module that targeted xul.dll module in the Firefox main dir.
Here is the script I created to build only plugin lib and xul.dll:
build.sh
cd c:/firefoxdev/release-src/obj-ff-debug/dom/plugins/ipc
c:/firefoxdev/release-src/build/pymake/make.py
cd c:/firefoxdev/release-src/obj-ff-debug/toolkit/library
c:/firefoxdev/release-src/build/pymake/make.py
After looking through the code, it turned out that there is a built-in logging system in there already.
It is pretty wize and easy to use - you just set some environment vars and good to go.
Here is the PowerShell script setting NSPR_LOG_MODULES and NSPR_LOG_FILE environment vars to the values needed to look what happens in plugin modules:
EnablePluginLogging.ps1
[Environment]::SetEnvironmentVariable("NSPR_LOG_MODULES", "IPCPlugins:5,Plugin:5,PluginNPN:5,PluginNPP:5", "Process")
[Environment]::SetEnvironmentVariable("NSPR_LOG_FILE", "c:\FirefoxDev\logfile.txt", "Process")
While the logging system above is good to get the high view on what is happening in plugin system, it has a big deficiency: it cannot format the strings (%s) longer than 100 chars.
While this setting could be set somewhere, I decided not to bother and simply made a very simple logging system.
Here it is:
DebugLog.h
#include "stdio.h"
#define BUF_SIZE 512
#define __L(format, ...) { FILE* fp = fopen(LOG_FILENAME, "a+"); if(fp) { char buf[BUF_SIZE]; _snprintf_s(buf, BUF_SIZE, _TRUNCATE, format, __VA_ARGS__); fprintf(fp, buf); fprintf(fp, "\n"); fclose(fp); }}
#define __LW(format, ...) { FILE* fp = fopen(LOG_FILENAME, "a+"); if(fp) { char buf[BUF_SIZE]; _snprintf_s(buf, BUF_SIZE, _TRUNCATE, format, __VA_ARGS__); fprintf(fp, buf); fclose(fp); }}
#define __L_FUNC __L(__FUNCTION__)
#define __L_MTHD __L(__FUNCTION__" [%p]", (void*) this)
I am still in the middle of investigation and can log everything that plugin is asking from the browser but not what browser (for example, JavaScript), can send to plugin.
But initial problem is solved!
Comments
Post a Comment