Archive for the ‘Firefox’ Category

What’s New in Firefox

September 14th, 2005 by daryl

Chris pointed me to this nifty video showcasing some of the features in the latest version of Firefox. There’s some pretty nice stuff in there; most useful to me will be the ability to reorder tabs without having to load an extension to do so.

Dr. FogBugz

September 1st, 2005 by daryl

Or, how I learned to stop worrying and import the bugs. Hrrmmmm.

So my company’s looking at switching from using the beastly Bugzilla bug tracking software to using something called FogBugz. It seems a decent enough piece of software, though the install process went as follows:

  1. Download and untar install files.
  2. Learn from the readme that it requires a PHP extension, a daemon, and (for me) a PHP upgrade. This is all rather more intrusive than most bug software I’ve seen, though to be fair, Bugzilla also has a lot of dependencies.
  3. Upgrade PHP.
  4. Run a script at the command line to make sure dependencies are all worked out.
  5. Start the daemon.
  6. Run a wizard on the Web to set up the database, etc.
  7. Buy and submit license key.
  8. Worry about importing bugs from old bug tracker into new one.

This last item is the one that’s taken up some four hours of my morning today. FogBugz apparently ships as an asp application, but there’s a PHP version that we’re using. For the Windows version, there’s a script to import from Bugzilla, but it’s hosed on Linux. It seems to tap into stuff set in the PHP extension that’s Windows-specific or something. So I worked a little magic using some PEAR classes and was able to connect to Bugzilla’s xml interfact to retrieve bugs.

But I was getting authentication errors. Apparently, if you’re not logged in, you can’t see bugs using Bugzilla’s xml interface. I tried a couple of things and finally just used links at the command line with the -source flag to get all of our bugs as text files. I had to browse to our Bugzilla install using links and login first, though, so that the cookie would be set and subsequent connections would be able to see the xml data rather than the “NotPermitted” error.

So, now I’ve got 700ish bug reports in a directory. Time to hack the import script to make it work using my data rather than the obfuscated methods available through the Zend extension. This was just a little tedious and mainly consisted of finding objects and function calls and replacing them with arrays and keys that hold the corresponding data from my parsed xml. That is, the shipped code gets an xml file and creates objects to hold the data, while my code slurps in the xml and creates a nested array for each bug; I had to make the import script read my arrays rather than looking for objects. There were a couple of little hitches that were easily fixed, and before too long, I had my 700ish bugs imported into FogBugz.

But I noticed when reviewing my new bug list that I had a bunch of bugs that weren’t mine, and others had bugs that should have been mine. Moreover, most of the bugs were assigned to just two of us. Why this happened I have no idea. To fix it, I wrote a script that reconciles user ids between the two systems and changes bug assignment in FogBugz for each bug to what the assignment in Bugzilla originally was. For example, say user X in Bugzilla has numeric id 5, while he has numeric id 22 in FogBugz (just because of the way the users were imported). Luckily, both systems use the email address as the login, so I could query both databases, get the numeric id for each, and then do a query for each bug that says (in English) “Change the assigned-to field for bug 700 to the numeric id 22 because the numeric id for assigned-to in Bugzilla is 5, and user 5 in Bugzilla corresponds to user 22 in FogBugz because they map to the same email address.”

And voila, my bug list is as it should be. I’m sure we’ll find problems here and there, but by and large, I’d say it was as successful an import as could have been hoped for.

Flock

August 4th, 2005 by daryl
Flock 0.1So I can’t say much about it yet, but I’ve spent the last couple of weeks tearing my hair out in an effort to release Flock 0.1, which my company is pitching as a tool for a new (social) browsing experience. There are many bugs yet (they’ll be cause for hair-tearing over the next month), but it feels like we’ve got a pretty solid alpha release. If you’re interested in finding out more or in getting on the list of people who’ll be given invites to try our software for the next wave of testing, head on over to flock.com.

 

 

 

 

 

 

 

Changes to XUL’s getCellText() params

July 22nd, 2005 by daryl

I learned after about an hour of puzzlement tonight that the parameters for XUL’s nsITreeView::getCellText() have changed. Formerly, you passed a numeric id corresponding to the row in a tree as the first parameter and a string matching the id attribute of the desired column as the second. This provokes errors in recent versions of Gecko because the function now expects an nsITreeColumn as the second parameter.

A couple of nice people (db48x and gavin) on #developers at irc.mozilla.org pointed me to some docs that helped me unpuzzle myself. First, the idl file for nsITreeview, which clued me in to the fact that the second parameter is no longer a string. Second, a link to a mailing list posting about the change.

