February 08, 2010
Theme Bugs Filed This Week
Note: I haven’t filed any Linux bugs yet and the Wiki page is out-of-date. Still working out some details there and should have that resolved this week.
This week I filed the first round of Bugs for implementing the new theme:
- #544815 – Allow for placing Tabs over the Navigation Bar with option for Tabs under the Navigation Bar
- #544816 – Attach combined Stop/Go/Refresh button to the Location Bar
- #544817 – Create Bookmarks Widget with placement dependent on Bookmarks Bar status
- #544818 – Progress “Line” indicator for background loading tabs
- #544819 – Create a basic Home Tab linking to the current Home Page
- #544823 – [Meta] Theme Visual Refresh
- #544820 – [Windows] Theme Visual Refresh
- #544821 – [OS X] Theme Visual Refresh
This is a pretty exciting step for me after having worked on the design for so many months.
Wiki Updates
I also spent some time getting all the mockups and thought processes on the Wiki current:
February 08, 2010 05:59 AM
February 07, 2010
Status
- Planned for eventual mozilla-central landing – want to get initial parts landed before betas
- Major AMO integration will probably be done as followups
- Have been bringing UI up to speed with changes in mockups
- Started looking at install/updates before realizing it’s not in the API yet
Loose ends
- Boriss was away for the latest meeting, need to catch up
- Waiting on project branch to be setup (bug 542910)
Next steps
- UX discussions! UX discussions! UX discussions!
- Implement helper widgets
- Install/uninstall/update/enable/disable
- Search
- Help with API development
Target for next week
- Catch up with Boriss
- Implement various widgets – download progress, ratings, etc
- Start implementing search (only local, until the API supports AMO searching)
Status
- Refactored UI for better toolkit/browser separation
- Renamed “open tab” concept to the more generic “open page”
- Must remember that adding a constant doesn’t mean the interface needs a change of UUID
- Waiting on next review, then SR
Loose ends
Next steps
- Land
- Tackle followup bugs
Target for next week
- Landed on mozilla-central
Reflections
- I need to get better at estimating time required for larger projects
- I’m having far too much fun for this to be considered “work”
Related posts:
- Status update
- Status update
- Status update
February 07, 2010 10:27 PM
February 06, 2010
Started a Firefox project page to track Jetpack and its integration into Firefox. Atul typed up a reboot glossary. Anyone who talks to other human beings about Jetpack going forward should read it. Preview:
Jetpack: Synonym for Cuddlefish. Currently, we prefer using the term “Cuddlefish” to disambiguate it from the Jetpack Prototype, which is a completely different animal.
Began a couple of API proposals for the reboot, context menus and simple persistent storage. Others on the Jetpack team have started proposals also. Met today to discuss and shape what we’ve got so far. Plan: Iterate on them together in the coming weeks.
Talked with Mano and Marco about async bookmark folders, new WIP patch. Mano is working on a new view-related bug that now blocks. Once his is done, should be fairly straightforward to finish.
February 06, 2010 01:41 AM
I’m going to give weekly blog status updates a shot. I suspect planet already gets inundated with them near the end of the week, so maybe I’ll try adjusting my schedule by a few days. Or maybe I’ll end up just posting them on wikimo instead. Either way I’ll try to keep them interesting!
I didn’t think I was going to end up doing this, so I didn’t take detailed notes of everything I’ve done this week. I’m going to try to get better at that.
Accomplished this week:
- tried to keep the review queue cleanup rolling from last week, but I think I netted out even (or slightly negative). Current state: 33 pending requests.
- reviewed dolske’s plugin crashing UI patches (bug 539848, bug 538910)
- helped test the 1.9.3 alpha 1 branding changes (bug 543564)
- wrote some additional tests for bug 512784 (consolidated smart getters for common services). ready to land once it gets rs=Mossop
- spent some time reviewing patch for bug 480350 (tab matches in awesomebar)
- wasted a bit of time arguing with RSnake on his blog
Up next (roughly in priority order):
- shorlander’s going to be filing bugs for proposed theme/UX changes, will need to triage/prioritize those with dao
- need to make progress on browser.js cleanup/simplification – I want to get a list of actionable items by mid-next-week and get patching
- I have some mobile blog post ideas and notes that I really need to turn into posts
- try not to give up too much ground on review queue clearing
- want speak to Ryan about some changes required for bug 511017 (allow default search plugins to be updated, allowing them to get locale-specific search URLs to avoid redirects through google.com)
- would like to resolve bug 479334 (improved en-US spellcheck dictionary, including better merge scripts to ease taking changes from upstream hunspell and chromium). just needs a final test run and a couple of tweaks before landing, I think.
Ideally I think my “upcoming” tasks would be as granular and clearly defined as my “completed” tasks, I guess, but they’ll probably be easier to split out into specific tasks once some of the planning/exploratory work is done.
February 06, 2010 12:15 AM
February 05, 2010
What the Firefox UX team is up to this week
February 05, 2010 06:40 PM
Done:
Lost most of the week to sickness but trawled through some reviews that were blocking people's work.
Next:
- Downloads and updates in the add-ons API
February 05, 2010 10:12 AM
One common thread running through the many different and interesting WebGL projects out there is that they all need to do vector and matrix math, do it quickly, and do it in JavaScript. To date, developers have either rolled their own, or they've used Sylvester, a fairly featureful vector and matrix JavaScript library.
One of the problems with Sylvester is that while it's fully featured (arbitrary NxN matrices and vectors can be created and manipulated), it suffers in performance because of it. Since this is such a crucial part of a successful WebGL program, I've put together a small package that I'm calling mjs.
mjs is designed around speed and simplicity. For example, it doesn't attempt to stuff vectors and matrices into JavaScript objects. Because the language offers no operator overloading, there's very little benefit in treating these types as discrete objects, and lots of performance and memory usage downsides. Instead, it provides a set of functions for performing operations on vectors and matrices, which can be any array-like object. For any function that returns a vector or matrix, an existing array can be passed in to take the result, or the function can create a new one. Array reuse ends up being important because of the potential for expensive garbage collection churn eating away at performance.
Here's a sample of the API:
var r = M4x4.rotate(Math.PI/2, V3.$(0, 1, 0), M4x4.I);
Note that V3.$ and M4x4.$ are shorthand for creating a new V3 or M4x4 (I wanted to use V3() and M4x4(), but that didn't work out too well since functions have a length property). However, because all they return are just new array-like objects, you could also write:
var r = M4x4.rotate(Math.PI/2, [0, 1, 0], M4x4.I);
If the WebGL types are available, those will be used for newly created vectors/matrices. They are a significant performance boost especially for repeated operations; but for specifying one-off vectors such as the above, literal array syntax is fine.
The rotate function internally makes a rotation matrix, and then multiplies it by the given matrix. So the above could also be written as:
var rotation = M4x4.makeRotate(Math.PI/2, [0, 1, 0]);
var r = M4x4.mul(M4x4.I, rotation);
(The last line being redundant given that we're multiplying by the identity matrix.)
All methods that return a vector or matrix take an optional final argument, that of an existing object to reuse. For example:
var m0 = M4x4.$();
r = M4x4.mul(someMatrixA, someMatrixB, m0);
// r == m0, so the assignment isn't necessary, but it's handy for chaining
// .... do something with r ...
r = M4x4.mul(someMatrixB, someMatrixC, m0);
// r == m0 still
// ... do something else with new results ...
Without allocating any additional temporary objects.
As mentioned before, one of the goals of mjs is performance. Matrix multiplication is one of the most common tasks, so here are some numbers comparing mjs, Sylvester, and native C code. This was run on a Core i7 desktop using a local build of Spidermonkey, which included one patch that's about to go into the tree that fixes the no-reuse tracing case. (Without it, the no-reuse tracing case is much larger because it's never actually jitted.) The test is simple: it multiplies two matrices together in a loop 1,000,000 times.
| Test |
Time |
| mjs, JIT, matrix reuse |
140ms |
| mjs, JIT, no reuse |
533ms |
| Sylvester, JIT, no reuse |
5,280ms |
| mjs, no JIT, matrix reuse |
25,833ms |
| mjs, no JIT, no reuse |
26,681ms |
| Sylvester, no JIT, no reuse |
41,996ms |
| Native C++, SSE2, matrix reuse |
71ms |
| Native C++, SSE2, no reuse |
142ms |
(I also have numbers for MSVC without the SSE2 compile flag, but the numbers vary greatly depending on whether the values eventually go to infinity or not; if the values end up trending towards 0, the non-SSE2 code tends to win at around 52ms vs. 71ms; if the values trend to infinity, the non-SSE2 code takes around 11,000ms!)
Those numbers are pretty encouraging -- having native code be only 2x as slow for something like this is pretty nice to see. Granted, this is only a very isolated test, and I'm sure there are some tricks to optimizing the native code case (it's currently just a fully unrolled set of multiplies and adds). The "no JIT" case is less nice, but I'm sure that our Jaegermonkey folks will be all over this testcase (right, guys?). In any case, ideally most WebGL rendering loops will be fully traced in Firefox, so it would be less of an issue.
mjs is still very much a work in progress; it's missing a test suite and a whole bunch of features. You can find it hosted at Google Code, at webgl-mjs. (Side note: I couldn't just call the project mjs because a project called mjs was abandoned on Sourceforget 5 years ago, and Google Code complained.) There's also some documentation, viewable online here.
Bugs and contributions welcome!
February 05, 2010 09:04 AM
February 04, 2010
Bugzilla is the devil we know. It’s more complicated than we’d like it to be (albeit mostly by our own hand), it’s pretty intimidating to new users (though I recognize the efforts to improve that), and adding the features we want can be a slog (I’m looking at you, multi-state flags).
It’s also essential to the way we manage our project at scale, though, and enough of our project’s history and daily activity lives there that understanding it is not really optional. Certain edge cases aside, you can’t really be effective in the Mozilla project without at least a passing ability to wade through Bugzilla.
I put together this video to help people who don’t really live in Bugzilla learn how to at least manage themselves. If you’re inclined to thank me for it, thank Deb and Dan instead – they’re the ones that actually made me sit down and finish the job.
Until wordpress stops eating my video tags, you can get the open-web, flash-free, unencumbered-codec goodness here.
If you’re using a browser that doesn’t understand ogg, I’ve put a copy on Vimeo as well:
<object height="375" width="600"><param name="allowfullscreen" value="true"><param name="allowscriptaccess" value="always"><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=9205730&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=00ADEF&fullscreen=1"><embed allowfullscreen="true" allowscriptaccess="always" height="375" src="http://vimeo.com/moogaloop.swf?clip_id=9205730&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=00ADEF&fullscreen=1" type="application/x-shockwave-flash" width="600"></embed></object>
February 04, 2010 03:54 PM
February 03, 2010
Firefox’s tab strip is necessary, I think, but its usefulness degrades when you open lots of tabs. In those cases I usually tap the tabs menu, which sits quietly at the end of the strip. The menu works well with a moderate number of tabs, but I often open enough to actually force it to scroll. It’s annoying to have to frequently mouse to its bottom.
So I wrote an extension that sorts the tabs menu in most recently used (MRU) order. Like, if you select tab A, then B, and then C, the tabs menu will show C, B, and A, in that order. Tabs that you often use rise to the top, those that you don’t sink to the bottom. (Like how Ctrl- or Cmd-Tab works for applications in your OS. Dão implemented something similar for tabs in Firefox.)

