Snippets code from my daily experience

October 18, 2009

.NET Framework Assistant, automatic plugin installation and PluginChecker

Filed under: extension, plugins, xul — dafi @ 2:21 pm

In these days the net is populated by blog posts about the .NET Framework Assistant plugin for Firefox, its disabling and the fact Firefox does not warn user when a plugin installs itself without explicit permission.

Well, this is a old problem at least for me, indeed I discovered it some time ago when my Firefox crashed (apparently) without reason, discovering after a couple of days that Microsoft Office 2003 plugin fought with Foxit Reader and Google update plugins.

The problem was that I never installed Office plugin!

plugins

Disabling Office plugin Firefox stopped to crash.

After that experience I decided to write a simple (very simple) extension that at every Firefox startup checks if there are new plugins installed.

plugincheckerNothing so cool, only a quick and dirty solution implemented in a few of hours.

Waiting Mozilla implements a better solution than mine you can install PluginChecker.

If you expect to find PluginChecker innovative or the “I-can-live-without-it” extension you are on the wrong place, if you expect a not intrusive and simple solution to unattended plugins installation than you can take a look at it.

You can download PluginChecker from SourceForge.

September 14, 2009

Table2Clipboard 1.0 now preserves styles

Filed under: excel, extension, firefox, openoffice, table2clipboard, xul — dafi @ 6:49 pm

Finally after almost a year I release a new version of Table2Clipboard, one of twelve extensions that won in 2008 the Firefox 2 Contest in the section Runners Up.

What’s new

Until now Table2Clipboard has pasted to clipboard the structure of HTML tables without the styles (colors, borders, fonts) but many users have asked me that the behavior was much more similar to that of Internet Explorer (IE) which indeed maintains many details.

Well, the version 1.0 preserves the styles and in certain cases the result is better than that obtained with IE.

IE inserts also the DOM elements declared “not visible”, for example the table shown in Figure 1  is pasted in Excel as shown in Figure 2.

ie

Figure 1

Table selection on Internet Explorer

excel-from-ie

Figure 2

Copy from Internet Explorer paste to Microsoft Excel

Table2Clipboard discards hidden DOM elements as shown in Figure 3, this makes more sense for me.

Paste from Firefox with Table2Clipboard to Microsoft Excel

Figure 3

Copy from Firefox with Table2Clipboard paste to Microsoft Excel

Other little improvements

Now web links are copied and user can choose to copy images (tag IMG), too.
All defaults settings can be modified from configuration dialog.

The copy of styles on OpenOffice doesn’t work as well as the one on Microsoft products.
The “Paste Special” feature available on OpenOffice doesn’t recognize CSS styles but only deprecated tags like FONT.

I will add support for OpenOffice soon but I prefer the “release early release often” (after a year??? :P ) approach so this version has poor styles support on the popular open source office automation suite.

Compatibility issues with Thunderbird 3.x are now fixed.

Table2Clipboard can be installed from AMO or from the project site on dafizilla.

August 1, 2009

Table2Clipboard and clipboard application interoperability

Filed under: calc, clipboard, excel, extension, openoffice, table2clipboard, xul — dafi @ 10:35 am

calc_excel_t2cMany users asked to me to add to the extension Table2Clipboard (T2C for friends) the ability to preserve web links and maintain the styles during tables copy.

Preserving links and other HTML tags was a very easy task, I’ve written the code very quickly and both OpenOffice Calc and Microsoft Excel have handled correctly the pasted content.

When I started to support style preservation I discovered different and ugly results on the two popular office suites making harder to write cross platform XUL code.

Actually T2C pastes to clipboard inserting data in two different formats (flavors), unicode plain text and HTML format.
When users do “Paste Special” the HTML format is pasted and applications (Excel or Calc) render inside the data sheet.

Both Excel and Calc handle only the deprecated FONT tag and a subset of TABLE tag attributes and this represents a great limitation for style preservation from T2C.

If you try to paste from Microsoft Explorer to Microsoft Excel you discover everything is copied, the styles are totally preserved but if you paste from Explorer to OpenOffice Calc all style are lost!!!

Well, Explorer inserts to clipboard also RTF formatted text and Excel works very fine with the barely public RTF file format.

Clipboard application interoperability goes to hell, HTML is not fully supported by the “Paste Special” feature available on both suites, and as usual Microsoft uses semi proprietary data formats to exchange informations between applications.

I think at least OpenOffice should improve its “Paste” feature simply adding support for HTML style attribute.

T2C can preserve correctly styles only implementing platform specific code for OpenOffice and Microsoft Office and I really hate write specific platform.

I’m considering other alternatives but I see only the darkness of C++, OLE and core dump…

July 18, 2009

Discontinue extensions support for some applications