Basically, the change was implemented in order to do away with the necessity to give treecols an id. By generalizing the function a bit to expect an nsITreeColumn, Gecko can now figure out which column to use in a number of ways. For example:

tree.columns.getColumnFor(treeColElement);
tree.columns.getNamedColumn(treeColID);
tree.columns.getColumnAt(index);

In my recent case, I knew the column name, so I passed tree.columns.getNamedColumn(’identifier’) rather than just ‘identifier’ to the getCellText() function and it worked like a charm.

I post this pretty much for my own later reference.

Dork, dork, dork

July 10th, 2005 by daryl

It’s midnight on a Saturday night, and I’m at a dork party I wasn’t sure I’d go to. It’s at a big house, and I’m one of thirteen in one of the den/living rooms. We’re all scattered about on couches, folding chairs, and the floor. There’s enough cable running around on the floor to, to I don’t know what. To put a small-to-medium sized business’s IT staff to shame. There’s much talk of browsers and xcode and extensions and so on and so forth. I donned my best dork shirt for the event (it reads /(bb|[^b]{2})/, which means something to dorks) and have already gotten a good cackle from somebody over it. I occasionally have to stop my diligent work to go to a terminal and type “iwconfig eth1 essid ‘bret’; ifup eth1″ to get back on the network, because I keep getting dropped. The other den full of people is apparently more social than my room, which is full of relatively quiet people. I’m probably the quietest. It’s not nearly as painful as it could be. If only I could get this makefile to work blah blee bloopety blooblah.

Round Two is Hiring!

June 16th, 2005 by daryl

My company is looking to hire a couple of full-time senior developers. The following criteria must be met:

  • You must already live near or be willing to relocate to Silicon Valley.
  • You must have a minimum of five years of application development, with a focus on the following skills, in descending order of importance:
    • Mozilla application development
    • XUL
    • XPCOM
    • C++
    • javascript
    • CSS
  • Experience developing on two of the following three platforms: PC, Mac, Linux
  • Experience working on Open Source Software projects is a plus.
  • All the usual buzz words (self-starter, team-player, etc.) apply.

Send me a resume at abcdefg@hijklmnopqrstuvw.xyz (but replace abcdefg with my first name and hijklmnopqrstuvw.xyz with learnhouston.com) if you think you’re the person for the job. If you’re not the person for the job, but you might know who is, have that person send me a resume and include your contact information. There’s a small reward for whoever turns up a person we ultimately hire. Please don’t apply or send me resumes for those who don’t meet the criteria listed here.

Weird Button

April 21st, 2005 by daryl

Weird ButtonSo I’m working on adding a little button to a Firefox toolbar. If you click the button, it performs a default action. If you click a little arrow next to the button, it produces a menupopup from which you may choose another action. For an example, check out the Forward and Back buttons in Firefox. Clicking the main button moves you forward or backward; clicking the arrow produces a list of where you’ve been or where you can go. The thing is that by default, this sort of toolbar button is kind of big, and I want a tiny, unobtrusive little button. So I’ve been experimenting with different ways of implementing the button. In one case, it’s fairly small, but it’s got an extra arrow icon and has some extra horizontal space as a label placeholder, even though I don’t want a label.

My latest iteration breaks new ground in UI design. If you look carefully, you’ll see that there’s a little green bullet sort of thing (an icon squished down) and then a button wrapped around this small button in the shape of a sideways “U.” If you click the wrapping button, sure enough, you get the popup. If you click the inner button, you get the default behavior. I fully expect this sort of button to begin appearing in software packages very soon.

Auto-Updating Extensions

April 19th, 2005 by daryl

Eric Hamiter’s tutorial on how to enable extension updates is pretty handy. As he points out, in order to make it so that the “Update” button in the extensions manager actually does something for your extension, you simply provide a value for the updateURL paramater within your extension’s install.rdf and make sure there’s a valid RDF file being served up from that URL. This file contains information about the current version and from where the latest xpi file can be downloaded. When you highlight an extension in the extensions manager and click the update button, it checks the current version number against what’s listed in your remote RDF, and if yours is old, it pops up the update wizard that walks you through doing an update. Very nifty.