After using it for a week, I’ve found that the new menu is nice when I forget what I’m doing and need a reminder: The top tabs tell me. It’s also nice when switching to a different task: I know its tabs aren’t at top. But I’m still occasionally surprised when I open the menu and see an ordering different from the tab strip’s. That happens mostly when all tabs are visible in the strip. And the use case I hypothesized would be best served by an MRU menu—selecting one tab when many aren’t visible—sometimes isn’t. The tabs related to a single task usually end up clumped together, so using the strip or key shortcuts is better.
I tried to be smart about performance. You don’t pay for MRU when you open or select tabs. You pay when you open the menu, and then it’s O(n log n), n = number of open tabs. (You were already paying O(n) for the standard, non-MRU menu.) It’s easy to imagine other approaches with different time-space trade-offs.
I’ve been working on Jetpack. Different people have different ideas of what Jetpack is supposed to be, but one of its early goals was to make extension development simpler than it is now. It took me an evening and 250 lines to write this. The menupopup is an XBL binding, so all I had to do was write a replacement and hook it up with a single CSS rule. A reminder that traditional extensions can be both powerful and simple to make, if only for a certain group of people.
February 03, 2010 07:20 PM
A proposal to make downloading web page resources faster in all browsers.
February 03, 2010 05:46 AM
It's been a while since I posted a progress update (or really any blog post, ahem), but porting Firefox/Fennec to Android is progressing at a good clip. After working out a few kinks (and setting the all-important "you're allowed to touch the network" permission), I just got our first page load:

Mouse events sort of work, toplevel windows sort of work, keyboard doesn't work yet but shouldn't be hard to hook up. This is running in an emulator at the moment for ease of debugging, but it's working just fine on physical hardware as well.
You'll note that this is the full Firefox interface, and not the Fennec/Firefox Mobile UI; we're testing with the full interface because it's significantly more complex than the mobile UI and stresses Gecko much more. So, if the full UI works, then Fennec should work fine as well. Given the interest in Android on netbook and tablet devices, an updated version of the full Firefox UI might find a home on some of these. Android has been pretty great to work with so far; it's a bit unusual platform for us due to its Java core, but with the NDK we're able to bridge things together without many problems.
We're still a ways to go before any kind of usable alpha release, but we're certainly one step closer. We'll also be able to accelerate our progress now that we have some of the basic scaffolding in place. I know I'm looking forward to running Fennec on my Droid, and there are tons of Android devices coming out that should be great platforms for Fennec.
February 03, 2010 12:29 AM
February 01, 2010
Progress:
- Patch almost ready for review – Bug 530872 [Toolkit] – app.update.url params / update.xml cleanup and addition of a custom string property for apps [All]. The changes are backward and forward compatible which should minimize releng’s pain when implementing this on AUS. This is the app update work to support Bug 538331 [Firefox] – On update perform action based upon the update meta-data [All] as well as general cleanup of overridden attributes in the update xml.
- Landed Bug 536547 [Toolkit] – 3.5.6 is downloading the same version for an update [Windows]. This prevents resuming the download for an update with the same app version with the same build id.
- Landed Bug 540356 [Toolkit] – Enforce a sane minimum interval for app.update.timer [All]. There have been several bugs filed over the years due to using extremely low values for this timer along with the app update timer interval during release testing and this is the first of a couple of fixes to prevent this from happening in the future.
- Landed Bug 543312 [Toolkit] – Remove the dependency on nsTryToClose.js from app update’s ui [All].
- Landed Bug 538533 [Toolkit] – If a complete update fails the update prompt should state the error and offer a link to download the update [All]. This has caused several bug reports over the years during release testing.
- Met with Ken Kovash to define new app update metrics for Firefox Lorentz.
- Rewrote Software Update:Manually Installing a MAR file.
Future targets:
- Land Bug 530872 [Toolkit] – app.update.url params / update.xml cleanup and addition of a custom string property for apps [All] and ddahl should have Bug 538331 [Firefox] – On update perform action based upon the update meta-data [All] landed as well. The remainder of the work to enable this will be done on AUS and I’ll get an ETA for this from nthomas during the week.
- Write mochitests for Bug 538533 [Toolkit] – If a complete update fails the update prompt should state the error and offer a link to download the update [All]
- Start coding for the new app update metrics for Firefox Lorentz
February 01, 2010 12:54 AM
January 30, 2010
No progress at all. Another week closer to being dead.
January 30, 2010 04:42 AM
No big changes from last week, so I’m not going to knock you over the head with the big table, but here are some notes on the progress of some of the projects and areas of research:
- Joel has patch in Ted’s review queue for the static build changes. He’s also working on getting Windows builds un-broken, with help from Ben Smedberg and Brad Lassey.
- Rob Campbell enabled PGO on the Mac, and found no detectable difference in performance. I built PGO on Linux, and found the same. It could be that there’s no improvement to be had. It could be that our profile-generation approach doesn’t target the codepaths that our performance tests measure. Not sure yet!
- I talked with Rob Stong about the fast-startup component, and he brought up a bunch of problems with enabling it in multi-user environments. I’m pretty convinced that there’s no way we can ship with it enabled. And I’m still convinced that it should be exposed as an option to users. I did get it actually working on Windows 7, and as expected, first startup post boot was 60% faster. The scary part is that it took 40% of startup to do the rest…
- I researched code locality options for Linux, and haven’t yet found a way to specify a function order like you’re able to on Darwin. Joel’s been spending some time looking into this on Mac, but gprof is broken on Snow Leopard – instrumented builds just hang. Boo.
- Joel talked with some Apple developers on the Darwin list and got some more information about compressing with HFS+. They thought it was pretty hacky, recommended improving code locality instead (See previous comment about gprof being broken. *sigh*). Compressing locally does break our code-signed builds, so might not be feasible anyways. Next is to look into compressing on the release side.

January 30, 2010 01:24 AM
January 29, 2010
And so it came to pass, after months of watching and opining and speculating, that in mid-December we got the letter from Microsoft’s attorneys. The European Commission had adopted a decision settling its current tying case with Microsoft. Among other things, this decision introduced a mandatory browser choice screen for Microsoft Windows users. Would we like to participate?
(Yes, we would.)
Our deliverables had to be submitted by January 15. Others in our (amazing, amazing) community did all the real work, but since I was asked to pick up the coordination and delivery of those pieces, I wanted to talk about them a little.
In broad strokes, Microsoft asked us for 3 things:
- An icon for the choice screen itself
- Localized content for each supported locale
- Administrative pieces that aren’t really interesting here.
First things first, then.
Icon