Filed under: extension, firefox, flock, komodo, kompozer, seamonkey — dafi @ 4:46 pm

Before publish new updates for my extensions I try to test them on every application declared supported on install.rdf, this is a very expensive activity when a specific extension runs on different kind of applications and versions.

I add support for a new application (e.g browser, email client, multimedia applet)

  • when I use the application itself and I need the extension functionality on it
  • when other users ask to me

Now I must decide to drop support for some applications and for specific versions to simplify my release tests cycle.

In some cases it’s easy to decide, for example Firefox 2.x is no longer supported by Mozilla and users continuing to use it are braves or simply fools.

Supporting SeaMonkey 1.x is very hard for me, no special technical problems SM is a very good product but I simply don’t use it.
Instead I’m a satisfied SeaMonkey 2.0 user since alpha1 version.

Supporting Flock, the “social” browser, is easy due to the fact is very compatible with Firefox 3.x but sometimes little differences caused me headaches.
I think to drop support for extensions not Flock centric considering the decision taken from its team last December

Komodo 4.x is no longer upgraded by ActiveState but many people continues to use it, Komodo has a commercial version, KomodoIDE, and not all users purchased the upgrade (me too) so it is very difficult to drop the very old 4.x architecture.

NVU is dead but many users continue to use it also if its sibling/son Kompozer should be strong preferred.

What specifically means “discontinue support”

I would to remove specific tricky code present in extensions to make them cleaner but this can be a bad solution, regressions are always possible so the cure can be worse than the disease…

Removing SeaMonkey 1.x support will make my extension build system cleaner no longer install.js, contents.rdf  and informations present both in install.rdf and chrome.manifest, obviously I don’t discard support only to remove a couple of configuration files but I consider it another complication.

So, “discontinue support” for me means moving attention and energies on applications (and versions) I can test easily, on application I daily use, on applications I receive feedback from other users.

June 5, 2009

gContextMenu’s imageURL property refactored on Firefox 3.5x

Filed under: extension, firefox, xul — dafi @ 5:04 pm
Tags: , , ,

Edited on 9 June 2009 Mozilla guys decided to add a getter for imageURL so no extension will be affected by new property mediaURL replacement, you can read the full story at bug 497098.

Another time Mozilla community demonstrates its strength, why nobody considered the impact before modification is another story ;)

Today a ViewSourceWith user filed a bug about a regression on Firefox 3.5b4, causing VSW to no more open images 8O

After dressing the debug uniform I started to investigate the problem.

I’ve realized the object gContextMenu doesn’t more contain the property imageURL used by VSW and maybe many other extensions.

The imageURL property has been renamed/refactored to mediaURL.

Honestly the new name fits better its new usage and maybe the imageURL property is not intended for usage from extensions.

The poor gContextMenu documentation doesn’t describe imageURL so maybe I abused its usage.

I think gContextMenu need a better documentation because its usage is so sexy inside extensions.

The workaround

A string find/replace inside code fixed the bug, to maintain compatibility with FF 3.0.x I’ve modified the code as shown below

var imageURL = gContextMenu.imageURL || gContextMenu.mediaURL;

April 1, 2009

Colored file tabs for Komodo

Filed under: extension, komodo, macro, openkomodo, xul — dafi @ 1:37 pm

A couple of months ago I wrote a Komodo macro allowing the editor view tabs to be colored based on user defined color schemes, when the macro became stable I published it on Komodo community forum.

Amazingly the macro received more feedback so I decided to ‘convert’ it to an XUL extension.

Komodo macros are fantastic but they don’t allow to create complex UIs so moving them to XPI become a necessary step.

Now ColorTab is ready and can be downloaded from here.

The original name was KolorTab, the ‘K’ letter used to remember Komodo but I’ve decided to use a more tradictional name :P

ColorTab look&feel

ColorTab look&feel

February 3, 2009

Firefox spelling checker and multiple dictionaries

Filed under: extension, firefox, spelling — dafi @ 10:00 am

When Firefox integrated the spelling checker I didn’t immediately realized its value, but using it day after day I became “spell” addicted and now I can’t imagine my browser without this feature.

You can install all dictionaries you need, but many people uses only the dictionary for its own language.

Obviously I’m not a normal person so I use three dictionaries; Italian, English and French switching between them when necessary.

Following Murphy laws every time I start to type inside a input box I discover I’m using the wrong language and I must switch it from context menu, a very annoying practice.

Finally I’ve solved this problem writing the extension SpellBySite.

SpellBySite switches automatically to the correct dictionary looking for it on user settings.

For example user can set English dictionary for mail.google.com, Italian for twitter.com and so on.

When input boxes receive focus the dictionary is set and spell checking executed, no more needs to switching from context menu :D