But let’s say I want to force an update (or at least prompt the user to let him or her know that a new version exists. Supposedly, there are some configuration options you can set to cause extensions (and Firefox itself) to automatically update (thanks to Nigel McFarlane’s Firefox Hacks for this):

extensions.update.autoUpdate /* set to true */
extensions.update.severity.threshold /* set to 0 (lowest severity) */
app.update.autoUpdateEnabled /* set to true */
app.update.enabled /* set to true */

That didn’t work for me, presumably because there’s some sort of timer. It seems to me as if I’ve heard at some point that different versions of Firefox do their updates at different times once a week. But say I have an important security release for my extension and want to prompt people to upgrade immediately, whether they’ve just installed it two days ago or whether they’ve had their browser open for three weeks without a restart (a tempting method for checking updates would be on browser load).

Luckily, Firefox’s mechanism has interfaces exposed that allow you to tap into some of the functionality. Unfortunately, there’s not enough exposed to be extremely useful, but there’s enough to get by. Specifically, there’s a function available through the nsIExtensionManager component that allows you to display the extensions manager wizard, as follows:

var nsIUpdateItem = Components.interfaces.nsIUpdateItem;
var gExtensionManager = gomponents.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);
var itemType=nsIUpdateItem.TYPE_EXTENSION;
//The guid here is the guid for the extension in question.
var items = gExtensionManager.getItemList(’{e9f3a1cb-98a9-4384-879b-c6d1e39ef5bf}’, itemType, { });
var updates = Components.classes["@mozilla.org/updates/update-service;1"]
.getService(Components.interfaces.nsIUpdateService);
updates.checkForUpdates(items, items.length, itemType, Components.interfaces.nsIUpdateService.SOURCE_EVENT_USER, window);