Firefox Logo Submission
Among the many things for which I take no credit, I take no credit for this. Patrick Finch and Jennifer Boriss worked the logo question up and down. There was market research in more than a dozen countries, there were mechanical turks, and a great deal of analysis from all quarters. Taking the research as a whole, this design led the others by a healthy margin. It beat other background colours*, it beat other styles, and it beat versions that omitted the word “mozilla” to focus harder on the product brand. Design decisions tend to be very personal, but Patrick and Boriss ran this thing like champs, and by the numbers.
[*Curiously, in Italy a version with an orange background did significantly better than the green. We asked if we could provide an icon per locale. No such luck.]
Localized Content
We were also asked to supply a 140-character* product description in each of 23 languages, specifically:
Bulgarian, Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, German, Greek, Hungarian, Italian, Latvian, Lithuanian, Norwegian (Bokmal), Polish, Portuguese, Romanian, Slovak, Slovenian, Spanish, Swedish
In what is fast becoming a pattern, I can take no credit for making this happen, either. Patrick (always Patrick) worked with Staś, Seth, and our amazing localizers, and collectively they got it done.
Got it overdone, really. Our team noted that while the EU has 23 “working” languages (and two more that are official EEA languages), we were quite capable of providing several more as well. They also pointed out that there were some surprises in the list supplied – it was similar, but not identical, to the EU working languages list. Maltese and Gaelic had been dropped, Croatian and Norwegian had been added. We offered to supply the missing ones, along with some others, but we heard back that, no, the choice screen will be limited to those 23. You can see our complete submission, here.
[*No, I do not believe that this limit was introduced in order to make them more tweetable. Tip o' the hat to old Friedhelm though.]
Next Steps
Content! We have a little more than a month before the Browser Choice page goes live, and that means the localization and web dev teams (and Patrick…) are pushing to get everything ready for our new visitors. While we get that together, Microsoft will be running QA on the page itself in all 23 languages. We don’t get to QA the pages ourselves, but they have been responsive throughout this process; I trust that any issues they discover with our content will be brought to our attention quickly.
We did confirm that users in locales outside of the 23 requested will be shown the en-GB version of the Browser Choice page, which may give us the ability to wire up the Tell Me More and Download links with additional locale smarts if we want to provide extra information for those users.
So there you have it. We got the first pass done on a tight schedule, and we’ll get the rest in on time, too. At the end of the day, though, I think Mitchell put it best:
While the ballot mechanism represented by the choice screen has received the most attention, Mozilla is most pleased with the core principles Microsoft will be adopting that protect the choices a person has already made. These principles won’t be obvious to a person using Windows. That’s the point — once a person has chosen an alternative browser, IE should not keep reappearing. These principles are expressed in several components of the commitments and together should result in a greater respect for individual human decisions.
January 29, 2010 02:44 PM
Done:
- Intermittent test failure tracking
- Post mortems
- Wrote a patch to fix showing incompatible add-ons to users who have upgraded
- Started setting up a project branch for the add-ons manager work
Next:
Need to change my working practices and start ignoring new emails unless they are critical so I can actually get more work done.
January 29, 2010 01:33 PM
In addition to the UI and appearance changes we have been exploring for Firefox, we have also been exploring how to better improve the user experience through animation.
One area that animation would be very beneficial is with tab interactions. Specifically moving/arranging tabs on the tab strip, closing/opening tabs and tearing off tabs into new windows. Presently the feedback here isn’t as good or as elegant as it could be.
New Tab Animation
Some of the goals for animation are to make browsing feel faster, adding visual affordances that makes tasks more understandable and to make the browser more visually appealing. There is much more detail on the Wiki articles linked above. My goal was to quickly demo how this would actually look and feel because still images and wireframes can only convey so much.
Some of the goals for animation are to make browsing feel faster, adding visual affordances that makes tasks more understandable and to make the browser more visually appealing. There is much more detail on the Wiki articles linked above. My goal was to quickly demo how this would actually look and feel because still images and wireframes can only convey so much.
Click the image below for the animation that shows how a new tab animation could look. It’s pretty short and fast.
It is hard to tell from the video how this would work frame by frame. The general idea is that after you click the new tab button that button itself grows into the new tab.
Tab Tear Off
This demo shows both tab rearrangement and tab tear-off.
January 29, 2010 11:41 AM
January 26, 2010
Yesterday i've pushed the last parts of my small improvements to browser chrome tests harness.
Some time ago Dao pushed bug 521282, ensuring that we focus the browser window before any test run. I've extended that concept with bug 528469. Now, before each test (and also before the first test) we check that we have a consistent number of browser windows, and ensure that the window where the test will run is focused.
This means that if your browser chrome test will leave windows open, we will detect them and notify that as an error of your test. We will then close the unexpected windows, avoiding failures in next tests.
With bug 485269 and bug 529860 i've instead brought to browser chrome tests a couple features we already had in xpcshell tests.
You can now have an header file, called head.js, in the tests folder. This file will be injected into your test's scope, so that you can collect utils and helpers into it, for all the tests in that folder.
You can also register clean up functions, that are guaranteed to be run after your test finishes, regardless the fact it succeeds, fails or timeouts. You just have to call registerCleanupFunction(myCleanupFunc), and you can register as many functions as you will. You can also call it in the head.js file, so it will be run for any test in that folder.
This way you can always guarantee clean up of the environment, that's pretty important for browser chrome tests, since they don't run in new context, so if you don't clean up browser before finishing your test, it is most likely that next tests could fail.
Finally i've provided a way to enlarge timeout for those random failing tests that are timing out due to taking too much time. Notice this is not intended as a solution, you should really investigate why your test is taking so much time, and evaluate if that's due to a bad test design, or to a real performance issue. This is instead intended to try reducing orangeness on mozilla-central.
To use the new method you just have to call requestLongerTimeout(integerFactor), where integerFactor is an integer used to multiply the default timeout value (30 seconds). So if you pass in a factor of 2, your test will have a 60 seconds timeout (30s*2).
I've also updated MDC page about Browser Chrome Tests, for your reference.
I hope these changes will allow people to write better tests and reduce orangeness as well.
Happy browser chrome tests to everyone!
January 26, 2010 12:58 PM
January 25, 2010
Status
- “$” or “!” as the restrict character? Got i18n input: smontagu suggested “%” as a more common character on non-US keyboards
- Discovered a (small) issue with having such a normalized DB schema
- Unit tests (why do these take SO much time?!)
- In process of final code review
Loose ends
Next steps
- Address reviewer’s comments
- Get SR review for API changes
Target for next week
- Final reviews and (finally) landing
Status
- Meetings, plannings, and discussions, oh my!
Loose ends
Next steps
- Bring UI in line with newer mockups
- Handle installing and updating
Target for next week
- Extract mockups from Boriss’s brain
- Act on said mockups
- Handle updates
Miscellaneous
Reflections
- 5am start to a 13 hour day makes the next day really difficult.
Related posts:
- Status update
- Status update
- Status update
January 25, 2010 12:08 AM
January 24, 2010
Progress
- Began working towards this quarter’s main-thread IO reduction goal by creating an asynchronous version of nsIContentPrefService::getPref. We currently use getPref every onLocationChange to check if there’s a page zoom setting saved for the site being loaded. This check happens on every page load and tab switch and sometimes multiple times for each (f.e. loading a link in new, focused tab fires onLocationChange when switching to the new tab, loading about:blank in that tab and then loading the final URL – arguably we can be a bit more intelligent about filtering these) and if it’s slow to return, the UI will be blocked while we wait for it. The downside to doing this is that in the cases where we’d previously be stuck waiting, unzoomed content will continue loading and then be set to the desired zoom level once we’ve gotten a result – sometimes leading to a distracting jump in size if the content’s already visible, but I think that’s definitely a hit worth taking. The API changes are covered in bug 539907, frontend in bug 541779.
- While working on the above, I ran across a few tests that check that entering and exiting print preview doesn’t interfere with the zoom level. Print preview works in a way that makes it rather difficult and fragile to do what I want, so I’ve decided to take advantage of our new ability to clone documents and make print preview open in a separate window. I’ll be posting a followup later this week with some builds to try out. Stay tuned!
January 24, 2010 02:53 AM
January 23, 2010
Async bookmark folders got its second review. Currently trying to convince Mano that my design is good, which it totally is.
Bookmarks and history in content was supposed to be easy, but there are wrinkles. A new WIP patch but not much forward movement. Think I’ll have to take a different approach.
Epic meetings with Atul and the Jetpack team. Is there a meeting instruction booklet? There are two distinct APIs we’re developing. Still working out the terminology, which is stunningly important, but one is Cuddlefish, and the other is Jetpack.
Cuddlefish is the Mozilla standard library. It wraps the Mozilla platform—or at least the parts that extensions commonly use—in XPCOMless APIs packaged as CommonJS modules. Cuddlefish is chrome-privileged and ignores security. You can write traditional extensions using Cuddlefish or use Cuddlefish in your traditional extensions. Cuddlefish will make it easy to write no-restart-needed extensions, which is an upcoming mechanism altogether independent of Cuddlefish and Jetpack. Anyone can write CommonJS modules, so if the standard library doesn’t expose a certain part of the platform, you can write a new module. You can keep that module to yourself, share it with others, or submit it to the standard library so everyone can benefit. There are other interesting aspects to Cuddlefish, but it’s not my intention to enumerate them all.
Jetpack securely exposes Cuddlefish and provides UI hooks. I’m not sure whether the Cuddlefish API is a subset of Jetpack’s. Maybe Jetpack’s API is fairly impotent, I don’t know. Atul has mentioned keeping Jetpack’s surface small, so that might be the case. One idea we discussed this week is making it dead simple for jetpacks to hook into the UI: They provide some UI bits, like an icon and title, and a callback. No statusbar, no toolbar, no sidebar, no UI power. In return they get ease of implementation and a spiffy presentation that fits in well with the rest of the browser and the user’s other jetpacks. If they need more power, they can write a UI-oriented Cuddlefish module, expose it securely, and use it. (More likely, they can find such a module that someone else has written.)
It’s possible to simultaneously dislike Jetpack and find Cuddlefish exciting. Jetpack might fail while Cuddlefish succeeds. I think that Cuddlefish, if it does succeed independently of Jetpack, will be really, really large, and that’s quite a daunting task. Atul, however, has described it as a sleek and svelte kernel.
Is it our immediate priority to build Cuddlefish broadly or only enough for Jetpack’s needs? I think we should start at Jetpack and build downward.
To that end, wrote a patch that adds byte streams to Cuddlefish, so it’s now possible to read and write files. Once it lands we can implement simple JSON-backed storage in Jetpack, if indeed we want to bring over that API from the prototype.
January 23, 2010 11:09 AM
January 22, 2010
A good week: Firefox 3.6 was released, and I’ve gotten a lot of feedback from friends and colleagues that startup has improved, and that it’s snappier than ever. Yesterday I blogged a roundup of the performance improvements in Firefox 3.6.
Top Startup Bugs
| Estimated win |
Bug # |
Summary |
Owner |
Status |
Notes |
| >10% |
512584 |
Super fast paths for Components.classes and Components.interfaces |
Taras Glek |
in progress |
Taras is traveling, says he’ll close it out when he returns. |
| >10% |
525013 |
Investigate a more static build configuration of Firefox |
Joel Reymont |
in progress |
More great data from Zack and Joel. See PDF charts of the different build configurations tested on different hard-drive speeds for Mac and for Linux. |
| up to 25% |
514083 |
Per-file HFS+ compression on Mac OSX 10.6 |
Joel Reymont |
in progress |
Conclusion is that we need to make this happen via the installer, as well as the updater, since modifying files results in decompression. Need to find an owner for this still. |
| TBD |
520309 |
Startup cache: replacement for fastload cache |
Ben Hsieh |
in progress |
Considering moving back to the simpler caching approach. |
| TBD |
503483 |
Turn on –enable-faststart for Firefox by default |
Dietrich |
needs testing |
Started talking with Rob Strong about making the changes to the NSIS installer to make this happen. |
| TBD |
513149 |
Speed up CSS parsing by using a machine generated lexer |
Zack Weinberg |
Zack’s blocked on other work |
No update.Taras says about 6% of startup spent parsing CSS. |
Other activity this week:
Projects in a holding pattern:
- More investigation into Hunspell changes in bug 468799, possibly incorporating some changes Chrome made.
- Ryan Flint has a WIP patch to minify JS on bug 524858 that significantly reduces the size of shipped JavaScript files.
- JARification: David abandoned moving JS modules into a JAR file, since those files are fastloaded. However, since we want things like post-extension-install restarts to be fast, and those cause fastload cache invalidation, we might want to do things like this anyways. I filed a bug for the same treatment for components. These are lower priority, since they’re not the normal startup case. Follow along with all JAR-ification via the tracker bug.
- Startup Timeline: No updates, still not landed. Add [ft] in the whiteboard of your bug w/ the function names you want timed and David will generate it and update the bug.
- Static Analysis: No progress on bug 506128. David needs to file a bug with the final log of named-yet-uncalled functions.
- Dirty Profile Testing: No progress. We have a list of test scenarios, still need to file bugs for each, generate Talos config patches and profile data, and then move it into Rel-Eng territory. Also, need to get a separate Tinderbox tree, since it’s going to cause a bazillion new columns.
- Joel Reymont noted in bug 513076 that there are serious drawbacks to getting our libraries in the dyld shared cache on Mac, so has deprioritized that work.
As usual, more details and links are available on the project wiki, and we’re available to answer questions in #startup on irc.mozilla.org.

January 22, 2010 09:56 PM
Done:
- Identified and mostly fixed a regression in 3.6 involving executable files in XPI packages.
- Worked with AMO to try to improve the capabilities of release notes for add-ons.
- Figured out how to make the backend parts of lightweight themes and xpi themes operate independently.
Next:
- Implement the new add-on download and install process
- Work out how to proceed on some large toolkit issues
January 22, 2010 12:22 PM

You may have heard: Firefox 3.6 is out. Its pretty awesome. I helped make it. That makes it extra special.
If you use Firefox, you should upgrade – its easy! And if you don’t use Firefox, give it a try! Here’s why:
Download it from firefox.com!
Related posts:
- Firefox 3.6 knows when your plugins are out of date
January 22, 2010 03:01 AM
January 21, 2010
Firefox 3.6 was released today! For me, the most important changes in this release are the performance and stability improvements. On Mac especially, there are some big improvements in startup time, yielding up to 30% faster startup generally. And on both Mac and Windows, we fixed some pathologically bad startup scenarios.
The list of bugs fixed that specifically affect startup time is here, however a few should be called out individually:
- Ted Mielczarek and Drew Willcoxon combined all .xpt files into a single one, reducing the number of files read from the disk at startup.
- Rob Strong removed the need for services to load at startup for timer registration, reducing the number of files read from disk at startup, as well as reducing the amount of JavaScript executed. There are still services that need to be ported to this new scheme, so expect more improvements here.
- Vlad Vukicevic found that on Mac it could take up to a whole second to initialize Growl, if present. His fix initializes Growl on demand.
- Joel Reymont found that up to 10% of startup time on Mac was in the initialization of fonts. John Daggett and Jonathan Kew did some great work to reduce the problem in Firefox 3.6. They subsequently modified font loading on Mac to occur on-demand, so the next release will be even faster.
- Joel also found that up to 12% of startup on Mac was spent in some APIs that were only needed for debugging. The problem was quickly fixed by Masayuki Nakano.
- Taras Glek and Alfred Kayser spent a bunch of time improving the performance of how JARs are loaded and read from. The infrastructure improvements made are paying off as we move more groups of small files into these archives, reducing the number of individual file operations that occur at startup time.
- On Windows, it was found that a large portion of startup time was spent in the security libraries, building up entropy by trawling through IE’s cache folder and the Windows temp directory. Some Windows users reported upwards of 25k files in their temp directories, so you can imagine the delays that this behavior was causing for some users. The behavior is now fixed.
The full list of bugs fixed in Firefox 3.6 with the “perf” keyword is here. These range from improvements to web page loading times, general UI responsiveness, and improvements to specific UI actions such as searching History and Bookmarks:
And all of this is just a taste of what’s to come: Over 60% of the bugs fixed as part of our focus on startup performance have landed on trunk, but didn’t make it in time for the 3.6 release. You can follow along on the wiki page for the startup project, and here on my blog, where I post status updates every Friday.

January 21, 2010 06:18 PM
January 20, 2010
Last week, on Friday, i've pushed the last pieces of the new Places Expiration component. This was one of the Firefox Projects intended for 1.9.3 branch, you can find more background on the start of this project in its wiki page.
Some background
Originally expiration was managed by History component itself on three major steps: after each visit, during idle, at shutdown. This had various drawbacks. First of all it was making navigation experience laggish, so we moved the after each visit step to be after each sync between memory and disk tables. We also reduced idle expiration and shutdown expiration.
The result was better, but we had other issues: we were not expiring enough pages related to the number of visits, and the sync component was now bloated with non-related functionality (And slower). We were also still doing a bunch of stuff at shutdown.
In bug 516940 i cleaned up the shutdown stuff, while increasing separation between History and Expiration, at that point was easier to split it out of History in a separate component.
So, what's new?
The new component is a JS component, it runs expiration in steps, every 3 minutes, with a simple adaptive algorithm, so that if the last step did not expire enough, the next one will be run later, while if it finds more items than the expired ones, the next step will expire more! This should ensure we don't lag behind with expiration.
It also uses async Storage API, this ensures that we run I/O in a separate thread, so we won't hurt your navigation.
Expiration on idle will run just a single larger step, then it'll stop till you exit idle, this way it won't kill your standby or batteries. Expiration on shutdown runs a larger step, but not too large, in most cases the adapative expiration steps should still ensure we don't expire on shutdown.
What has changed for you?
The new component is able to detect your hardware specs, especially memory size, and adapt expiration to it, this means you don't need anymore to tweak number of days of history, or whatever. For this reason we have removed the number of days field from the preferences panel, you don't need anymore to tell us how much days of history your computer can handle.
What about privacy? Well, we discussed about that obviously and we went to a conclusion that the days field was not giving back any real privacy gain. Sure i could have set it to 6 days, but that would have not protected me since:
- The days pref was an "at least" pref, so for most users it was really a fake-change
- Being expiration async per definition, you can't be sure when pages are phisically expired
- even if you reduce history to 6 days, nobody can ensure you don't have bad entries in these days
Since we have better privacy tools (And we can even build new ones, so feel free to suggest changes and file enh bugs about that) like Clear Recent History, Private Browsing and Forget about this page/site, the choice was pretty clear, we want real privacy, not fake-privacy.
Also hidden expiration preferences have gone, so browser.history_expire_days, browser.history_expire_days_min, browser.history_expire_sites are now replaced by a single places.history.enabled preference. No more need to read preferences manuals just to make the browser feel faster.
What can you tweak? Ideally you don't need to tweak anything, and i suggest you don't touch any pref. Btw, for the sake of information we have two new hidden preferences: places.history.expiration.interval_seconds is number of seconds between each expiration step, while places.history.expiration.max_pages is maximum number of pages that we will retain before expiring. We make our best to have satisfying default values for anyone, current values are built to be pessimistic, we will evaluate how we behave with them, and eventually increase them in future, if we feel that's needed.
What you got finally
Faster, easier and more secure expiration with smoother navigation. All of this at the price of fake-privacy. Win win.
January 20, 2010 03:25 PM
January 16, 2010
Offmainthreading the opening of bookmark folders awaits a second review. After that, superreview. After that, history and bookmark searches off the main thread, the patch for which is mostly written but may change depending on the upcoming reviews.
Bookmarks and history in content swerved off road and struck a mailbox. Our current architecture was not designed to show single bookmark and history items in isolation, outside of their hierarchy. Only recently do I realize this. We can design a new architecture, modify the current one, or build on top of it. That last option is simplest if simplest means least invasive and is what I’ve been working on. It’s a good thing that, although this new webby UI is not scheduled to arrive in full until Firefox humphfrahumph, we’re exploring it now. Alex made a mockup of what the first-pass implementation will look like.
Wrote some file-handling code for the Jetpack reboot. It won’t be used but helped me learn more about how the new platform works. Started a reboot FAQ with Atul and submitted a small patch. Would like to port the prototype’s simple JSON-backed storage to the reboot, and doing that will require writing some file-handling code. It’s cool, the reboot is heavily influenced by CommonJS, a specification for a cross-platform JavaScript standard library. As I understand it at this moment in time, the reboot’s platform—what Atul has named Cuddlefish—will be made up of various privileged modules that implement the CommonJS API. There may be modules for streams, module for XHRs, modules for sockets, just as there are such modules in an installation of Python or Ruby or Perl. On top of this Mozilla standard library sits the Jetpack API, and in between the two a security model. People have asked about a cross-browser extension platform ever since Atul and Aza started Jetpack. An interesting thing about using CommonJS is that Cuddlefish is born standardized. An interesting thing about the architecture as a whole is its modularity. Potentially you could use Cuddlefish to make traditional extensions while avoiding Jetpack altogether.
January 16, 2010 07:46 AM
I’ve spent the past week speaking with community members at development and product management meetings, as well as speaking with members of the technical press about the upcoming release of Firefox 3.6, which I truly believe to be the best browser for users. Of course everyone wants to know what’s next for Mozilla, and what the future looks like. Despite doing my best to be as clear as possible, what gets written can be more or less accurate.
The rumours of Firefox 3.7’s demise have been greatly exaggerated. Nobody’s planning on “dumping” features or the hard work of our passionate and tireless community.
The shape of the Internet changes every day. Our mission is to develop the best open source implementations of web technologies and ship them in an excellent browser so that our users and the entire Web can benefit. That means always thinking about how we can deliver technology as efficiently and quickly as possible. Sometimes it means challenging our assumptions.
One assumption we’ve had for a long time is that the only way to ship new technology – such as improvements to downloadable web fonts or support for new standards like CSS, SVG and WebGL – was through a full Firefox version update. Until recently, our infrastructure prevented us from being able to be as agile as we would have needed to be in order to deliver something isolated like the “Lorentz” project (which aims to improve product stability and security by running plugins in their own process) to our users. Now that we have better test automation and the ability to develop on project branches, we can better isolate changes with continuous integration testing, nightly builds and the ability to deliver smaller pieces continuously through the regular maintenance cycle (”minor updates”) of a product. This means that we can, without the user being disrupted or disturbed, improve stability, security, and capability for the 25% of the Internet users who browse using Firefox. One day they’ll start up their web browser and it will be better. Maybe it will crash less, maybe it will be improve typography support on the web.
This is a powerful change, but we must also be careful to keep users in control of their software. Improving the open video engine is something we should feel comfortable doing, as it preserves (but improves!) the existing user functionality. Changing the way the browser looks or interacts with users is something we should avoid doing. I think of it this way: if I take my car in for service and it comes out with better fuel efficiency, that’s great. If my gearshift has changed location, I’d be pretty surprised and upset. We shouldn’t be doing anything in a maintenance release that could leave a user surprised and upset, period.
So instead of thinking of “Firefox 3.7″ and “Firefox 4.0″ and being rigid and proscriptive about what technology improvements will come in which specific months, I’m encouraging us all to think about what we’re trying to improve, and how those improvements can be most efficiently delivered to our users and the Internet. Improvements and support for new technology originally slated for Firefox 3.7 in a draft roadmap long ago may now find their way into users’ hands even earlier. Risky interactive changes that could benefit from multiple iterations and betas can safely do so without worrying about “missing the boat.”
Software development is chaotic, and due to the open nature of our community you (and the press) are getting to see exactly how the sausages are made. It may look like a bloody mess at the start, but once it starts to take shape it’s obvious that you’re making something delicious.
January 16, 2010 01:28 AM
In an effort to provide realistic data in places.sqlite, I wrote a data generator in Python which inserts many records into places, and this was a good thing.
The data is entriely made up from random strings, and you end up with urls like this: http://ffhjhfj.uwtgbz.wsc
The same for tags, etc...
In order to make things more realistic and "testable" inside xpcshell, I created a crawler using Jetpack and standard Firefox XPCOM components. I have a feeling that QA might be interested in this as, so I posted to the
Jetpack GalleryIt is not configurable from the outside, but I have plans for that. I am planning on making JetCrawl surf every night for a set period to increase my collection of data work with.
I need this data in crafting a new Places Query API that is fast and well tested against a rather large collection of bookmarks and history. The urls that Jetcrawl use are taken from the Alexa Top 100, so it is a common set to boot.
Automated tests will work better with this data since it is hitting predictable urls and it is the actual places apis creating the data in the first place.
If you want to try it out, please use a new profile. You can stop it by closing the tab. There is no UI as of yet.
January 16, 2010 01:09 AM
Happy 2010 everyone!
Top Startup Bugs
| Estimated win |
Bug # |
Summary |
Owner |
Status |
Notes |
| >10% |
512584 |
Super fast paths for Components.classes and Components.interfaces |
Taras Glek |
in progress |
Taras is traveling, says he’ll close it out when he returns. |
| >10% |
525013 |
Investigate a more static build configuration of Firefox |
Joel Reymont |
in progress |
Lots of progress! Joel has a patch for Mac and Linux working on the tryserver, and numbers to confirm a partial static build gets ~8% improvement on Mac, with no compat problems. Zach added a bunch of number crunching to validate Joel’s numbers. On the Windows front, Taras has a patch in progress now. |
| up to 25% |
514083 |
Per-file HFS+ compression on Mac OSX 10.6 |
Joel Reymont |
in progress |
Conclusion is that we need to make this happen via the installer, as well as the updater, since modifying files results in decompression. Need to find an owner for this still. |
| TBD |
520309 |
Startup cache: replacement for fastload cache |
Ben Hsieh |
in progress |
Ben is looking into a perf regression that arose after some major changes. |
| TBD |
503483 |
Turn on –enable-faststart for Firefox by default |
Dietrich |
needs testing |
No update, need to test still. Maybe just push on Windows here. |
| TBD |
513149 |
Speed up CSS parsing by using a machine generated lexer |
Zack Weinberg |
Zack’s blocked on other work |
No update.Taras says about 6% of startup spent parsing CSS. |
Other activity this week:
Projects in a holding pattern:
- More investigation into Hunspell changes in bug 468799, possibly incorporating some changes Chrome made.
- Ryan Flint has a WIP patch to minify JS on bug 524858 that significantly reduces the size of shipped JavaScript files.
- JARification: David abandoned moving JS modules into a JAR file, since those files are fastloaded. However, since we want things like post-extension-install restarts to be fast, and those cause fastload cache invalidation, we might want to do things like this anyways. I filed a bug for the same treatment for components. These are lower priority, since they’re not the normal startup case. Follow along with all JAR-ification via the tracker bug.
- Startup Timeline: No updates, still not landed. Add [ft] in the whiteboard of your bug w/ the function names you want timed and David will generate it and update the bug.
- Static Analysis: No progress on bug 506128. David needs to file a bug with the final log of named-yet-uncalled functions.
- Dirty Profile Testing: No progress. We have a list of test scenarios, still need to file bugs for each, generate Talos config patches and profile data, and then move it into Rel-Eng territory. Also, need to get a separate Tinderbox tree, since it’s going to cause a bazillion new columns.
- Joel Reymont noted in bug 513076 that there are serious drawbacks to getting our libraries in the dyld shared cache on Mac, so has deprioritized that work.
As usual, more details and links are available on the project wiki, and we’re available to answer questions in #startup on irc.mozilla.org.

January 16, 2010 12:08 AM
January 15, 2010
Progress:
- Tracked down the cause of the following crashkill bug – Bug 501429 [Core] – Gmail tab crash while closing it’s tab [@ UserCallWinProcCheckWow ] (caused by Google Talk Plugin) [Windows XP]. This was a PITA due to it being in Firefox 3.0 cycle and there being no nightly builds for the range.
- Met with metrics to go over their requirements for Firefox.next.
- Received r+ on Bug 538533 [Toolkit] – If a complete update fails the update prompt should state the error and offer a link to download the update [All]. This is actually an old bug that causes QA to file bugs against app update during almost every release cycle.
- Performed over 5% of the Firefox 3.6 RC1 Full Functional Tests including all of the Windows 7 Multitouch Full Functional Tests.
Future targets:
- Get back on track with the Quarter 1 app update work.
January 15, 2010 10:03 PM
Done:
- Fixed a minor bug with the new extensions.checkCompatibility.X.Y pref naming
- Synced up with Unfocused and Boriss on the new add-ons manager UI
- Submitted a list of things we need added to AMO's API
- Posted to the community about the plan to drop extension dependencies
Next:
- Evaluate feedback from the community on dropping extension dependencies
- Work out how to handle lightweight/XPI themes in the new world order
- Expose stubs for additional metadata to the EM API
- Make async API work real
January 15, 2010 06:43 PM
Done:
- Started removing extension dependency support from the new EM backend.
- Changed some of the API notifications to better represent add-ons that don't require restarts.
- Fixed a bug involving opening new windows after canceled shutdowns.
Next:
- Work out how to handle lightweight/XPI themes in the new world order
- Expose stubs for additional metadata to the EM API
- Make async API work asynchronously
January 15, 2010 10:45 AM
January 13, 2010
If you’re involved with developing on Mozilla, odds are you’ve got at least one or two (dozen? :) profiles for testing. Some used regularly, some created-and-forgotten for one-off testing, some you’ve forgotten what they’re for. And you probably jump through gymnastics with the Profile Manager to create, select, and delete said profiles.
Once upon a time I used to do the same thing, until someone pointed out that there’s a different way to create and select profiles.
Old And Busted:
1) run firefox -P
2) Create new profile
3) Click, click, typeity, click
4) Select new profile
5) Swear, run firefox -P again because you didn’t mean to set that as your default
6) What was I doing again?
7) Oh yeah, test that thing. Quit.
8) run firefox -P
9) Delete profile
10) Lather, rinse, repeat for repeating testing with a clean new profile.
New Hotness:
1) mkdir /tmp/blah (or ~/profiles/blah for more permanence)
2) firefox -profile /tmp/blah
3) rm -rf /tmp/blah
At least for my workflow, I haven’t used the Profile Manager since. (This trick doesn’t depend on Profile Manager at all, so even it was removed at some point this would still work.) Some folks might prefer the Profile Manger for their needs, but this works great for me.
January 13, 2010 10:31 PM
January 12, 2010
For ages, I have relied on Douglas Crockford's excellent
supplant() for my string formatting needs in JS. It works great with whatever objects you have already hanging around in your code:
var myObj = { name: "Conan", surname: "The Barbarian" };
"{name} {surname}".supplant(myObj);
// result:
"Conan The Barbarian"
This is great, reliable and all that...
But it is a bit verbose in the cases where you do not already have an object hanging around with the correct properties. I tried to find an existing implementation, but most of them were still too verbose relying on hacks like: "{$1} {$2}" or "$1 $2" or worse.
I want a "printf" or Python-style string interpolation:
#python
"%s %s" % ("Conan", "The Barbarian",)
// result:
"Conan The Barbarian"
That's what I want! - only for strings, it doesn't have to be too feature-rich. Eventually it would be nice if it could handle integers and floats etc.
After some questions and answers on irc in #js, I was able to get something rudimentary going. I started with supplant, and added support for arrays and arguments.
Behold! String.printf():
String.prototype.printf = function (obj) {
var useArguments = false;
var _arguments = arguments;
var i = -1;
if (typeof _arguments[0] == "string") {
useArguments = true;
}
if (obj instanceof Array || useArguments) {
return this.replace(/\%s/g,
function (a, b) {
i++;
if (useArguments) {
if (typeof _arguments[i] == 'string') {
return _arguments[i];
}
else {
throw new Error("Arguments element is an invalid type");
}
}
return obj[i];
});
}
else {
return this.replace(/{([^{}]*)}/g,
function (a, b) {
var r = obj[b];
return typeof r === 'string' || typeof r === 'number' ? r : a;
});
}
};
Examples:
"{f} {b}".printf({f: "foo", b: "bar"});
"%s %s".printf(["foo", "bar"]);
"%s %s".printf("foo", "bar");
// all of which give this result:
"foo bar"
Let me know if you think of more tweaks for this - or problems. It pains me every time I see concatenation in JS code. Question, which is more efficient? '+' or String.replace()?
Cheers!
January 12, 2010 12:50 AM
January 11, 2010
As we get close to ship date, my calendar tends to fill up quite a bit as I meet with various team members to go over final checklists as well as my friends in the technical press to talk about what’s new and exciting in the world of Firefox. This has left me with a busier than usual week:

If I’m not as available as you’re used to, please accept my apologies in advance and send me an email, instead.
Oh, and if you haven’t already, do give the Firefox 3.6 Release Candidate a thorough try. Since I’ve been using this version since the alpha releases, it’s easy for me to forget how much of an improvement it is over what we were so proud to publish only 6 months ago. With built-in support for Personas, vastly improved stability and security, and new technology that improves the capabilities of the web as well as the speed with which we bring it to you, I’m pretty sure that Firefox 3.6 will be a big hit.
January 11, 2010 07:43 AM
January 10, 2010
Got back from my “holiday” late last week, after taking a 3-day roadtrip home. While away I mostly worked on the new Extension Manager UI, and am rather pleased with it all. Er, I relaxed and spent time with family too. Of course, almost everything else got ignored (including IRC). Back to the usual day-to-day awesomeness now.
Status
- Add-ons tree, list view, and detail view are all mostly implemented, hookup up the the new API, and look like the mockups
- New API is really nice to use
- Synced up with Mossop and Boriss (screensharing ftw!)
- Sorted out a weekly meeting time (timezones are fun)
Loose ends
- Need more data out of AMO’s API – Mossop has talked to people, filed bugs, etc
Next steps
- Installation and updates
- Searching
Target for next week
- Tackle searching
- Tweaks after latest round of mockups
No update. Expect things to move quickly this week.
Reflections
- Taking a break from a project can result in a more objective view of past decisions.
- Starting new projects is fun.
- Mondays are EVIL.
Related posts:
- Status update
- Status update
- Status update
January 10, 2010 10:24 PM
Mike Connor wrote:
The Personas and Jetpack projects were experiments designed to make extending the platform easier, and dramatically reduce the overhead involved in version updates/UI changes. We knew from the beginning that we would have to trade off truly limitless customizations to produce a more stable API/pseudo-API [...]
This is a strategic product decision, intended to grow our developer ecosystem and broaden the scope of potential developers as much as possible, and deliver a much better user experience with customizations across core application updates. Deprecating the old systems in favour of the new systems is a required part of the strategic plan, because it is not enough to simply build a better system, we must migrate our users and our developer ecosystem to that system to reap the benefits.
In this context, I think deprecation includes the intent to remove the thing after a transitioning period. If I got this wrong, please tell me so and stop reading here.
If removing the current system is indeed part of the plan, then I don’t understand the reasoning. The last quoted sentence says that the need to migrate users and developers to a better system implies the need to deprecate the current one. But once a truly better system is widely available, making it easier to write and maintain appealing extensions, then developers will migrate, users will follow. Why wouldn’t they?
This would fail if the new system was actually less attractive (e.g. harder to learn) than the current one, but that would undermine the whole campaign anyway and make a forceful migration unfitting.
It would also fail in cases where the new system lacks capabilities of the current system (it needs to lack some, for it shouldn’t inherit the compatibility issue). Trashing the current system wouldn’t magically migrate extensions depending such capabilities, it would rather trash them as well. Would this be acceptable if 10%, 30%, or 50% of the current extensions were affected, including some of the more popular ones? Are we, and if so, why are we confident that the remainder would be sufficient for maintaining our lead in extensibility rather than pulling us down to Chrome’s level? How would users who already opt out of major updates because of their favorite extension react to this? Would losing them be better than letting them wait for an extension to become compatible?
It seems wise to me to allow a smaller set of dedicated people to create traditional extensions and indeed maintain them over years. Carrying around a minority of these extensions doesn’t mean you couldn’t reap any benefits. You’d still get more developers involved in the new system, you’d still get people to depend on fewer traditional extensions.
January 10, 2010 06:13 PM
January 08, 2010
Progress:
- Dealt with a few items in my review queue.
- Patch ready for review – Bug 538533 [Toolkit] – If a complete update fails the update prompt should state the error and offer a link to download the update [All].
- Discussed with ddahl the after update action work he will be doing for Firefox.next and filed Bug 538331 [Firefox] – On update perform action based upon the update metadata [All] for this work.
- Profiled startup on Firefox WinCE with and without 325 named anonymous functions which showed there is no longer a cost for naming anonymous functions. I discussed this with Brendan and he confirmed that his upvar2 work removed the additional cost associated with naming anonymous functions.
Future targets:
- Land Bug 538533 [Toolkit] – If a complete update fails the update prompt should state the error and offer a link to download the update [All]
- Write mochitests for Bug 538533 [Toolkit] – If a complete update fails the update prompt should state the error and offer a link to download the update [All]
- Add backend suppport for Bug 538331 [Firefox] – On update perform action based upon the update metadata [All]
January 08, 2010 10:41 PM
January 04, 2010
Nothing sucks on the web like not being able to go to the site you want. Page not found and 404 errors are an inconvenience that entirely halt your workflow. What’s worse than not being able to access a site is not being given relevant information to fix the problem. When users are presented with an error message, they tend to do whatever will make the error go away to get back to their task. Page not found errors can’t be dismissed, because they’re shown instead of the content wanted.
What creates an added level of frustration is not being given information on what the problem is. When users get a Page not found error, they likely have two questions in mind:
- Is this problem on my end, or not?
- If the problem is on my end, how can I fix it?
These are questions that have been hard for browsers to answer. Currently, Firefox’s network error pages aren’t incredibly useful. They’re certainly not as useful as Chrome’s, which use Google Link Doctor to find possible matches both for subdirectories and domains. That won’t necessarily tell the user if the problem is on their end or not, but it will help if the problem is a typo.
So how could a browser tell users if the problem is on their end or not, without infringing on their privacy? One project that currently takes a stab at this is Herdict, which Johnathan Zittrain’s been working on at Harvard University’s Berkman Center for Internet and Society. What Herdict does is let computer users tell the “herd” – via a Firefox extension – what sites are accessible. The aggregated data can tell if a site is down (because no one can access it), or blocked by a firewall (because only some people can access it), or likely on the user’s end (because everyone else can access it). Not only does that answer the question of “is this problem on my end,” but it may start to answer questions like “is this problem only experienced by my country, network provider, or device?”
Useful stuff! Does it have a place in the browser, and specifically in Firefox? I think that getting and submitting anonymized data should have an increased role in the browser, and especially where it promotes transparency and information to the user. Mitchell Baker has been writing about data, and how Mozilla could be treating aggregated, anonymized data as a public asset that should be freely available. Especially in situations where sites are being blocked and censored, giving users knowledge of the situation seems to align with Mozilla’s goals of transparency and viewing the web as global public resource that must remain open and accessible.
One way something like Herdict could be incorporated is through those Page not found errors. If there were an option on these to submit anonymized data, we could build a pretty accurate view of accessibility information for a website and share it. Allowing users to submit data when there’s a problem is something many programs do already – especially for crashes. This is good design; it makes users feel better by registering the annoyance they feel as a useful data point to developers. Here’s some sketches of what it could look like to incorporate Herdict’s aggregated accessibility data with these error messages:
1. No available information on a site:

2. Site is blocked due to local firewall:

3. Site is down for a country:

4. Site is down for everyone:


January 04, 2010 01:31 AM
January 01, 2010
Landed Places protocol handler. Next: Finish patch for and land Places data should be visible in content. Despite the fact that Places UI work has slipped to 4.0, Dietrich wants a first-pass implementation of Places-in-content on trunk so people can play with it.
New bug Asynchronous API for opening nsNavHistoryFolderResultNodes and patches for it, the first of which Marco has reviewed. It moves opening bookmark folders off the main thread, sans batching. Started on the non-bookmark folder counterpart—history and searches and such—but progress there depends on the aforementioned bug. I am going to land async Places containers before the end of Q1 fer sher. No one will stop me. NO ONE. Am thinking it would be nice to get Clear Recent History completely off the main thread next; it wasn’t when I touched it, but Marco’s recent work on async history expiration might have covered most of it. I want to make you faster and more responsive, Firefox, and I will work the levers my fat tiny hands can grasp.
Various Jetpack things. Landed two bugs related to the in vivo API reference, API Reference broken in 0.7 (nice) and API Reference should link to MDC docs, and menu bug menu.remove() and menu.replace() don’t work with regular expressions. Worked on the documentation: Stubbed out missing docs to point to the appropriate JEPs, cleaned up the front page and subpages a little, wrote the simple storage doc complete with a full example people can install. A few Jetpack Gallery user-friendliness bugs I filed landed: Make page titles more friendly, since they become the names of jetpacks, Source code should be viewable without having to log in, and Share Jetpack popup obscures View Source Code link.
January 01, 2010 12:39 AM
December 23, 2009
I’ve spent some time profiling the startup costs for JavaScript components from the first app-startup notification through the last final-ui-startup notification. I’ve limited the data to just these notifications for the time being in order to keep the focus specifically on this subset of startup cost to make the analysis easier. All times are in milliseconds and the profiling was done on WinCE Firefox trunk using a Tegra device. The patches in Bug 507012 were used and as can be seen the noise is pretty darn small. Where possible I have calculated the difference between the start and end time for each component (this isn’t immediately obvious from the log files) so the data would include at least some of the native code cost for the component during startup. This additional cost is readily apparent in the tables at the end of this post where fuelApplication.js is removed entirely from startup.
Note: get_PB_Enabled is short for PBS_get_privateBrowsingEnabled in nsPrivateBrowsingService.js.
Samples: 50
| stage |
file |
function |
avg |
stdev |
min |
max |
| start to final |
|
|
3946.148 |
62.610 (1.59%) |
3832.055 |
4087.264 |
| app-startup |
|
|
927.774 |
8.117 (0.87%) |
911.413 |
946.115 |
| app-startup |
fuelApplication.js |
JS_Execute |
632.945 |
7.690 (1.21%) |
617.986 |
655.014 |
| app-startup |
fuelApplication.js |
init|observe |
22.706 |
0.301 (1.33%) |
22.368 |
23.980 |
| app-startup |
nsSessionStartup.js |
JS_Execute |
27.703 |
0.304 (1.10%) |
27.271 |
28.404 |
| app-startup |
nsSessionStartup.js |
init|observe |
12.801 |
0.137 (1.07%) |
12.645 |
13.180 |
| app-startup |
nsBrowserGlue.js |
JS_Execute |
48.739 |
0.527 (1.08%) |
45.564 |
49.544 |
| app-startup |
nsBrowserGlue.js |
init|observe |
22.068 |
0.129 (0.58%) |
21.931 |
22.386 |
| app-startup |
nsPrivateBrowsingService.js |
JS_Execute |
30.141 |
0.306 (1.01%) |
29.725 |
31.694 |
| app-startup |
nsPrivateBrowsingService.js |
init|observe |
21.593 |
0.177 (0.82%) |
21.341 |
22.277 |
| app-startup |
WebContentConverter.js |
JS_Execute |
33.150 |
0.225 (0.68%) |
32.904 |
34.148 |
| app-startup |
WebContentConverter.js |
init|observe |
9.549 |
0.073 (0.76%) |
9.444 |
9.741 |
| app-startup |
nsTryToClose.js |
JS_Execute |
12.994 |
0.386 (2.97%) |
12.587 |
14.098 |
| app-startup |
nsTryToClose.js |
init|observe |
10.511 |
0.247 (2.35%) |
10.164 |
11.232 |
| profile-after-change |
|
|
343.994 |
3.557 (1.03%) |
337.407 |
352.034 |
| profile-after-change |
nsPrivateBrowsingService.js |
observe |
8.906 |
0.278 (3.12%) |
8.232 |
9.834 |
| profile-after-change |
nsExtensionManager.js |
JS_Execute |
192.271 |
3.356 (1.75%) |
186.200 |
199.659 |
| profile-after-change |
nsExtensionManager.js |
init|observe |
86.652 |
0.493 (0.57%) |
84.153 |
84.153 |
| profile-after-change |
nsUpdateTimerManager.js |
JS_Execute |
19.618 |
0.099 (0.50%) |
19.376 |
19.832 |
| profile-after-change |
nsUpdateTimerManager.js |
init|observe |
11.913 |
0.100 (0.84%) |
11.779 |
12.122 |
| profile-after-change |
nsUpdateServiceStub.js |
JS_Execute |
9.062 |
0.083 (0.92%) |
8.877 |
9.265 |
| profile-after-change |
nsUpdateServiceStub.js |
init |
9.599 |
0.198 (2.06%) |
9.396 |
10.240 |
| command-line-startup |
|
|
3.953 |
0.079 (2.00%) |
3.866 |
4.108 |
| command-line-startup |
nsPrivateBrowsingService.js |
observe |
3.953 |
0.079 (2.00%) |
3.866 |
4.108 |
| called-from-native |
nsPrivateBrowsingService.js |
get_PB_Enabled |
2.130 |
0.085 (4.01%) |
2.059 |
2.450 |
| called-from-native |
nsExtensionManager.js |
EM_start |
201.015 |
2.805 (1.40%) |
196.609 |
208.310 |
| final-ui-startup |
|
|
183.553 |
0.932 (0.51%) |
181.029 |
186.338 |
| final-ui-startup |
nsBrowserGlue.js |
observe |
167.908 |
0.907 (0.54%) |
165.127 |
170.474 |
| final-ui-startup |
nsSessionStartup.js |
observe |
13.533 |
0.179 (1.32%) |
13.235 |
13.995 |
| final-ui-startup |
fuelApplication.js |
observe |
1.637 |
0.110 (6.73%) |
1.564 |
1.873 |
Totals for each component using their averages from the previous table.
Samples: 50
| Component |
JS_Execute |
CallHooks |
Total |
| fuelApplication.js |
632.945 |
24.343 |
657.288 |
| nsExtensionManager.js |
192.271 |
287.667 |
479.937 |
| nsBrowserGlue.js |
48.739 |
189.976 |
238.715 |
| nsPrivateBrowsingService.js |
30.141 |
36.582 |
66.723 |
| nsSessionStartup.js |
27.703 |
26.334 |
54.037 |
| WebContentConverter.js |
33.150 |
9.549 |
42.698 |
| nsUpdateTimerManager.js |
19.618 |
11.913 |
31.531 |
| nsTryToClose.js |
12.994 |
10.511 |
23.505 |
| nsUpdateServiceStub.js |
9.062 |
9.599 |
18.660 |
One thing that stands out is that fuelApplication.js appears to be paying a penalty for being the first JavaScript component to load. To verify this I made nsSessionStartup.js load first, fuelApplication.js load second, and analyzed the new data. The results showed that the load first penalty is ≈ 558ms for JS_Execute and ≈ 10ms for the first CallHook.
Totals for each component using their averages with nsSessionStartup.js loading first and fuelApplication.js loading second (complete table not shown).
Samples: 50
| Component |
JS_Execute |
CallHooks |
Total |
| nsSessionStartup.js |
584.927 |
37.141 |
622.067 |
| nsExtensionManager.js |
192.704 |
288.571 |
481.275 |
| nsBrowserGlue.js |
48.255 |
189.883 |
238.138 |
| fuelApplication.js |
74.777 |
15.408 |
90.185 |
| nsPrivateBrowsingService.js |
30.115 |
36.482 |
66.597 |
| WebContentConverter.js |
33.068 |
9.534 |
42.601 |
| nsUpdateTimerManager.js |
19.615 |
11.916 |
31.530 |
| nsTryToClose.js |
12.987 |
10.508 |
23.495 |
| nsUpdateServiceStub.js |
8.949 |
9.653 |
18.602 |
There are a couple of things that can be done to the nsExtensionManager.js component that I’ll write about later. Besides optimizing a couple of these components I think that the fuelApplication.js component should either be re-written as a JavaScript module or be removed entirely. With its removal from the startup path startup time is reduced by ≈ 140ms on WinCE Firefox trunk with a Tegra device as can be seen below. I suspect that this would also reduce startup on a few of the Firefox desktop platforms by ≈ 1%.
Filed: Bug 536504 [Firefox] – Remove fuelApplications.js from the startup path [All]
Samples: 30
| stage |
file |
function |
avg |
stdev |
min |
max |
| start to final |
|
|
3806.027 |
54.004 (1.42%) |
3673.833 |
3919.366 |
| app-startup
| |
|
824.938 |
9.636 (1.17%) |
807.022 |
844.464 |
| app-startup |
nsSessionStartup.js |
JS_Execute |
569.328 |
6.921 (1.22%) |
554.889 |
580.804 |
| app-startup |
nsSessionStartup.js |
init|observe |
23.529 |
1.419 (6.03%) |
21.495 |
26.296 |
| app-startup |
nsBrowserGlue.js |
JS_Execute |
52.306 |
3.796 (7.26%) |
36.339 |
59.105 |
| app-startup |
nsBrowserGlue.js |
init|observe |
22.714 |
0.112 (0.50%) |
22.513 |
22.945 |
| app-startup |
nsPrivateBrowsingService.js |
JS_Execute |
28.945 |
0.163 (0.56%) |
28.527 |
29.397 |
| app-startup |
nsPrivateBrowsingService.js |
init|observe |
20.176 |
0.110 (0.55%) |
19.980 |
20.384 |
| app-startup |
WebContentConverter.js |
JS_Execute |
35.192 |
0.173 (0.49%) |
34.916 |
35.591 |
| app-startup |
WebContentConverter.js |
init|observe |
9.532 |
0.128 (1.34%) |
9.305 |
9.968 |
| app-startup |
nsTryToClose.js |
JS_Execute |
13.500 |
0.560 (4.14%) |
13.083 |
14.826 |
| app-startup |
nsTryToClose.js |
init|observe |
9.889 |
0.317 (3.20%) |
9.559 |
10.702 |
| profile-after-change
| |
|
343.520 |
5.753 (1.67%) |
330.411 |
360.803 |
| profile-after-change |
nsPrivateBrowsingService.js |
observe |
5.880 |
0.442 (7.51%) |
4.748 |
6.569 |
| profile-after-change |
nsExtensionManager.js |
JS_Execute |
196.433 |
5.820 (2.96%) |
184.414 |
215.039 |
| profile-after-change |
nsExtensionManager.js |
init|observe |
86.338 |
0.264 (0.31%) |
85.751 |
86.854 |
| profile-after-change |
nsUpdateTimerManager.js |
JS_Execute |
19.623 |
0.094 (0.48%) |
19.428 |
19.792 |
| profile-after-change |
nsUpdateTimerManager.js |
init|observe |
11.814 |
0.111 (0.94%) |
11.701 |
11.701 |
| profile-after-change |
nsUpdateServiceStub.js |
JS_Execute |
7.826 |
0.083 (1.06%) |
7.608 |
8.059 |
| profile-after-change |
nsUpdateServiceStub.js |
init |
9.714 |
0.080 (0.82%) |
9.588 |
9.882 |
| command-line-startup
| |
|
4.940 |
0.073 (1.48%) |
4.837 |
5.111 |
| command-line-startup |
nsPrivateBrowsingService.js |
observe |
4.940 |
0.073 (1.48%) |
4.837 |
5.111 |
| called-from-native |
nsPrivateBrowsingService.js |
get_PB_Enabled |
2.137 |
0.103 (4.81%) |
2.054 |
2.390 |
| called-from-native |
nsExtensionManager.js |
EM_start |
197.268 |
2.809 (1.42%) |
193.497 |
204.272 |
| final-ui-startup
| |
|
177.882 |
0.716 (0.40%) |
177.263 |
180.097 |
| final-ui-startup |
nsBrowserGlue.js |
observe |
164.155 |
0.631 (0.38%) |
163.518 |
166.598 |
| final-ui-startup |
nsSessionStartup.js |
observe |
13.495 |
0.399 (2.96%) |
13.215 |
15.489 |
Totals for each component using their averages without fuelApplication.js from the previous table.
Samples: 30
| Component |
JS_Execute |
CallHooks |
Total |
| nsSessionStartup.js |
569.328 |
37.024 |
606.352 |
| nsExtensionManager.js |
196.433 |
283.605 |
480.038 |
| nsBrowserGlue.js |
52.306 |
186.869 |
239.174 |
| nsPrivateBrowsingService.js |
28.945 |
33.134 |
62.080 |
| WebContentConverter.js |
35.192 |
9.532 |
44.724 |
| nsUpdateTimerManager.js |
19.623 |
11.814 |
31.437 |
| nsTryToClose.js |
13.500 |
9.889 |
23.389 |
| nsUpdateServiceStub.js |
7.826 |
9.714 |
17.539 |
The profile logs used for this analysis include additional details including call stacks and are available for download…
profile logs
December 23, 2009 11:56 AM
Since I spend most of my online time in front of a netbook, saving screen real estate has become a lot more important to me. Gaining or losing 50px vertically has immediate implications on the usability of a number of websites that I frequent. In this regard, Firefox with its default configuration isn’t quite the product that I need it to be. At the same time, the default configuration makes sense to me, as I regularly use most of what it provides. So this isn’t just about cruft removal. I want the whole package for half the price.
In this post, I will describe how I got there:

The menu bar. I use it every day, but not so often that I need to see it all the time. So I just implemented what IE does. Starting with Firefox 3.6, every Windows user will be able to hide the menu bar in Firefox and show it temporarily with the Alt key.
The bookmarks toolbar is my only place for bookmarks. The bookmarks menu hasn’t grown on me, although I’m not sure why. I definitely don’t and won’t use the clunky bookmarks sidebar or the Library to access a particular bookmark. So the toolbar it is. But like the menu bar, I neither need nor want it to occupy space permanently. And as with the menu bar, the solution turned out to be simple. I took the bookmarks button that Firefox provides in the toolbar customization palette and made it show/hide the bookmark toolbar rather than the sidebar. You can get the extension for this here.
The status bar is trickier. I mostly need it for exposing link targets (since the progress bar is redundant). I tried to stop depending on that, but it didn’t work. I need the URLs to be displayed, even if I won’t read them out most of the time. Existing solutions for Firefox show the status bar temporarily or display link targets in the location bar, both of which didn’t feel ideal to me. It took me months to figure this out, but I think Chrome gets this right: It displays the URL in a small panel in a bottom corner of the browser window. This allows me to look there when I need it and ignore it otherwise. Just what I need. So I implemented something similar for Firefox. You can get the extension here.
December 23, 2009 09:55 AM
December 22, 2009
Firefox 4 mockup, published yesterday:

Opera 10.5 pre-alpha screenshot, published today:

The history of Opera’s user interface isn’t exactly a success story. I wonder whether we should be proud of leading them the right way or afraid of heading the same way as Opera.
December 22, 2009 12:24 PM
December 21, 2009
I’m in beautiful Motueka for two and a half weeks, staying with Anne’s family; enjoying the scenery and generally relaxing. I’ll be working while up here (working remotely remotely – very meta), but don’t expect to see me on IRC as much as usual.
Status
- Fixed unit tests, and fixed code breaking unit tests
- First code review done (epic job done by Marco) – very positive
Loose ends
- Need an icon made (no rush for this)
Next steps
- There’s a unit test that fails on the Tryserver Tinderbox but not locally on my machine – need to figure that out
- Fix reviewer’s recommendations, rinse, repeat
Target for next week
- Another round of reviews!
Status
- Re-read all (?) existing material, studied mockups, etc
- Met with Mossop, who is designing and implementing the new API
- Started building initial (dumb, non-interactive) prototype based on Boriss’s mockups
Loose ends
Next steps
- Non-interactive prototype based on mockups
- Start pulling info from new API, and provide Mossop with feedback from experience
Target for next week
- At least one mockup looking the same in XUL
Miscellaneous
- Bug 397937 (view-source on safebrowsing blocked pages) is ready to be landed (also fixes bug 435726)
Reflections
- Being stuck on a slow 3G connection may prove to be actually good for my productivity
- Hot weather is not good for my productivity (counteracting the above point)
Related posts:
- Status update
- Status update
- Status update
December 21, 2009 10:43 AM
Recently there has been a lot of work going on refining the ideas for the Firefox 4 redesign on Windows. This work has involved evaluating feedback on previous direction, polishing visuals, tweaking all kinds of things and exploring totally new ideas. The evolutionary work that was supposed to span 3.7 and 4.0 has now shifted full focus to the latter.
This week I have been working on a few things:
1) App Button
One of the more challenging, not to mention contentious, aspects of the Firefox UI update has been how to handle the MenuBar. On our first pass we were informed by how Safari and Chrome had handled this problem by paring down all menu items into two separate Page and Tools buttons. This approach has a few advantages but also some disadvantages. The new proposed approach to this problem is an App Button which is similar to the single menu approach taken by Windows 7 native applications (Paint, WordPad) and by MS Office.
The UX team feels this approach has several advantages over the previous idea:
- It is less complex
- Takes up less space
- Instead of two potentially conflicting locations for menu items, there is now only one unified location
- Can be placed in the upper left analogous to the Menubar paradigm it is replacing
- Similar to the far more ubiquitous Office 2008/2010 + Windows 7 application menu
- Reduces clutter on the Navigation Toolbar
- It also creates a more flexible and rich canvas for perhaps doing some decidedly non-menu-esque things
Appearance and Placement
One of the benefits of the App Button is that it is similar to the way Microsoft is treating its native apps and Office. Another benefit is that the placement is closer to where the Menubar would be and therefore it is more familiar.
One idea that we have already explored with the Pages and Tools buttons is to use text on the button instead of an icon. This is also reminiscent of the Menubar’s textual display and removes any ambiguity involved with icons. This approach is also explored in the most recent Office 2010 beta with the tab simply being labeled “File”. We discussed naming our App Button simply “Firefox” because it contains all the actions that apply to Firefox.
Attaching the button to the top of the window further implies that this menu affects Firefox as a whole.
Status of the Titlebar
In all the mockups up to this point the Titlebar has been removed and the space reallocated for portions of the tabs. Enough room was left for traditional window dragging. The rational behind this change was to further shrink vertical space and to address the redundancy of having the page title in the Titlebar and the tab.
In the original approach you would lose approximately the width of one tab (or less!) due to the window widgets. This was before talk of placing an App Button or an Identity button in this area. As it stands now you would be losing much more. It seems the vertical space tradeoff doesn’t stack up quite as well when losing so much horizontal tab space.
It would be better to leave the Titlebar, giving full access to it and not losing any tab space. It also won’t be frustrating for someone wanting to drag the window.
State of the Menu
What will this single menu look like? Something like the sketch I posted previously but not exactly. Ideas on this are welcome. Thoughts about what should and should no go into this menu can be based on work already done for menu cleanup.
2) Refining Toolbar Button Appearance:
Some initial work has gone into making the toolbar buttons more visible on light backgrounds and more crisp and dimensional (pressable).
This is work I am constantly reevaluating since they appear on variable backgrounds.
3) Location Bar:
Created some very early visuals for reevaluating site identity. Also the location bar is now properly recessed instead of floating.
4) Retain Separate Search Bar:
With the LocationBar containing an increasing amount of functionality it may be best to retain a clear distinction between the two fields.
5) Bookmarks Widget:
On a default profile or existing profile that hasn’t modified the Bookmarks Toolbar it will be hidden by default and the Bookmarks Widget placed in the Navigation Toolbar.
If the Bookmarks Toolbar is shown the Bookmarks Widget will appear there instead.
Alternatives to Default Configurations
With Bookmarks Bar
Tabs Under the Navigation Bar
If tabs-on-top is not desirable you can change to the classic tabs under the navigation bar.
Tabs Under the Navigation Bar with Bookmarks Bar
App Button Variations
Several variations of the App Button have been explored. Various factors of consideration include what color to make it, whether or not to have an icon, just an icon, icon and text, part of the tab bar, a separate button or attached to the top of the window.
Presently it is orange and attached to the top of the menu simply labeled “Firefox”. The color plays off of the Firefox icon and is noticeable. The placement attaches the button to the top of the window and suggests that its items apply to the whole menu. It also corresponds to the area of the window where someone would look for the menu bar. Using text only is reminiscent of a menu item.
Firefox 4 and Firefox 3.5 Comparison
A visual comparison of the current iteration of Firefox 4 next to Firefox 3.5
December 21, 2009 06:10 AM
December 20, 2009
Spent most of the week on Jetpack. Landed support for letting jetpacks tailor their first-run experience. They can define some HTML or point to a URL that will be shown on their installation and register a callback to perform arbitrary work on installation. Wrote up docs for these also, here and here.
Finally a patch that should pass Marco’s review on bug 529597, Places protocol handler.
The more I work on making Places containers async, the dumber I feel. Been working on this how long? Whittling it down how much? Trying to move some sorting to SQL, but since it can’t all be moved there, it’s important that the sorting there is equivalent to the sorting we do in C++. Problem is, the C++ sorting has some conditionals that are hard to do in SQL. Marco suggested writing a SQLite function that does the same. That’s a possibility, but its performance characteristics are unknown. A solution I like better is to simply change the semantics of the sorts to something simpler that can be done in SQL without jumping through hoops.
A third possibility is to kick the can down the road. SQL sorting is only necessary for returning batches of results to consumers as they asynchronously load from the database. It is not necessary for simply moving off the main thread queries and their associated I/O—a Q1 goal. This approach is easier to implement, and I think it could be done on the way to batch loading. The difference to the user is this: With batch loading, the first results will load and display fairly quickly, and as new batches come in they’ll fill the view batch-by-batch. Without batch loading, you’ll be waiting for the entire result set to load, and when it does all results will be displayed at once.
December 20, 2009 02:20 AM
December 18, 2009
Not much change from my late post on Monday, but a few updates below. I’ll be out of the office as of this Monday, and back on 1/11/2010. If you’re starving for startup info during that time, hit up Taras, Joel and Planet Firefox for the goods. The current numbers for startup and all other tests are available on the Performance Snapshot Page.
Top Startup Bugs
| Estimated win |
Bug # |
Summary |
Owner |
Status |
Notes |
| >10% |
512584 |
Super fast paths for Components.classes and Components.interfaces |
Taras Glek |
in progress |
Taras says mostly there. |
| >10% |
525013 |
Investigate a more static build configuration of Firefox |
Joel Reymont |
Mac and Linux in progress |
Joel’s working on getting load of XPCOM components working now. Next step is completing runs of the performance tests on the tryserver. |
| up to 25% |
514083 |
Per-file HFS+ compression on Mac OSX 10.6 |
Joel Reymont |
in progress |
Snow Leopard only. More testing needed to see if it’s feasible to compress at install-time, or if we’ll have to ship SL builds. |
| TBD |
520309 |
Startup cache: replacement for fastload cache |
Ben Hsieh |
in progress |
Brendan suggested some significant changes, in-progress. |
| TBD |
503483 |
Turn on –enable-faststart for Firefox by default |
Dietrich |
needs testing |
No update this week. Loads Firefox core libraries at boot time. Need to test on all OSes, publish the numbers, and get discussion going. |
| TBD |
513149 |
Speed up CSS parsing by using a machine generated lexer |
Zack Weinberg |
Zack’s blocked on other work |
Taras says about 6% of startup spent parsing CSS. |
Other activity this week:
- More investigation into Hunspell changes in bug 468799, possibly incorporating some changes Chrome made.
Projects in a holding pattern:
- Ryan Flint has a WIP patch to minify JS on bug 524858 that significantly reduces the size of shipped JavaScript files.
- JARification: David abandoned moving JS modules into a JAR file, since those files are fastloaded. However, since we want things like post-extension-install restarts to be fast, and those cause fastload cache invalidation, we might want to do things like this anyways. I filed a bug for the same treatment for components. These are lower priority, since they’re not the normal startup case. Follow along with all JAR-ification via the tracker bug.
- Startup Timeline: No updates, still not landed. Add [ft] in the whiteboard of your bug w/ the function names you want timed and David will generate it and update the bug.
- Static Analysis: No progress on bug 506128. David needs to file a bug with the final log of named-yet-uncalled functions.
- Dirty Profile Testing: No progress. We have a list of test scenarios, still need to file bugs for each, generate Talos config patches and profile data, and then move it into Rel-Eng territory. Also, need to get a separate Tinderbox tree, since it’s going to cause a bazillion new columns.
- Joel Reymont noted in bug 513076 that there are serious drawbacks to getting our libraries in the dyld shared cache on Mac, so has deprioritized that work.
As usual, more details and links are available on the project wiki, and we’re available to answer questions in #startup on irc.mozilla.org.

December 18, 2009 10:32 PM
Progress:
- Landed on 1.9.0 for Firefox 3.0.18, 1.9.0 GECKO190_20091130_RELBRANCH for Firefox 3.0.17, 1.9.1 for Firefox 3.5.8, 1.9.1 GECKO1916_20091130_RELBRANCH for Firefox 3.5.7, 1.9.2 for Firefox 3.6, and trunk (yes, it is a tad ridiculous listing them all but it was even more ridiculous having to land this six times) – Bug 534090 [Toolkit] – do not use background notification for major updates (was PMU 3.0->3.5 major update has been really poor) [All].
- Performed a bunch of startup JavaScript component profiling and I’ll blog about my findings after I have correlated the data.
- Edited to add – Landed on trunk – Bug 529942 [Toolkit] – Remove nsIApplicationUpdateService2 on trunk [All]
Future targets:
- Define app update work for Q1 2010.
December 18, 2009 08:20 PM