MD5/SHA1 Hash Decryptor

Posted on June 24th, 2008

Did you forget your password? Is your md5 or sha1 hash just hangin’ out in your database, collecting dust? Why regenerate it?

Try this first, before you do.

Qmake - Xcode project generator

Posted on June 23rd, 2008

qt Xcode

Since I can’t drop the topic of Qt on Mac OS X I will continue with the train ride. Qt’s qmake allows us to generate Xcode projects from .pro files. This is an awesome feature and I salute the Trolls for providing this capability to us. However, some time ago I noticed a minor issue with it and I wasn’t the only one. A colleague of mine Grant also noticed that searching through the project in Xcode takes quite a long time when searching through qmake generated Xcode projects. What happens is qmake adds the SDK that the project builds against and places it as a PBXFileReference into the “External Frameworks and Libraries” group. This causes each and every search request to go through the entire SDK directory structure and thus causing the poor search performance.

Since Grant and I do not have any time to waste on long searches… we shall patch qmake to attain our desired goal of fast project wide searches when working with qmake generated Xcode projects.

Just apply the below patch, rebuild qmake and voila… problem solved.

Patch

Integrating Qt documentation into Xcode 3.0

Posted on June 22nd, 2008

qt Xcode

Qt Assistant is an extremely useful application that comes along with Trolltech’s Qt releases. It provides documentation for the entire Qt framework. However, as an Xcode user, I’d prefer to never leave the IDE when looking up documentation. So I decided to look into a way of generating an Xcode documentation set for the Qt API. So here is how you do it.

Initially we must create an Xcode docset bundle. I am using Qt 4.3.3 so let’s create it:

1) mkdir -p ~/Library/Developer/Shared/Documentation/DocSets/com.trolltech.qt.4.3.3.docset

cd into the ~/Library/Developer/Shared/Documentation/DocSets folder. Now, we must populate the the rest of the docset bundle:

2) mkdir -p com.trolltech.qt.4.3.3.docset/Contents/Resources/Documents

Copy over the html documentation from the QTDIR/docs/html folder to the docset bundle:

3) cp –R /Developer/qt-4.3.3/docs/html/*
com.trolltech.qt.4.3.3.docset/Contents/Resources/Documents/

Edit the Info.plist file for the bundle

4) vi com.trolltech.qt.4.3.3.docset/Contents/Info.plist

Here is a basic Info.plist file which will work for our purposes:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.trolltech.qt.4.3.3.docset</string>
<key>CFBundleName</key>
<string>Qt 4.3.3</string>
<key>DocSetFeedName</key>
<string>Trolltech</string>
</dict>
</plist>

We also need to create a Nodes.xml file which will be needed for indexing the html docs:

5) vi com.trolltech.qt.4.3.3.docset/Contents/Resources/Nodes.xml

Here is a basic Nodes.xml which will server our goal:

<?xml version="1.0"
encoding="UTF-8"?>
<DocSetNodes version="1.0"> <!– Root element –>
<TOC>
<Node type="folder"> <!– Root node –>
<Name>Root</Name>
<Path>index.html</Path>
</Node>
</TOC>
</DocSetNodes>

And the final step will be to run the indexer so that Xcode can pick up our generated bundle contents:

6) /Developer/usr/bin/docsetutil index com.trolltech.qt.4.3.3.docset

Now our bundle is ready and we can start Xcode. Once inside Xcode, click on Help->Documentation and you should see a Trolltech subsection on left hand side under the DocSets. See Figure 1.


Figure 1

One interesting thing I have noticed is that searching within Xcode documentation is much faster than using Qt Assistant. There are other great features that Xcode provides, such as the Research Assistant which can be used to look up documentation while editing source code in the editor. But for those topics I shall refer you to the official documentation:

Xcode Documentation Set Guide

Debugging Qt with Xcode 3.0

Posted on May 30th, 2008

qt Xcode

As a user of Xcode and Trolltech’s Qt framework I recently discovered that data formatting for Qt’s string type QString no longer works in Xcode 3.0. This is something that used to work in the Xcode 2.4 and 2.5 releases, but with Xcode 3.0 I am unable to view the full contents of QStrings during debugging. At best, using simple data formatting methods, I am able to configure Xcode to display the the first character of a QString, but no other characters are displayed in the string. This makes the experience of debugging Qt code quite painful and reduces productivity.

There is a solution however. Xcode provides and exposes an interface for data formatting plug-ins, which Apple uses as well. Specifically, Apple has a similar plug-in for the Carbon data types which include: AEDesc, AEDataStorage, EventRecord, UTCDateTime and many more. By means of this functionality, I was able to cook up a plug-in that simplifies my life of debugging Qt source code with Xcode 3.0.

The plug-in is a Mach-O bundle that contains the code to interpret information about a particular object. In this case we’re extracting the character buffer contents of the QString. The contents look something like this:

#include “DataFormatterPlugin.h”
#include <QtCore>

_pbxgdb_plugin_function_list *_pbxgdb_plugin_functions;
static char *notSetString = “QtDataFormatter plugin error: _pbxgdb_plugin_functions not set!”;

char * GetCharArrayFromQString(QString &inString, int identifier)
{
   const char *src = inString.toAscii();
   if (!src)
      return 0;

   char *dest;
   if (_pbxgdb_plugin_functions)
   {
      int bufLen = strlen(src) + 1;
      dest = (char *)(_pbxgdb_plugin_functions->allocate(identifier, bufLen));
      dest[0] = 0;
      strcpy(dest, src);
   }
   else
   {
      dest = notSetString;
   }
   return dest;
}

There also exists a plist file that maps the QString type to this function call during debugging. This file exists inside the plug-in bundle and is named CustomDataViews.plist.

The plug-in bundle needs to be copied to the Xcode plug-ins destination located in /Developer/Library/Xcode/CustomDataViews for a default installation. Once the plug-in is loaded, one can view the contents of a QString while debugging. See Figure 1.

figure 1

Figure 1

Double clicking on the Summary field of any QString will display the means by which Xcode determines the Summary for that variable. See Figure 2.

figure 2

Figure 2

That’s pretty much it!

The same thing could be accomplished for any other Qt types if one wants to see the contents of a particular object during debugging. This does not just apply to Qt and can be extended to other frameworks as well.

Below you will find the binary and source tarballs for this plug-in.

qtdataformatters_bin.tar.gz Binary Package
qtdataformatters_src.tar.gz Source Package

Redmond and Cupertino, start your photocopiers!

Posted on December 10th, 2007

compiz-fusion

Today I will briefly discuss the Compiz-Fusion project. Compiz Fusion is an extension pack released for Compiz. Compiz is a compositing window manager. Compiz Fusion was created as a result of Compiz and Beryl joining hands and thus coming up with one of the best add-ons to my Linux distribution. Whether I use Gnome or KDE, Compiz-Fusion makes my experience on the Linux platform quite awesome! Here are some videos showing some Compiz Fusion functionality:

and here is another video

So hurry Redmond and Cupertino… I’d like to see this functionality in commercial OS’s.

Here are some useful links to check out:
Compiz Fusion
Compiz
Beryl Project

QtCoverFlowWidget using Core Animation and Qt

Posted on November 21st, 2007

Introduction

Core Animation is one very cool and interesting API provided by Apple in the Leopard version of Mac OS X. Core Animation can be used to attain some really cool effects like the Cover Flow view, which is available and seen in both iTunes and Finder. The Cover Flow has also been included in the new iPods and in the iPhone. It is an animated view of the files that one is browsing, whether the files are images, videos or documents. Cover Flow displays the preview…

This functionality is now available in Leopard and allows developers to take advantage of this feature by means of Core Animation. Core Animation is a part of the Quartz Core framework and is programmable by means of the objective-c API. This is nice if one’s application UI is written completely in Cocoa. However, why should Carbon developers not be able to take advantage of Core Animation? Well, Apple has thought of that as well. They have exposed a new API named the HICocoaView.

HICocoaView

The HICocoaView allows the developer to embed an NSVIew or any control derived from NSView into a Carbon HIView. This means that Core Animation could be included in a Carbon application. For more information on embedding Cocoa NSViews in a Carbon HIView please visit this link:

http://developer.apple.com/documentation/Cocoa/Conceptual/CarbonCocoaDoc/Articles/HICocoaView.html

Since Trolltech’s Qt framework is currently sitting directly on top of Carbon, I thought I would try and get Cover Flow working in a Qt Application by means of creating a custom widget, which I call the QtCoverFlowWidget.

QtCoverFlowWidget

The first thing we need to do is locate the code for Cover Flow. Conveniently, Apple has an example which ships with the freely available developer tools and it’s named CovertFlow. The entire CovertFlow project, including implementation is available in the following location on your disk:

/Developer/Examples/Quartz/Core Animation/CovertFlow

Basically, the bulk of the work is already done for us, thanks to Apple’s example. Now we must figure out how to wrap a QWidget around this implementation, such that we can use this CovertFlow view inside our Qt Application. So Let us begin.

Creating the project

I simply created a main.cpp from which I then generated an Xcode project. My main.cpp looked something like this:

#include <QtGui>
#include <QtCore>
class MyWidget : public QWidget
{
   Q_OBJECT
 public:
   MyWidget(QWidget *parent) : QWidget(parent) { }
 virtual ~MyWidget() { }
};
#include "main.moc"
int main(int argc, char** argv)
{
   QApplication app(argc, argv);
   QMainWindow *win = new QMainWindow;
   win->resize(600,300);
   win->show();
   MyWidget *w = new MyWidget(win);
   w->resize(400,200);
   w->show();
   return app.exec();
}

now let’s create the project:

qmake -project
qmake -spec macx-xcode QtCoverFlowExample.pro

The above will generate a QtCoverFlowExample.xcodeproj which we can open using Xcode 3.0.

Once the project is opened, there are some things that must be done. They are as follows:

Right click on main.cpp and click Info. In the General tab switch the File Type to “sourcecode.cpp.objcpp”. This is done to let the compiler know that this file contains objective c++ code.
Add QuartzCore and Cocoa frameworks to the project. AppKit framwork can be removed since the Cocoa framework acts as an umbrella around AppKit.
Import the relevant files from the CovertFlow project into our project. They are:

Catalog.h
Catalog.cpp
Controller.h
Controller.cpp
DesktopImage.h
DesktopImage.cpp
DesktopImageLayout.h
DesktopImageLayout.cpp
View.h
View.cpp

and View.nib must go to the Resources folder (create one if one does not exist)

The project should resemble something similar to this once the aforementioned steps have been completed…

Now that the project is created, we must create our custom widget that will display the CovertFlow view which is written using the Quartz Core framework.

Below is the code to our custom widget named QtCoverFlowWidget

class QtCoverFlowWidget : public QWidget
{
   Q_OBJECT
   public:
      QtCoverFlowWidget(QWidget *parent = 0) : QWidget(parent)
      {
         // instantiate controller for the covertflow view
	 HIViewRef coverFlowRef;
         controller = [[Controller alloc] init];
         //HICocoaView wrapper around covert flow view
         HICocoaViewCreate([controller view], 0, &coverFlowRef);
         create(WId(coverFlowRef));
         // connect resize of parent to resize of ourselves
         connect(parent, SIGNAL(resized(int, int)), this, SLOT(slotResize(int, int)));
      }
      virtual ~QtCoverFlowWidget() { }

   protected slots:
      void slotResize ( int w, int h )
      {
         // resize ourselves
         resize(w, h-20);
      }
   private:
      Controller *controller;
};

We derive the QtCoverFlowWidget from the QWidget class. The CovertFlow example that Apple provides is a classic example of an MVC application. Therefore, in the constructor of our custom widget, we instantiate the controller associated with the CovertFlow example. We then create and HICocoaView which wraps the NSView containing the Cover Flow view and then associate our widget with the HIViewRef associated with the HIView wrapping the NSView which contains the Cover Flow view. This is made possible by the fact that a QWidget is just an HIView on its own. Carbon API can be used to communicate directly to the QWidget, which is an HIView. There are some useful Qt functions which help bridge Carbon and the Qt API. These functions are:

// returns an HIViewRef/WindowPtr which is associated with the QWidget
HIViewRef qt_mac_hiview_for(const QWidget *w)
WindowPtr qt_mac_window_for(const QWidget *w)
// returns HIViewRef for a native Carbon Window and vise versa
HIViewRef qt_mac_hiview_for(WindowPtr w)
WindowPtr qt_mac_window_for(HIViewRef hiview)

In order for the above functions to be used in code, all you need to do is #include <QtGui>.

We also have a slot implemented named slotResize(int, int). This slot is hooked to the resized(int, int) signal which is emitted by the parent of this widget (our QMainWindow implementation). This can be seen in the example code here:

connect(parent, SIGNAL(resized(int, int)), this, SLOT(slotResize(int, int)));

The parent widget is actually a custom widget as well. Specifically, it is a custom implementation of the QMainWindow. Not much happens in this implementation except the interception of the resizeEvent(QResizeEvent *) and the action of emitting the resized(int, int) signal once that occurs.

Last steps

There are also a few things that must be done in order to have a properly integrated Cocoa event loop. The main function needs the following:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSApplicationLoad();
…
…
…
[pool release];

The above code ensures the Cocoa event loop is running and properly handling Cocoa events.

Now we can simply instantiate our custom QtCoverFlowWidget just like we do any other Qt Widget. All the code, including the Xcode project as well as the binaries can be found here…

QtCoverFlowExample.zip Binary Universal Bundle
QtCoverFlowExample_src.zip Source

And the results are….

Conclusion

The HICocoaView made the above possible. The HICocoaView is a power class allowing developers to mix Cocoa views inside their Carbon application. Perhaps next time we’ll do something with Apple’s QTKit.

A peek at Xcode 3.0

Posted on November 14th, 2007

I have been using Xcode 3.0 for some time now. It has worked quite well in production for me. Full of features and enhancements make it one of the best development environments to work with. One of the features which particularly strikes me as genius is the Project Organizer. This feature is available from the Window menu.

Not only does the organizer allow the developer to maintain a number of Xcode projects in an effectively organized way, but it also allows for building Makefile projects. This is in fact something new from Apple and is extremely convenient. Open source projects fit favorably in the little window which is brilliant to say the least.

But let’s take it one step further, not only is the Organizer an organizer, but it is also a lightweight SCM system. Sure it is a local, file based SCM system, but it is extremely useful.

This lightweight SCM functionality is by no means a replacement for the SCM system one uses. It is extremely light weight and allows for better organizing changes made on the local machine. This is quite beneficial for my needs as I often work on code involving a large number of changes which I perform incrementally. Once I reach a stable or satisfactory state of the development task, I simply create a snapshot. The reason I do so is because quite often it is not desired to check in one’s partial changes to the main code repository used by your project team, as it may inflict unnecessary, yet inadvertent, pain on them. This feature allows the developer to experiment effectively while maintaining a coherent and easily accessible history of changes. I often code in a location where there is no internet access and I am unable to check in my desired changes for example. During those times, I can simply create a snapshot and restore later when I am ready to perform the check in to the public code tree.

Let’s move on… so I began coding and I created a snapshot before hand. I made some changes and decided to Create another snapshot. Let’s see what this looks like…

As you can see, the file differences in the “Files Changed” list are displayed and right below that is the differences results, provided by Xcode’s built-in diff tool. Yes, it does look very similar to filemerge. The toolbar provides few operations but gives the user the ability to create more snapshots, delete snapshots and of course restore your project state to a particular snapshot.

Finally, the Organizer also possesses an editor, thus allowing the developer to perform all of his/her work from inside the Organizer.

Cut your wires! Well… not just yet.

Posted on November 16th, 2006


I was browsing around the other day and ran into an interesting post which discusses the idea of energy transmission without wires - wireless power. The post can be located here:

http://arstechnica.com/news.ars/post/20061115-8229.html

This is the research paper that describes the wireless power proposal in greater detail by MIT faculty and students:

http://arxiv.org/ftp/physics/papers/0611/0611063.pdf

Bridging the Gap: Integrating SCM Tools with IDEs

Posted on October 23rd, 2006

Introduction

Software configuration management (SCM) is an essential part of the development lifecycle process. An SCM tool assists in the development process and increases individual and overall team productivity. Because most developers use some type of Integrated Development Environment (IDE), it greatly benefits the development team to have an SCM tool that integrates with the IDE of their choice. Developers generally prefer to stay within the boundaries of their IDE when developing and maintaining code. Switching between an SCM tool and the IDE slows down the development process and prevents developers from reaching a high level of efficiency. Convenience and ease of use are also important issues when working with an SCM tool, therefore the SCM tool must seamlessly integrate with the IDE. A number of SCM tools for the Windows platform support the Microsoft Source Code Control Interface (MSSCCI), which allows providers to integrate into Microsoft’s Visual Studio suite. This article provides a glimpse into the MSSCCI. Seapine’s Surround SCM is used to illustrate a sophisticated integration with Visual Studio .NET 2005.

MSSCCI functionality overview

The MSSCCI is an old API designed by Microsoft that dates back to the Visual Studio 6.0 days. It is strict in nature but includes a rich variety of options that a particular SCM provider can support. This interface has evolved over the years by offering additional functionality, better and faster communication between the provider and the IDE, as well as usability improvements.The MSSCCI sets up a communication bridge between the provider and the Visual Studio environment. A Source Control Adapter resides inside Visual Studio and acts as a proxy between the IDE and the provider. All Visual Studio components, such as the Solution Explorer, the editor, the projects and the source control UI, communicate directly with the Source Control Adapter. The Source Control Adapter passes information to and from those components via MSSCCI. The provider, while adhering to the strict interface guidelines, has the ability to be quite flexible in the way certain operations are implemented. For example, the provider can display its own UI elements. In fact, this behavior is encouraged in order to provide a tighter integration between Visual Studio and the SCM provider. The ability to display UI elements also provides a way for the integration library to support advanced features for a number of operations in the MSSCCI.

Hurdles, potholes, and more

As previously stated, the integration comes in a library form and implements the MSSCCI. The MSSCCI supports an advanced feature set, which allows the provider to support additional functionality. However, not all functionality of each provider can be implemented. While working on Surround’s integration, it quickly became apparent that it is next to impossible to implement direct support for branching in the integration library. Sure there are ways to do this, but they are neither clean nor desired since they may confuse users. MSSCCI does not directly provide support for branching in its current form. In Surround’s case, it is advised to perform any branch level operations using the Surround GUI client or the Surround CLI client. However, the beauty of the tight integration is the way a project works after it has been branched. The branched project, when opened from Visual Studio, behaves and functions as expected without any additional modifications or maintenance required from the user.In the early version of the MSSCCI documentation, it was difficult to really understand why certain calls were being made to the integration library. The documentation says one thing while Visual Studio acts differently and calls a different function in the integration library or calls the functions out of sequence. Trial and error techniques were generally used in the early stages of the development process because the behavior did not match the rules. One example of this was the expectation that the integration library would send a list of supported capabilities so Visual Studio’s Source Control Adapter could communicate with the library fittingly. We did just that with Surround SCM, sending back such a list to Visual Studio. However, even when certain operations were either supported or not supported by our library, calls to these functions were made incorrectly by Visual Studio. Over the years, this part of the MSSCCI has improved along with the documentation. Bug fixes in the interface and the Visual Studio IDE have improved functionality and performance in addition to resolving most problems.

How does Surround SCM integrate with Visual Studio?

To enable the integration library several Windows registry settings must be set prior to launching Visual Studio. The registry settings simply point to the location of the integration library, as follows:

The key

[HKEY_LOCAL_MACHINE\Software\SourceControlProvider] = “Software\Seapine Software\Surround SCM\Scci”

The key

[HKEY_LOCAL_MACHINE\Software\Seapine Software\Surround SCM\Scci]

contains the following string values:

SCCServerName = “Surround SCM”
SCCServerPath = “C:\Program Files\Seapine\Surround SCM\Surround SCM SCCI.dll”

The Surround SCM installer takes care of this setting during the install process. After the integration library is registered, Visual Studio enables the Source Control in its main context menu (as seen in Figure 1) as well is in the File menu for the IDE.Adding existing Visual Studio Projects is a trivial task with Surround SCM integration into Visual Studio.

Figure 1

Other operations including Check In, Check Out, Undo Check Out, Get, Diff, History, Remove, and Rename are similar in structure and should also be implemented with the same basic foundation as shown in the previous code snippet.After the “Add Solution to Source Control” option is selected, the Source Control Adapter communicates with the integration library to perform the desired task. The MSSCCI sends information to the library and the library performs the add operation after manipulating some of the data that is passed in.

 1 long CMSSCCIController::AddFiles(const StringList &files, const String &advancedOptions, const long flags)
 2 {
 3    long rtn = OPERATION_OK;
 4    try
 5    {
 6    	// process list of files if needed
 7    	// process flags if needed here
 8    	// process advanced options here
 9    	CMSSCCIAdvancedOptions addAdvancedOptions(advancedOptions);
10
11 	// perform add
12    	rtn = m_pServer->ProcessAddFiles(files, &addAdvancedOptions);
13    }
14    catch()
15    {
16    	rtn = OPERATION_UNKNOWN_ERROR;
17    }
18
19    return (rtn);
20 }

Additional logic may be required for any advanced options or extra flags being passed into the integration library. It is a good practice to place all the operations inside a try/catch block since strange things may happen otherwise. A crash inside the library may yield erroneous dialogs from Visual Studio or, even worse, cause the whole IDE to crash.Additional flags or advanced options in the add operation may signal some additional useful information for the SCM provider. For example, if the files are all text files then a flag can be set to indicate this. The SCM provider can then save time by omitting its auto-detection scheme. The advanced options, driven by the integration library, can turn on options such as “Perform a Get after an Add” or “Check out files after Add” if so desired by the user. Other advanced options, such as change list usage, are also incorporated with Surround’s implementation.

File detection and association

Each provider uses different methods to determine if a file or a set of files have a specific status and whether or not they are in a controlled or a non-controlled state. Surround SCM uses local hidden files and server communication for determining this information. When a project is initialized and opened by the integration library, the logic to check for file status and state is comparable to the following:

 1 long CMSSCCIController::GetFileInfo(const StringList &files, long* fileStatus )
 2 {
 3    long rtn = OPERATION_OK;
 4    try
 5    {
 6       if (m_pCacheObject != NULL)
 7       {
 8          // process file list if needed
 9          if (m_pCacheObject->IsCacheOutDated())
10          {
11             // if data is outdated, query the server
12             rtn = m_pServer->ProcessGetFileInfo(files, fileStatus);
13          }
14          else
15          {
16             // otherwise check cache for file status
17             rtn = m_pCacheObject->ProcessGetFileInfo(files, filestatus);
18          }
19       }
20    }
21    catch()
22    {
23       rtn = OPERATION_UNKNOWN_ERROR;
24    }
25    return (rtn);
26 }

The file status and state results are transferred to the Source Control Adapter, which then performs all the necessary updating inside Visual Studio based on the status flags it acquired from the integration library. Figure 2 illustrates how the results are posted to the Visual Studio shell.

Figure 2

Each glyph, displayed next to the file icon, represents the file’s status in the Solution Explorer. The controlled elements are visually indicated by a padlock while checkmarks and other glyphs are used for additional status flags.

Accessing the SCM tool from the IDE

This operation is the most trivial to implement since the implementer has full control over the SCM tool that is launched. SCM providers that do not have a GUI client cannot truly take advantage of this feature. When the DLL is registered by Visual Studio and the Source Control menus are enabled, the “Launch provider” menu item is displayed and enabled (See Figure 3).

Figure 3

he reason this implementation is trivial is because data manipulation does not take place. We simply look up the install root folder of Surround SCM from the Windows registry and start a new process. The ability to launch the Surround GUI client from inside Visual Studio allows the user to perform some advanced operations that are not included in the integration due to the strict interface guidelines imposed by MSSCCI. At the same time, the IDE allows the user to perform all operations from inside its shell, which includes the launching of the GUI client for advanced operations.

Conclusion

Seamless integration between an SCM tool and an IDE is a huge benefit to the developer, the development team, and the company. With all the SCM operations and actions available from the IDE’s shell, developers are more productive, giving them and the company the extra edge. The MSSCCI API is strict in nature but allows the opportunity for tight integration if the provider chooses to perform the implementation.Microsoft Source Code Control Interface information, documentation, and sample source code is available online: http://msdn.microsoft.com/vstudio/extend/.

How hungry is Firefox?

Posted on October 17th, 2006

From personal experience, it’s ridiculously hungry for RAM. More often than not I have multiple windows open, each one having a number of tabs, with content. With 1 GB of RAM in my Dell, I expect this to work flawlessly. However, the OS performance degrades tremendously. Windows XP becomes increasingly less responsive and thus hinders my ability to have a smooth experience. Firefox eats up 150-250 MB RAM on a regular basis. It appears as if Firefox doesn’t periodically release memory. Even closing tabs does not necessarily decrease the process’ memory usage. After some investigation, I have discovered that the Mozilla Corporation has provided a hidden Firefox configuration option, which in turn performs exactly what I want Firefox to do by default. This configuration option forces Firefox to perform a memory release, similar to the Java’s System.gc() call, but it is guaranteed by Firefox to perform this operation, unlike the Java garbage collector. This configuration option is triggered by a minimize action performed by the user.
The following steps will configure Firefox to take advantage of this hidden feature:

1. Browse to about:config inside the Firefox browser
2. A configuration screen will be displayed. Right click anywhere on the page and choose New->Boolean
3. Enter “config.trim_on_minimize” in the preference name text field and click OK
4. Set the value of this preference to “true” and click OK

Restart Firefox, load up some pages, but don’t forget to minimze!