Now my life is a bit easier :P

PS
SpellBySite is waiting on AMO to escape from sandbox ;)

December 22, 2008

Downloading protected resources using nsIChannel and friends

Filed under: babelzilla, extension, komodo, macro, nsIChannel, nsIStreamListener — dafi @ 2:35 pm

A couple of days ago I needed to automate file downloading from a service, a very trivial task in every programming language (or using wget).

The little complication was represented by the web based authentication mechanism (userid/password) needed to access to files.
Determining which files to download and their usage (unzipping and picking files) required some specific business logic, nothing really complicated but very annoying.

After a while I realized this job can be done using Javascript and XPCOM and here I would share the solution based on nsIChannel.

What is does

  • the service uses userid and password to login
  • login to the service using HTTP POST method, it simulates an HTML <form/> submission
  • store the cookies sent from server. They contains credentials login data, cookies usage is a prerequisite in our scenario
  • reuse login data to download protected resources

Example usage

Suppose you want to automate download of extensions stored on AMO’s sandbox, you must login first so this use-case is perfect for us.
Someone can consider this approach ugly, web services or Remora API are better but here I only want to demonstrate how to use nsIChannel.

Let’s start…

You can write the Javascript code shown below to download my extension RichFeedButton (dropped on sandbox an year ago)

var amoUsername = "dafi@localhost";
var amoPassword = "my_secret_code";
downloadProtectedResource(
   "https://addons.mozilla.org/it/firefox/users/login",

   "data[Login][email]=" + amoUsername + "&data[Login][password]" + amoPassword,

   "https://addons.mozilla.org/en-US/firefox/downloads/file/33926/richfeedbutton-0.0.21-fx.xpi",

   "/tmp/richfeedbutton-0.0.21-fx.xpi");

where our downloadProtectedResource function signature is shown below

function downloadProtectedResource(loginUrl, postData, resourceUrl, destPathName) { ... }

Nothing special, simply we need to know the HTML input names used for userid and password (ie data[Login][email] and data[Login][password]) and pass them in postData argument.

The downloadProtectedResource interacts with nsIChannel (nsIHttpChannel) and other XPCOM object

function downloadProtectedResource(loginUrl, postData, resourceUrl, destPathName) {
   var httpChannel = makeHttpChannel(loginUrl); // create an object nsIHttpChannel
   var stream = makeStringStream(postData); // create an object nsIStringInputStream
   setChannelPostData(httpChannel, stream); // fill data using nsIUploadChannel

   // downloader saves data on disk
   var downloader = new Downloader(resourceUrl, destPathName);
   // make a login then passes cookies to downloader object
   var cookieListener = new CookieRetrieverListener(downloader);

   // start authentication and download
   httpChannel.asyncOpen(cookieListener, null);
}

The object Downloader and CookieRetrieverListener implement the nsIStreamListener interface.

The cookieListener after obtaining cookies aborts the operation because we don’t need all server output, then it calls the downloader.

function CookieRetrieverListener(downloader) {
   this.downloader = downloader;
   this.cookies = "";
}

CookieRetrieverListener.prototype = {
   onStartRequest: function(request, ctx) {
         var channel = request.QueryInterface(Components.interfaces.nsIHttpChannel);
         this.cookies = channel.getRequestHeader("Cookie");

         // no need more data
         throw Components.results.NS_ERROR_ABORT;
   },

   onDataAvailable : function(request, context, inputStream, offset, count) {
   },

   onStopRequest: function(request, ctx, status) {
      this.downloader.cookies = this.cookies;
      this.downloader.start();
   }
}

Another way to use this code consists to download localizations from BabelZilla as shown below.
BabelZilla requires many parameters on query string :?


var bzUsername = "dafi_duck";
var bzPassword = "my_secret_code";
var bzItemId = "88";
var bzExtId = "4432";
downloadProtectedResource("http://www.babelzilla.org/index.php",
                 "op2=login&lang=english&message=0"
                        + "&option=ipblogin&task=login&0b14737c5ade1f7697a8f81b33b0bacf=1"
                        + "&option=com_frontpage&Itemid=1"
                        + "&username=" + bzUsername
                        + "&passwd=" + bzPassword,
                 "http://www.babelzilla.org/index.php?option=com_wts&type=downloadtar"
                        + "&Itemid=" + bzItemId
                        + "&extension=" + bzExtId,
                 "/tmp/vsw.tar.gz");

nsIChannel.asyncOpen

Accessing to cookies received from server requires to use nsIStreamListener available only in asynchronous open calls.

This needs to start the download only when cookies are surely retrieved, this is achieved using the nsIRequestObserver.onStopRequest, any better idea is very appreciated.

Complete code