The trick, then, is to check the current and remote versions of the extension and to display the wizard only when there’s a discrepancy. Else you wind up showing a blank wizard. This is easily enough managed by querying the extensions RDF for the version number and then polling a remote script that serves up the current version of your extension (I use a different output source here than the updateURL RDF because all I really need is the number, and I want to conserve bandwidth. I could find no way to check the remote version using built-in interfaces without spawning the update wizard, though I may have overlooked or misunderstood some code. In pseudocode, the routine runs as follows:

  • Check a timer to see if we need to check for an update.
  • If so, query the extensions rdf to get the installed version number.
  • Check a remote file for the current version number of the extension.
  • If there’s a difference, use the code given above to pop up the upgrade wizard, which walks the user through the process.
  • Set the timer to now plus the update check interval.

Naturally, you kick this off in an onload handler so that any time your browser is started, it checks immediately for updates and then checks periodically for as long as the browser’s open.

Round Two Launches

April 13th, 2005 by daryl

In February, I started a new job that it’s been really hard describing to people.

>> “What do you do?” they’ll ask.
<< “I program stuff.”
>> “What do you program?”
<< “Web services.”
>> “What’s a Web service?”
<< “It’s something that allows another application to access your data.”
>> “But isn’t your company tied up in Firefox somehow?”
<< “Yes. I write Web services that we hope will help enhance the browsing experience.”
>> “How?”
<< “I can’t really say very much about it right now. I’m writing extensions to go along with the Web services.”
>> “How’s your company going to make money?”
<< “Nice weather we’re having today, huh?”

Well, we finally launched our Web site yesterday after a lot of work by a guy named Joel Apter, whom I hooked up with as a developer resource on the Spread Firefox project, and a designer named Bryan Bell who’s great at icon work in particular and who can be contracted for pretty darned reasonable rates. These guys did the bulk of the site so that I could work on my mysterious Web services and extensions with limited distractions. And I think they did a great job.

I spent some time the night we launched doing some benchmarking and tweaking to make sure our site scaled pretty well, and I’m happy to say that we weathered a slashdotting with aplomb, the site hardly affected by the heavy traffic.

For now, our site doesn’t say a whole lot about what we do. Out of the gate, our offering is sponsorship of several popular Firefox extensions. Basically, we’ve given money and other resources (server infrastructure) to these developers both to support their great work and to attach our name to their popular products. We have a lot more on the horizon, and with a little luck and a few more twelve-hour days on my part, we’ll have a beta release of what we hope will be a pretty exciting extension near the end of the month.

Firefox Extension Build Script Redux

April 12th, 2005 by daryl

A few weeks ago, I posted about a shell script I had written to help automate the building of an extension for Firefox. Building an extension’s not a hard process, but it can be a pain to do over and over because it involves zipping some files and putting them into a directory, then zipping that directory and another file into another archive. It’s just kind of a pain. This week, I’ve been hit with a need to generate different versions of my extension for different platforms in order to accommodate styling differences among the platforms. (Macs have nice rounded text inputs for some of their widgets, for example.) I could find no way to do a simple sniff to determine what CSS file to use for a given XUL document within an extension, so I figured I’d need to generate separate packages for each platform, complete with specialized style sheets. So I was looking at having to generate packages for each platform. Even with my nifty little build script, that was going to be kind of a pain and was going to necessitate keeping three copies of my code and making updates in three places. What a pain.

To get around this, I wrote a new script this morning that builds packages from a base directory and incorporates changes per platform. So I make core changes to one code base and make changes to platform-specific code only within the given platform’s directories. When I run the build script, for each platform specified in the script, it copies the base files into a temp directory, then copies platform-specific files in on top of them. Then it builds and exports the package to an export directory specified within the script. It should make this whole process substantially less painful. The script appears below.

#!/bin/sh
##############################################################
#                                                            #
# Multi-platform Firefox extension build script.             #
#                                                            #
#    Author:    Daryl L. L. Houston                          #
#               http://daryl.learnhouston.com                #
#   Version:    1.0                                          #
# Rev. Date:    Tue Apr 12 11:01:51 EDT 2005                 #
#                                                            #
#     Usage:    Current directory should contain directories #
#               "base" and platform-specific directories.    #
#               Base directory contains install.rdf and      #
#               files common to all platforms. For example:  #
#                                                            #
#                  + contents/                               #
#                    + r2/                                   #
#                      - contents.rdf                        #
#                      - overlay.xul                         #
#                      - overlay.js                          #
#                  + skin/                                   #
#                    + r2/                                   #
#                      - r2.css                              #
#                  + locale/                                 #
#                    + en_US/                                #
#                      + r2/                                 #
#                        - overlay.dtd                       #
#                  - install.rdf                             #
#                                                            #
#              Platform-specific directories contain files   #
#              in addition to or different from base files.  #
#              So if the Mac package needs a different       #
#              stylesheet, you create the skin hierarchy     #
#              under a directory named (eg) "mac" and put    #
#              the Mac stylesheet in there. It will be       #
#              dropped into the Mac package in place of the  #
#              base package's style sheet.                   #
#                                                            #
#              Packages are named (eg) "extname_mac.xpi"     #
#              where the "extension" variable below is       #
#              set to "extname" and are placed in the        #
#              directory specified in "export_path" below.   #
#                                                            #
##############################################################

#Set these variables.

#Final export directory.
export_path='/home/houston/code/extensions/xpi'

#Package name. This should match chrome:name from contents.rdf
extension='r2'

#Platform directories. Will be used to create final xpi names.
#Corresponding directories must also exist.
dirs=(mac windows linux)

#No need to edit below this line.

for idx in $(seq 0 $((${#dirs[@]} - 1)))
do
	#Need to make a temporary build work space
	mkdir temp

	echo ' '
	echo '===== '${dirs[$idx]} '===='

	#Remove old xpi files.
	oldxpi=$export_path'/'$extension'_'${dirs[$idx]}'.xpi'
	if [ -e $oldxpi ]
	then
		echo '+ Removing ' $oldxpi
		rm $oldxpi
	fi

	#Copy common files into build directory
	echo '+ Copying files into ' ${dirs[$idx]} ' temp build directory'
	cp -Rf base/* temp/

	#Now copy (and force) files from the current platform build directory
	#into temp directory. This adds new files and overwrites base files.
	cp -Rf ${dirs[$idx]}/* temp/

	#Make chrome directory
	if [ -d temp/chrome ]
	then
		rm -rf temp/chrome
	fi
	mkdir temp/chrome

	#Now go into temp directory and zip up the files copied there, name the zip
	#with a .jar extension, and move into the chrome directory.
	cd temp
	echo '+ Creating jar for '${dirs[$idx]}
	file=$extension.jar
	zip -r $file content skin locale
	mv $file chrome/

	#Create the xpi by zipping install.rdf and chrome
	#and giving the file a .xpi extension.
	echo '+ Creating package for '${dirs[$idx]}
	file=$extension'_'${dirs[$idx]}'.xpi'
	zip -r $file install.rdf chrome/

	#Move the newly generated extension to the export directory
	echo '+ Moving xpi file to output directory for '${dirs[$idx]}
	mv $file $export_path

	#Go up a directory and remove temp directory in anticipation
	#of iteration for next platform. Lather, rinse, repeat
	cd ..
	rm -rf temp

done