iosart.com | projects | articles | photos | about

Firefox extension update failure

August 13th, 2004

Update: This issue (bug 252543) has been solved in Mozilla, so the workaround is no longer needed.

I have written a Firefox extension which uses an XPCOM component. When the extension is installed and the user will try to install a newer version of the extension, the installation fails.

The reason for the failure is that the old version of the extension is already loaded when the new version installation is attempted. The XPCOM component DLL is in use and it cannot be overwritten with the new version of the DLL.

So, what happens is that the old version of the extension remains installed and the Extension Manager says “the extension will be installed the next time you start Firefox” no matter how many time you restart the browser.

Making the users uninstall the old version of the extension before installing the new one solves the problem, but it is not a very user friendly way of solving this.

My solution:

  1. Detect the situation. To detect the situation, my extension queries the Extension Manager on every startup. If it detects that there is a version of the same extension (self) with a status “toBeInstalled”, it probably means that the user has installed a new version of the extension and the installation failed. Otherwise the status would have been “installed”.
    If this situation is detected, I move (rename) the component DLL MyComponent.dll to MyComponent.dll.uninstalled. This will succeed, because you can rename a DLL when it is in use, even though you cannot remove or overwrite it.
  2. I then notify the user that an additional restart of the browser is needed.
  3. When the browser is started for the next time, the installation will succeed because the file
    MyComponent.dll is no longer in use.

One little point that shouldn’t be overlooked – we have created a new file, MyComponent.dll.uninstalled, in the components directory. This file will not get deleted when the extension is uninstalled, because we never installed it. To solve this, I have packaged an empty MyComponent.dll.uninstalled file with the extension. Because this file has and “uninstalled” extension, it is ignored by everyone. When it is time to uninstall the extension the file is removed along with all the other extension files.

I can provide the complete source code (in Javascript) for this technique on request.

Internet Explorer Filter Quirks

June 30th, 2004

My online photo galleries show thumbnails of the photographs for every folder. Sometimes after reloading a gallery page some of the off-screen thumbnails weren’t rendered – only a gray rectangle appeared instead of the image. Hovering over the thumbnail revealed the correct image.

The thumbnails have a filter:progid:DXImageTransform.Microsoft.Shadow(...) CSS style applied to them which means that they have a nice shadow. Removing this style solved the problem, but obviously the gallery looked less nice.

Pim Rijpsma explained to me that the problem is caused by a buggy DirectX implementation – Internet Explorer uses DirectX to apply the effect and for off-screen images the image sometimes “gets stuck” in some internal buffer. Hovering over the image creates another request and the image is finally shown.

Obviously, I have no control over people’s DirectX version. Hovering over the problematic images makes things right, so why not simulate this hovering over all the thumbnails after the page loads? I ended up using the following code:


<!--[if gte IE 5.5]>
<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript">
function RefreshThumbnails() {
  var aReturn=document.body.getElementsByTagName("A");
  for(i = 0; i < aReturn.length; i++) {
    if (aReturn[i].currentStyle.filter != '') {
	 aReturn[i].setActive();
    }
  }
  window.status = 'Done';
}

window.onload = RefreshThumbnails;
</SCRIPT>
<![endif]-->

Basically, the code checks if the browser is IE5.5 or newer. If so –
go over all the Anchors which have filters and activate them (which is apparently similar to hovering).

The code is executed on page load. It solves the problem quite nicely.

Crazy layout dance

May 27th, 2004

I have noticed that several HTML pages change their layout wildly while loading in the browser. Apparently, this behavior was caused by images at the top of the problematic pages. The image was added using JavaScript: document.writeln("<IMG SRC=...>");.

Internet Explorer didn’t like that – it had problems determining the correct page layout while loading, so it used a preliminary layout first and then the final layout. This switch in layout in the middle of loading was the reason for the annoying “jumps”.

I switched to server side include techniques (mod_include and PHP “virtual“) so the browser gets the page as the final HTML – image and all.

Fooling Apache

May 26th, 2004

Tweaking with the Apache configuration, I encountered some pretty interesting problems.

I used mod_rewrite to serve different content based on the HTTP request. Basically, what I was trying to do is this: there are two domains, “one.com” and “two.com” both pointing to the same server. If the user used the first domain name in the address, serve “Page A”, else serve “Page B”. This can be accomplished quite easily by using the RewriteCond %{HTTP_HOST} ^one.com$ directive.

I used the above technique and all was well, until I noticed that the images served by the one.com domain are not being cached by the browser! To find out what was going on I used wget with the “-S” option to see the full header returned by the server. The server was returning a header which included a “Vary: Host” field, which means that the server didn’t serve a regular static page, but its reply depends on the “Host” field in the HTTP request. Browsers interpret this as “the content returned is dynamic, don’t cache it.

I needed to get rid of the “Vary” header. One option was to use the Header unset Vary directive, but that requires mod_header module, which is unfortunately isn’t included in my server. Another option is to use the SetEnv force-no-vary directive. This tells the server not to return the “Vary” field.

It seams like problem solved… Not exactly. SetEnv force-no-vary along with suppressing the “Vary” header, forces the response to be HTTP/1.0. Why is this a problem? When serving HTTP/1.0, some advanced features of HTTP/1.1 aren’t used. One of these features is “Keep-Alive”. This feature can increase the loading time of the page by up to 50% by using the same connection for more than one request. Turn this off and it takes much longer to load pages with many images – and this incidentally was exactly the type of pages I was serving!

So “SetEnv force-no-vary” is out too. What can be done to make the server stop sending the damn “Vary” header? I needed a way to fool the server so it doesn’t notice I’m checking the Host header field. A simple solution then came too mind – what if I save the HTTP_HOST value in an environment variable and use this variable in the condition directive. The server won’t have any way of knowing that this variable actually contains the HTTP_HOST and stop sending the “Vary” field. I used the following code:


RewriteRule .*  - [E=MY_HTTP_HOST:%{HTTP_HOST}]
RewriteCond %{ENV:MY_HTTP_HOST} ^one.com$

The first line sets a new environment variable “MY_HTTP_HOST” and initializes it with HTTP_HOST. The second line is the condition and it looks to the server as if I check a regular environment variable. This finally solved the problem.

IE6 CSS bug

May 26th, 2004

DHTML – using a floated DIV followed by a <DIV STYLE="clear:both;"> causes some strange behavior in IE6 – a large portion of the page disappears and reappears randomly after refresh and/or mouse hover.

What was happening is that the above configuration brought out a bug in IE6 and it drew the (white) background OVER the text in the DIV. Removing the background: white; from the style sheet solved the problem, but I really needed the background to be white. Putting the same background setting on the parent container solved the problem.

MFC blues

May 26th, 2004

A release build of a MFC application crashes, while the Debug build works fine.

The crash analysis shows that the stack has been overwritten and thus destroyed.
Further analysis reveals that the crash occurs inside a ::SetWindowText call in a CEdit sub-classed object. This shouldn’t be my code, right? Wrong.

What was happening is that somewhere inside the call the framework called my OnUpdate handler (setup with ON_CONTROL_REFLECT_EX). The problem was that the handler was defined having a wrong prototype: BOOL OnUpdate(NMHDR* pNotifyStruct, LRESULT* result) instead of BOOL OnUpdate(). The framework doesn’t perform type checking – the function pointer is just being casted and the call is being made. So, no parameters are being pushed, but two parameters are popped – and the stuck is trashed.