The complete code contains a few of helper functions (reading binary stream, saving file) and is available on SVN, it’s ready to be executed as Komodo macro simply setting userid and password.

November 21, 2008

Komodo ViewAbout

Filed under: extension, komodo, mozilla, openkomodo, xul — dafi @ 7:42 pm

After reading ViewAbout post written by Gary Kwong I was curious to see what Komodo should have shown.

Komodo doesn’t require to write an extension to implement a similar feature, it is sufficient to write a macro ;)

So I’ve written the code that adds a popup menu inside Help menu and amazing it worked immediately :D

The macro can be triggered at startup but the menu will be added only on first open window because Komodo doesn’t have a “on open new window” macro event but it can be easily simulated adding a listener.

The code shown below is the complete Komodo Javascript macro, nothing else is necessary. (EDIT Thanks to Mook to point me how to remove the hardcoded abouts list)

aboutview


var abouts = [];
for (var c in Components.classes) {
    var m = c.split(/=/);
    if (m[0] == "@mozilla.org/network/protocol/about;1?what") {
        if (m[1]) {
            abouts.push(m[1]);
        }
    }
}

var menuAbouts = document.createElement("menu");
menuAbouts.setAttribute("label", "All abouts:");

var menuAboutsPopup = document.createElement("menupopup");
menuAbouts.appendChild(menuAboutsPopup);

var helpMenuSeparator = document.getElementById("menu_helpShowKeybindings").nextSibling;
var helpMenu = helpMenuSeparator.parentNode;
helpMenu.insertBefore(menuAbouts, helpMenuSeparator);

for (i in abouts) {
    var menuitem = document.createElement("menuitem");
    menuitem.id = abouts[i];
    menuitem.openAbout = openAbout;
    menuitem.setAttribute("label", abouts[i]);
    menuitem.setAttribute("oncommand", "this.openAbout('" + abouts[i] + "')");
    menuAboutsPopup.appendChild(menuitem);
}

function openAbout(about) {
    var docSvc = Components.classes['@activestate.com/koDocumentService;1']
                    .getService(Components.interfaces.koIDocumentService);
    var doc = docSvc.createDocumentFromURI("about:" + about);
    ko.views.manager.topView.createViewFromDocument(doc, "browser");
}

October 15, 2008

SeaMonkey 2.0a1 and the mistery of the disappeared toolbar button

Filed under: extension, seamonkey — dafi @ 8:33 pm

I’m preparing the new ViewSourceWith release so I’ve decided to test it under the alpha version of SeaMonkey.

The SeaMonkey two dot zero is a little revolution (at least for me) because it’s based on Gecko 1.9 and is closer to Firefox, finally it uses the standard extension manager and many other benefits for extension authors.

After tweaking maxVer and installed VSW I noticed the VSW toolbar button is missing, trying to enable it from “Navigation Toolbar” Preferences dialog produced no result :(

A regression? A new container id to use?

After some frustrating hours I discovered SM2.0a1 doesn’t handle toolbar buttons like Firefox 2.x/3.x and amazingly it doesn’t work like SM 1.1.x 8O

Restoring VSW toolbar button required the following modifications

The overlay uses nav-bar id for browser toolbar button (svn code)

<hbox id=“nav-bar”>
<toolbarbutton id=“viewsourcewith-button” insertafter=“stop-button”/>
</hbox>

and composeToolbar for mail composition window

<toolbarpalette id=“composeToolbar”>
<toolbarbutton id=“viewsourcewith-button” insertafter=“button-attach” />
</toolbarpalette>

This is sufficient to finally show the icon but to allow user to decide to hide/show button you must handle the navigator_preferences inside pref-navigator.xul’s overlay (svn code)

<preferences id=“navigator_preferences”>
<preference id=“browser.toolbars.showbutton.viewsourcewith” name=“browser.toolbars.showbutton.viewsourcewith” type=“bool”/>
</preferences>

and declare its usage into checkbox element

<groupbox id=“prefShowButtonsBox1″>
<vbox>
<checkbox id=“viewsourcewithButton”
label=“ViewSourceWith”
preference=“browser.toolbars.showbutton.viewsourcewith”/>
</vbox>
</groupbox>

and finally they lived happily ever after…

The question is… Why is it so difficult to standardize the toolbar handling within XUL applications?

At least Komodo, SeaMonkey and Firefox use different ids and overlays (Flock and Songbird are more closed to Firefox).

I can figure out Firefox is a browser and Komodo is an editor with different application requirements but I can’t understand why SeaMonkey, especially the 2.0 version, doesn’t adopt the same Firefox elements.

Maybe the final 2.0 will simplify more the extension developer’s life also for handling toolbar button.

BTW SeaMonkey2 is very cool ;)

Next Page »

Blog at WordPress.com.