Two years ago I blogged about how it had been six years since I wrote my first patch for Firefox. Today I get to say that it’s been six years since I started getting paid to do what I love, working for Mozilla. In that time I’ve moved to a new continent, found a wife (through Mozilla no less!), progressed from coder to module owner to manager, seen good friends leave for other opportunities and others join and watched (dare I say helped?) Mozilla, and the Firefox team in particular, grow from the small group that I joined in 2007 to the large company that will soon surpass 1000 employees.
One of the things I’ve always appreciated about Mozilla is how flexible they can be about where you work. Recently my wife and I decided to move away from the bay area to be closer to family. It was a hard choice to make as it meant leaving a lot of friends behind but one thing that made it easier was knowing that I wouldn’t have to factor work into that choice. Unlike many other companies I know there is no strict requirement that everyone work from the office. True it is encouraged and it sometimes makes sense to require it for some employees, particularly when starting out, but I knew that when it came time to talk to my manager about it he wouldn’t have a problem with me switching to working remote. Of course six years ago when I started I was living in the UK and remained so for my first two years at Mozilla so he had a pretty good idea that I could handle it, and at least this time I’m only separated from the main office by a short distance and no time-zones.
The web has changed a lot in the last six years. Back then we were working on Firefox 3, the first release to contain the awesomebar and a built-in way to download extensions from AMO. Twitter and Facebook had only been generally available for about a year. The ideas for CSS3 and HTML5 were barely written, let alone implemented. If you had told me back then that you’d be able to play a 3D game in your browser with no additional plugins, or watch videos without flash I’d have probably thought they were crazy pipe-dreams. We weren’t even Jitting our JS code back then. Mozilla, along with other browser makers, are continuing to prove that HTML, CSS and JS are winning combinations that we can build on to make the future of the web open, performant and powerful. I can’t wait to see what things will be like in another six years.
It’s been a long ride but we can finally say it. This week Firefox 21 shipped and it includes the add-on SDK modules.
What does this mean? Well for users it means two important things:
Smaller add-ons. Since they no longer need to ship the APIs themselves add-ons only have to include the unique code that makes them special. That’s something like a 65% file-size saving for the most popular SDK based add-ons, probably more for simpler add-ons.
Add-ons will stay compatible with Firefox for longer. We can evolve the modules in Firefox that add-ons use so that most of the time when changes happen to Firefox the modules seamlessly shift to keep working. There are still some cases where that might be impossible (when a core feature is dropped from Firefox for example) but hopefully those should be rare.
To take advantage of these benefits add-ons have to be repacked with a recent version of the SDK. We’re working on a plan to do that automatically for existing add-ons where possible but developers who want to get the benefits right now can just repack their add-ons themselves using SDK 1.14 and using cfx xpi --strip-sdk, or using the next release of the SDK, 1.15 which will do that by default.
As part of the Grow Mozilla effort, the coding stewards have been working to grow our coding community. Our main focus has been to increase the number of contributions to the core mozilla-central codebase, which includes making it easier for newcomers to get started, as well as keeping existing contributors engaged. Recent work has been focused on things like mentored bugs and recognizing contributors.
We hold open weekly meetings every Wednesday to discuss progress on these goals, but we want to give more developers the opportunity to get involved with this effort, so we created the coding-stewards@mozilla.org mailing list for broader discussion. If you’re interested in growing our coding community, but you might not be interested in another weekly meeting, please join the list!
I got to spend Wednesday through Friday in Edinburgh last week to attend
Scotland.JS. Edinburgh is a lovely city and I will
definitely return to get to know it better. It has great people, beers, food and
even a castle - what could one want more?
I arrived on Wednesday, just in time for the
TechMeetup. It took place in the Appleton Tower and
had about 70-80 attendees with quite diverse technical backgrounds. I had a very
interesting talk to a freelance patent attorney and also met a couple of people
I knew from recent conferences and meetups in Berlin. After we were out of free
pizza and beers we met most of the Scotland.JS attendees in a pub right next to
the Appleton Tower. Cue more beers and tech conversations.
Thursday was the first day of Scotland.JS that started with
a great keynote
from Jan Lehnardt. The most memorable talk of the
day was about
Functional Reactive Programming using Bacon.js
by Philip Roberts. There of course were a
lot more great talks but the possibilities of creating and combining event
streams kept my head spinning the most. At the end of the day we again went to a
neat pub near the venue and I headed to bed rather early, still a little tired
from travel and the day before.
Friday started with a short 20-minute walk through Edinburgh’s old town that I
needed to pass on my way to the venue. My favorite talk of the second and last
day was held by Dominic Tarr that tought us
about
the internals of leveldb.
I also really enjoyed Mark Boas talking about
making audio a first-class citizen of the web
- a very entertaining and impressive mix of technologies. A GitHub drinkup in
the venue’s own pub was a great way to end the conference - lots of good
conversations with Scotland.JS attendees and speakers as well as people from the
local tech community and visitors of the Scottish Ruby Conf.
I flew home the very next day and already miss Edinburgh with its neat little
alleys and pubs everywhere. The JavaScript community has once again shown its
value as a very interesting mix of nice welcoming people coming from so many
different technical backgrounds. Like after most conferences I feel a little
exhausted and my head is full of ideas for future or current (side-)projects. I
will try my best to return next year, it has been a lot of fun!
Almost two years, I experimented with using the dominant color of a favicon to give a small icon a colorful background. And over the past week, I wrotesomepatches to incorporate this design into Firefox for Android!
The simple algorithm I wrote long ago was done in JS with canvas, but to use this in our native Android UI, it’s simplest to just do it in Java. Luckily, we already had a dominant color utility method in the tree, but creating a background and border with different saturation levels was trickier than I thought it would be. To solve this problem, I gave the ImageView a background drawable with a solid white interior and a gray border, then applied a transparent version of the dominant color as a color filter. This worked pretty well once I figured out which PorterDuff mode to use, but it made me appreciate the simplicity of CSS.
When testing with various icons, I found that our dominant color algorithm could use some improvement. Our Java algorithm is different than the one I experimented with in JS mainly because it uses the HSV color model as opposed to RGB. Instead of counting every distinct color, we split the range of hues into different bins and find the bin that holds the most colors. For the winning bin, we compute the average H, S, and V values within that bin, and return that as the dominant color. To make sure we only return colorful colors, we ignore transparent pixels, as well as pixels that are close enough to black or white. This simple algorithm may not be perfect, but it works pretty well for us, especially for small favicons.
As an interesting bit of history, after I blogged about my dominant color experiment, Mardak wrote an add-on that used an improved version of my JS snippet. At the time, Wes saw this add-on and incorporated the code into XUL Fennec to create icons for homescreen shortcuts. During the Fennec Native rewrite, Wes reimplemented this feature in Java, and that’s the code I found myself in last week. And for those interested in a more robust solution implemented in JS, there’s actually a toolkit service that does this now.
Update: Please note that this post describes the current implementation in
SpiderMonkey. The final
ES6 specification
will require generator functions to have a ‘*’ token as in function* nat()
{ … }. The flatten() function from the last example could use yield* to
delegate instead of a nested loop.
JavaScript comes with most of the little functional tools you need to work on
finite sequences that are usually implemented using Arrays. Array.prototype
includes a number of methods like map() and filter() that apply a given
function to all items of the Array and return the resulting new Array.
[1,2,3].map(x=>x+1);// result: [2, 3, 4];
These tools however are not a good fit for infinite sequences as they always
consume the whole sequence at once to return a new one. Implementing infinite
sequences by yourself means you would have to come up with your own API that
clients need to adhere to. You often would keep state variables whose values
need to be maintained for the duration of the computation process.
Generators to the rescue
Using ES6
generators
implementing the infinite sequence of all natural numbers turns out to be a
trivial task. We even have language support to iterate over them.
functionnat(){vari=1;while(true){yieldi++;}}varit=nat();console.log(it.next(),it.next(),it.next());// prints 1 2 3
Now that we have a first infinite set we need a couple of functions that help us
working with, combining, and building new sequences.
Mapping
Let us start with map() - a function at the very heart of functional
programming. It builds a new sequence by applying a function to all elements of
a given sequence.
functionmap(it,f){for(varxofit){yieldf(x);}}
Using the generator implementation of map() we can now easily write a function
called squares() that represents the set of squares of all natural numbers
(1², 2², 3², …, n²).
functionsquares(){returnmap(nat(),x=>x*x);}varit=squares();console.log(it.next(),it.next(),it.next());// prints 1 4 9
Using
for…in
instead of
for…of
works fine but using of has a neat advantage in that it properly iterates
Arrays as well. If you want to map values of a finite sequence you can just do
that.
varit=map([1,2,3],x=>x*x);console.log(it.next(),it.next(),it.next());// prints 1 4 9
Filtering
Another common task is filtering specific values from a sequence. Our custom
implementation of filter() takes an iterator and a predicate - the returned
sequence will consist of all items of the original one for which the predicate
holds.
Suppose we were to implement a sequence that represents all
Mersenne prime numbers.
Mersenne primes are defined as prime numbers of the form Mn = 2n - 1,
that is the set of all numbers of the given form that have no positive divisors
other than 1 and themselves. The set of Mersenne primes is
assumed to be infinite
though this remains unproven, yet.
Let us first define some helper functions. range(from, to) and forall() are
common helpers in functional programming languages. range() returns the set of
natural numbers in a given range. forall() returns whether the given predicate
holds for all items in the sequence and should therefore only be used for finite
sequences.
mersenneNumbers() is the set of all numbers of the form Mn = 2n - 1.
isPrime() is a very simple and naive (and slow) primality checker that returns
whether the given candidate is divisible by any of the numbers in the range of
[2, candidate - 1]. We will use isPrime() as a filter to remove all non-prime
numbers from mersenneNumbers().
functionmersenneNumbers(){returnmap(nat(),x=>Math.pow(2,x+1)-1);}functionmersennePrimes(){functionisPrime(n){returnforall(range(2,n-1),x=>n%x);}returnfilter(mersenneNumbers(),isPrime);}varit=mersennePrimes();console.log(it.next(),it.next(),it.next());// prints 3 7 31
Flattening
As a last example we will implement a function that flattens nested sequences.
Combining flatten() and map() to flatMap() we can implement another very
common function that flattens the result of applying a given function to all
items of a sequence. Let us use it to re-build the set of all natural numbers
from the set of all even natural numbers.
functionflatMap(it,f){returnflatten(map(it,f));}varit=flatMap(even(),x=>[x-1,x]);console.log(it.next(),it.next(),it.next());// prints 1 2 3
Generators are powerful
It is quite obvious that studying ES6 generators really repays. They are a very
powerful language construct and I personally cannot wait until they are
available in V8/Node.js as well. They will be in the toolbox of every
professional JavaScript developer soon and I am sure we can count on the
community to come up with lots of great uses and libraries.
You have probably already heard of
generators and iterators
coming to a browser near you. They have been available in Firefox for a long
time and are used extensively all over the Mozilla code base. The V8 team
will implement iterators and generators
once ES6 has been finalized.
This post describes the current implementation in SpiderMonkey and tries to
include the current state of the ES6 draft and discussions.
A simple generator
Let us take a look at a simple example of a generator function that represents
an infinite sequence containing all the numbers from 0 to Number.MAX_VALUE.
Once it reaches MAX_VALUE it will not increase any further but always return
the same number.
The next() method simply returns the item next in the sequence.
Finite sequences
As you surely noticed the generator of the first example produces iterators that
will never run out of items. The next example shows an iterator representing a
finite sequence:
The given code implements a custom iterator without writing a generator
function. Note that it throws StopIteration as soon as it reaches the maximum
value to signal that the sequence is exhausted. It is a lot more elegant to
implement the same sequence using a generator function:
Generator functions will automatically throw StopIteration when terminating.
So how should one consume iterators with finite sequences?
Consuming sequences
In Java for example, you would check iter.hasNext() and stop when it returns
false. In JavaScript however you need to use a try…catch statement to catch
StopIteration when it is being thrown.
You might wonder if there is a better way to do this and indeed there is. Using
for…in or for…of you do not have to catch StopIteration yourself, the
JavaScript engine will do it for you. As soon as the sequence is exhausted the
loop will terminate normally without the exception being propagated:
StopIteration actually is a standard variable that is bound to an object of
class StopIteration. It is an ordinary object with no properties of its own
and it is not a constructor function.
try{throwStopIteration;}catch(eifeinstanceofStopIteration){// This works because:StopIterationinstanceofStopIteration===true;}
As StopIteration is a singleton of type StopIteration you can also catch it
by checking for equality:
You should be aware that StopIteration is a mutable global. Just like
undefined it can be modified to hold any other value. If you write a library
and want to shield against modifications from outside you can use this neat
little trick I found on
Dave Herman’s blog:
The inner function is a generator that terminates immediately and therefore will
throw a StopIteration. The outer function simply catches and returns it.
StopIteration may become a constructor
The current
iterator strawman
states that StopIteration will become a constructor to maintain compatibility
with generator functions returning values.
The equality check from above would not work anymore so it might be better to
just use instanceof.
StopIteration may not be part of ES6
The Python way of throwing to denote the end of a sequence is backwards
compatible with old ECMAScript versions but there seem to be
peoplenot happywith the current proposal.
While I can’t tell whether StopIteration is really to be removed a couple of
alternative suggestions have been made:
Introduce a keyword to end a frame
To not misuse exceptions for normal control flow ES6 could introduce a
stopiteration or endframe keyword that would end the current frame with
an optional return value. The obvious downside is that it is probably not
backwards compatible.
Iter.prototype.next=function(){if(this.cur<this.max){returnthis.cur++;}stopiteration[reason];// or endframe [reason];};
Add an iterator.hasNext() method
Just like Java the iterator API could consist of the two methods next() and
hasNext(). The client would then need to check hasNext() every time before
calling next().
Custom iterators would be required to implement a single method but would not
need to throw. Instead they would return an object with the property done set
to true to indicate that the sequence has ended. The value property would be
used to store values passed to yield or return in a generator function.
This is in no way a complete list of possibilities or proposals that were
brought up on es-discuss so
please make up your own mind about the current iterators implementation and the
suggested improvements.
The future is bright
Whether or not StopIteration will end up in ES6, generators and iterators are
great and you should make sure to be prepared when they become available in
modern browsers as well as on Node.js.
I concentrated particularly on StopIteration but there are
lots ofgreatposts
out there that go way more into depth about generators and their usage. Make
sure to also take a look at libraries like Task.js that
combines generators with promises to cooperative tasks.
1 year ago, I started a spreadsheet. For 9 months we’d been rewriting Firefox for Android from the ground up, and on May 16, 2012 we released the first beta version to the Android market. I started a spreadsheet to track our star rating. I was nervous.
9 months of rewrite. In web time— in mobileweb time— that’s years. Rewrites are almost always the wrong call. You get to throw away bad code, but you throw away good code, too. Hard won, battle-hardened fixes are expensive to throw away, and the code is never cleanly labelled “baby” and “bathwater.” The decision to rewrite Firefox was one of the loudest weeks I’ve had. Even once we’d decided, my hand hovered over the send key for a long time.
3.5 stars. We didn’t pull the old version from the market during the rewrite. We wanted to keep those users safe with regular security updates; that meant keeping the product online. It meant taking black eyes every day from users who tried us, who loved us for our desktop product, and who were disappointed. And because the Android rating system rounds, our already painful 3.7-star rating rounded down to 3.5. We were dead last.
7:1. If you want to maintain a 4.5 star rating, it takes seven 5-star reviews to counteract each 1-star review. Star ratings are deeply flawed for all kinds of reasons: selection bias, survivorship bias, false dilemmas, unidimensionality, reporting bias, et cetera. I know this. And still I watched them. When you try to reach people through an app store, your star rating is the first assessment of your product they’ll see. And when you try to make something great, reviews are real pieces of feedback from real human beings and they are painful and they are frustrating and they are golden.
1181 reviews in the first week. 588 of them were 5-stars. 105 of them were 1-star. I argued with my screen over 1-star comments about bugs we had already fixed. I swooned at 5-star reviews that said they were reversing earlier 1-star reviews.
6 weeks after beta, we pushed to release. By this point beta had climbed to 3.8, which rounds to 4 stars. Fists were pumped. Release sat at 3.6.
Time passed.
200,000 reviews and 6 releases later, this week, today, Firefox and Beta both show 4.5 (rounded) stars in the market and the team is still going strong. I’m immensely proud of the work they’ve done. It’s made me reflective and maybe a bit wordy. I want to have some profound and pithy lesson to separate then and now. Something that I can package up and hand to you. We certainly learned lessons, profound lessons, but in repeating them they sound trite:
Listen. Care about what people think. Be hungry for feedback. Don’t work forward from the tech you have to the product you can build; work backward from the product your users deserve to the tech you’ll need to get there. Ask for help, and accept it even when it hurts to admit that you need it. Don’t throw things away lightly, but be able to throw them away in those rare cases where it’s necessary. Surround yourself with the most excellent people you can find. That one helps a lot.
The haters will say I over-focus on star ratings. There are certainly lots of other good things to measure, and lots of bad things to say about stars. But the stars abide. They are inescapable. They sit front and center in your primary distribution channel. Those five little stars. And I believe they do say something about what we’ve built.
Building good things is hard and my hat is off to anyone who earnestly tries. If the good thing you build reaches people through an app store, I want you to know that I know how you feel. And I’m rooting for you.
While the rapid release trains provide a very good userbase for testing a feature, it's only at the release time that the "real world" feedback allows to prioritize improvements. Unfortunately, at that time, there's the concrete risk of a disconnection:
the user sends valuable feedback
the development team is already busy on something else
Thanks to the open and transparent nature of the Mozilla project, the feedback is never lost, very often it naturally converts to bugs and discussions. On the other side this disconnection may cause a delay before actionable items are created.
Thus I decided, after the release, to collect the most common feedback about the new download experience and setup a meeting with people involved in its development, to work toghether towards a plan. I went through bugs, input.mozilla.org, comments to IT articles, Mozilla newsgroups, and forum discussions, extracted the most common topics and put them on the discussion table.
I'd like to point out this is not an exotic behavior at all, persons involved in development do read feedback and are active part of the community, there is also a User Research dedicated team. Though, it is worth writing this tale to clarify that what is sometimes confused with "indifference", is instead the unavoidable challenge of satisfying a large, heterogenous and passionate community.
What came out of that is a very concrete list of things we can do. Please forgive me if I don't go too much into details for each item, I'm still in the process of adding required information to bugs. Also notice many more suggestions were evaluated, this is a filtered list.
Priority improvements:
Notify ongoing downloads when closing the browser (bug 851774) [code]
Increase number of downloads in the panel (bug 780837) [ux]
Reintroduce speed for each download (bug 812894) [ux]
Make multi-selection commands work properly (bug 844606) [code]
Properly handle removed files in the UI (bug 726451) [code]
Improve tooltip of the download button with a summary [code]
Evaluate adding more command buttons to the Library view (bug 862528) [ux]
Now, to the bad news: we are low on resources. Clearly everyone has many projects to follow, we'll try to dedicate available time to these changes, but we'd like having some help from the community. So, if you are able in javascript, xul and css, your help will be very welcome. I've added a status near each item, indicating the current needs, those having [code] are already well defined and can be worked on, the others will be defined in the next days.
The Google Summer of Code 2013 project is about to get started: today the application submission period officially starts (and is open until May 3). Mozilla is again a participating org, and students can find a list of project ideas and application advice in our Summer of Code wiki page. It’s important to remember that the list on the wiki is for possible ideas, but students are not limited to those on the list: project proposals with your own ideas are also welcome. With this disclaimer in mind, I’d like to describe in a bit more details some of the projects that we from the Firefox team have included on the list, and to answer some of the more frequent questions that we have received through e-mail and IRC about them. If you’re a student interested in one of those, read on. I wrote a blog post for each of them:
To make a good proposal, it’s important to keep in mind the goals and non-goals of the project, to demonstrate that you’ve understood how to approach the implementation of the project, and that you’re capable of doing so. It’s also important to create a solid schedule of deliverables that are used both to guide the steps of the project and to validate the pace and the progress up until that point. I’ve already written enough about the specifics and there’s a lot of content out there explaining what makes a good candidate and a good proposal, so i’ll keep this post brief.
Just as a last note, if you’ve sent us e-mail or pinged us on IRC, please be patient because we’re not online all the time or available to immediately reply, and so far we have seen a lot of interest in GSoC, so it takes us a while to reply to everyone’s emails. We hope that these blog posts will help more students to clarify some common questions about our proposals. Good luck to everyone, and remember that you’re always welcome to contribute to Mozilla, during the Summer of Code and every other season too
This entry is part of a series of posts about some of our proposed GSoC projects. See here the introduction blog post.
about:memory for real people
What is it: about:memory is a tool that is used by Firefox developers to diagnose and understand the memory usage behaviors of the browsers. It has been immensely useful for us to find bugs in the MemShrink project and validate the fixes to those bugs. However, it is too focused on Firefox’s internals for the browser developers, but the available data there could be presented in different ways to also help web developers and regular users who wants to understand how each website consumes memory.
Example use case: User opens the new about:memory and sees that website A (tab 1) is taking 15mb and website B (tab 2) is taking 12mb. After 30min, the user opens the tool again, now to see website A still taking 17mb and website B taking now 30mb. They then can conclude that website B is consuming more memory as time passes, while website A is able to maintain its memory requirements steady.
What does it involve:
looking into the current about:memory and understanding the existing data available and its breakdowns
proposing various different ways to visually present that data and interact with it (e.g., sorting, time slicing, merging tabs from the same domain, animating data over time, etc.)
proposing an existing open-source JS dataviz graphics library to be used for the project
interact with the Firefox developers who work on memory optimization and provide feedback for more data that would be useful if it were available
should be done as an add-on using the Add-on SDK
Non-goals: This project will not remove the existing about:memory, but will create a new one. Also, you should not try to create your own graphics library as part of the project, as there’s not enough time available to do both things during the official schedule.
Where to start: You should start by looking into the current about:memory and its code and to understand how data is retrieved from the memory measurements code. You then need to analyze the available data to undestand its meaning and start thinking on how you want to present that in a more visually interactive way. The usage of the Add-on SDK will also be required but will be very limited to packaging and setting up the add-on, as the main code will be a simple html page that implements your new about:memory (along with its supporting CSS and JS files).
Skills needed: JavaScript and CSS skills, and experience with data visualization. Experience with one JS graphics library would be great.
What is expected in your project proposal: A great understanding of the project, its goals and non-goals, and a good idea on how to approach each of the features involved and how to time slice them. A proposal for at least 4 different ways to visualize the data, describing what type of graphs will be used and the possible interactions that it will provide. The selection of the graphics library to be used. Links to open-source code (e.g. a github profile) that you have produced (specially ones involving data visualization).
Last week I attended a community building meetup in Toronto, where I had the opportunity to meet with individuals who are driving volunteer participation across different areas of the Mozilla project. Together we discussed the things our teams are doing to engage volunteers, and we brainstormed ways that we can continue to grow Mozilla. These discussions gave me lots of ideas about what we can do to grow our Firefox for Android community, but most of them boiled down to three main points.
1. Improve communication. The first part of getting involved in a project is figuring out what’s going on. Our team tends to have lots of discussions on IRC and in Bugzilla, which is great if you’re following those channels closely, but it can be hard for a casual observer to keep up. We’re already trying to address this issue with a new mailing list for development discussions, as well as Twitter and Tumblr accounts for more lightweight updates. Mark Finkle just wrote a blog post covering these communication channels in more detail.
2. Diversify opportunities. When newcomers show up, we help them set up a build environment and point them at a list of mentor bugs. This is a great way to get started, but it doesn’t provide a path to becoming a core contributor, or a path toward other types of contributions. I’d like us to encourage more advanced contributions, such as helping debug difficult crashes, or working on bugs that will help us complete a feature we’re targeting for a given release. I also want us to do a better job advertising all the different ways someone can contribute to Firefox for Android, especially testing and support. Our “Get Involved” page mentions some of these opportunities, but there’s probably more we can do.
3. Manage expectations. Even though we do our best to make it easy, writing a patch is hard. New contributors need to remember that it can take a significant amount of effort to get a patch accepted, and core team members need to remember that it takes time for newcomers to develop the knowledge that we often take for granted. We also need to recognize that newcomers are volunteering their time to help improve Firefox, and that mentors are volunteering their time to help grow our community. It’s a lot of work all around, but no one ever said open source software was easy!
Tilt, or 3D view as it is known in Firefox, is an awesome visual tool that really lets you see the structure of a webpage. It shows you just how deep your tag hierarchy goes which might give signs of your page being too complex or even help you spot errors in your markup that you wouldn’t otherwise notice. But what if it could do more? What if there were different ways to visualise the same page? What if even web developers could create their own visualisations?
I’ve had this idea knocking around in my head for a while now and the devtools work week was the perfect time to hack on it. Here are some results, click through for larger images:
Normal 3D view
Only give depth to links
Only give depth to links going off-site
Only give depth to elements that have a different style on hover
This is all achieved with some changes to Firefox itself to make Tilt handle more generic visualisations along with an extension that then overrides Tilt’s default visualisation. Because the extension has access to everything Firefox knows about the webpage it can use some interested sources of data about the page, including those not found in the DOM. This one I particularly like, it makes the element’s depth proportional to the number of attached DOM event listeners:
Give depth to elements based on the number of attached event listeners
Just look at that search box, and what’s up with the two buttons having different height?
The code just calls a JS function to get the height for each element displayed in 3D view. It’s really easy to use DOM functions to highlight different things about the elements and while I think some of the examples I made are interesting I think it will be more interesting to just let web-devs come up with and share their own visualisations. To that end I also demoed using scratchpad to write whatever function you like to control the visualisation. You can see a screencast of it in action.
Something that struck me towards the end of the week is that it could be awesome to pair this up with external sources of data like analytics. What about being able to view your page with links given depth proportional to how often users click them? Seems like an awesome way to really understand where your users are going and maybe why.
I’m hoping to get the changes to Firefox landed soon maybe with an additional patch to properly support extensibility of Tilt, right now the extension works by replacing a function in a JSM which is pretty hacky, but it wouldn’t be difficult to make it nicer than that. After that I’ll be interested to see what visualisation ideas others come up with.
If I told you that a company is shipping a product to hundreds of millions of users right now, and included in the product are several prominent buttons that will break the product completely if you click them, and possibly lock you out from the Internet — can you guess which product it is?
Sounds like that’s the kind of product that only a large enterprise software company like Oracle or IBM would ship, right? Maybe some of the antivirus extortionware software for Windows? Maybe VPN software?
Well, we have met the enemy, and he is us.*
In the currently shipping version, Firefox ships with many options that will render the browser unusable to most people, right in the main settings UI.
How did we get to this point with Firefox? Most of these options exist for historical reasons — whenever there’s a new feature, it often gets a checkbox to turn it off. The other common case is when a feature isn’t obviously useful to everyone, and it’s hard to make an obvious choice about whether to have it enabled by default or not — so we build in a switch. Or sometimes the person implementing it thinks it should have a switch, and nobody stops to ask if it’s a good idea.
I’m not going to retread discussions about this, there are many versions of that article across the web — the main point is that it is usually a failure of design, and a failure to agree on sensible default behaviors. Options are “the cheap way out,” and they usually speak to an inability to agree on what to do in a given situation.
Design by committee often looks like a row of checkboxes.
What I do want to put the focus on, however, is that you have to perform an audit of your product every so often and see how the people using your product have changed, and what kind of functionality that made sense at the time may not make much sense anymore.
Of course, we should start in our own backyard, so here are some obvious examples from Firefox. These are things we need to fix:
Load images automatically
From the Content panel in our settings, try unchecking the box:
Here’s how Google’s front page looks like if you uncheck that box:
That’s right, you can’t even see the text box you’re supposed to type your search into. Congratulations, we just broke the Internet.
Of course, there are legitimate uses for this, from low-bandwidth situations to web development testing, but that’s where our excellent add-ons ecosystem comes to the rescue. Are more than 2% of our users likely to use this setting on a regular basis? Probably not.
Enable JavaScript
More fun from our Content panel, you can turn off JavaScript with a simple click:
Try booking a travel on Hipmunk without JavaScript:
Most sites these days that aren’t just displaying content will fail in interesting & mysterious ways if you don’t have JavaScript enabled. For the general population, Firefox will appear broken.
Fun historical fact: If you disabled JavaScript in Netscape 4, CSS would also stop working — because CSS was applied to the page using… JavaScript.
And yes, I know that some people have reasons (privacy, web development) to turn off JavaScript. There are many add-ons that can help with this — but it’s not something that we should ship to hundreds of millions of users.
Turning off navigation
Firefox is very customizable! In fact, it’s so customizable that we allow you to make the browser unusable with a single click. Try turning off the Navigation Toolbar, for instance:
Good luck trying to find a web site that can help you fix this problem when your son was clicking around the menus in Firefox yesterday, and today your browser has no buttons:
Turning off SSL & TLS
Now we’re getting to the “shooting fish in a barrel” category — there are many fun options in this preference panel:
If you turn off SSL or TLS, Gmail, Google Reader, and other Google services will look like this:
Note that we don’t even tell you that you can turn it back on in the settings. We just tell you that it has been disabled, and that you should “contact the website owners to inform them of this problem.”
Good luck trying to do that when you can’t even see the web site or load your email.
The entire certificate manager
Oh boy, where do we start?
Personally, I feel pretty confident that the number of people that know how any of this works can be narrowed down to the people that work in these companies in the list. At least not too far off.
This entire thing — possibly with the exception of the personal certificate list — needs to be moved out into an add-on for people with interest in managing their own certificates. It’s our job as a browser to keep you safe, we shouldn’t outsource this to individuals.
You probably don’t want your bank to look like this because two days ago, you read an article on the Internet — authored by who-knows — telling you to remove an entry in your certificates “for added safety”:
Also, is that an NSS Internal PKCS #11 module in your pocket, or are you just happy to see me? Do I need to enable my FIPS?
On the flipside, from that same article: how many users have we broken the web for when 1.6% of them may have TLS support turned off, and possibly not be aware of it? Even 1% of a few hundred million isn’t a trivial number of people.
The people that need to do these things should use add-ons, or at the very least an about:config tweak.
Override automatic cache management
Another way to slow down the browser and make Firefox look bad is to give it no disk space to use for caching:
What about computers with very little disk space? Shouldn’t you be able to restrict how much disk space is being used? It turns out, we know that you are low on disk space, and will reduce our usage accordingly. It’s pretty likely that Firefox keeps better track of this than humans do. So let’s make computers do what they’re good at: keeping track of numbers.
So what have we learned? There are a lot of options in our products that are used by very few people, and some of them can have disastrous effects. We’re trying to design software that can be used by everyone — that also means we have to keep them safe and not make it so easy to break a product they rely on every day. None of these are put there with malicious intent — some of them even made sense at the time — but it’s time for us to do some scrubbing and cleaning of the Firefox settings.
What about the product that you are building? Is it time to take a fresh look at what kind of options you include?
Thanks to Frank Yan, Blake Winton, Tony Santos, Monica Chew, Sid Stamm & Madhava Enros for reading drafts of this.
I want to make a point about changing the world, but first we need to talk about the horse head.
For Christmas last year I bought my brother a horse head and, while I was at it, picked one up for the office. It felt like the kind of thing that Mozilla Toronto would enjoy.
Between meetings we needed a place to store it; the sad, flat way it sort of collapsed when left on a desk was unsatisfying. So Madhava and I went out in search of a head on which to mount it. Steps from our office is a mannequin supply store, which helped.
I put the horse head on its styrofoam mount and, for giggles, set it up in the window. Facing outwards. Staring at the office in the next building.
For 2 weeks it sat there and I was pretty happy with it. And then something happened. Something wonderful and magical happened. I wasn’t there for it, but lmandel and overholt were.
So last week we bought them their own horse head. And yesterday mconley delivered it to their office. They invited him in. They brought the box over to the window where we could see. They gathered around their window and we gathered around ours. And when they opened it and realised what it was they actually jumped up and down, and applauded, and mouthed “thank you” through the window at us.
In Bowling Alone, Robert Putnam’s utterly definitive work on society and community, he writes that the best predictor of a school’s success is the activity of its PTA, and that the activity level of a PTA can be changed dramatically by one or two committed parents. Derek Sivers’ TED talk is all about the powerful change that happens when one person being silly becomes two people being silly, and cognitive scientists have been talking about the power of allies for 50 years.
The horse head(s) didn’t change the world; I’m not that pompous. But changing the world is hard work and it’s worth getting some practice in. So go start something. And, this is crucial, if you see someone else starting something: play along. Maybe the thing you’re playing with draws a great big crowd and changes the world. Maybe it never amounts to more than an office of strangers 50ft away silently jumping up and down and saying thanks.
It’s not such a terrible downside.
UPDATE: The world keeps getting more awesome. Denise from the other office just sent me email saying that the 4th floor office in our building saw their “best day ever” sign, and posted a reply. They don’t even know about the horses. They just wanted to share in the happy.
and tomorrow will be even better (photo credit: denise)
It's often hard to write cross-platform code for console coloring, and for mach there have not been exceptions. It colorizes build and tests output, so that you can easily scroll and find warnings and failures, but unfortunately only on Unix consoles.
We are not new to this kind of issues in the Windows build environment, and there's a bug filed to properly support that, though, in the meanwhile, we can apply the same trick used with pymake to get colorization on mach. Kudos to Shawn Wilsher and Justing Dolske for first implementing this idea with pymake, now let's also colorize our mach build!
First of all, you need a version of sed that supports the unbuffered option, download it from the update sed in mozilla-build bug and copy it to the msys/bin folder in your mozilla-build install path.
Then you need a .profile file in your user home folder, for example for me it's C:\Users\Marco\.profile, then just add this code snippet into the .profile file:
At this point, just close and reopen the console (fwiw, I use console2 and these steps are just tested there) and you should be able to just execute mach build browser and get this nicer output, instead of a wall of white text:
You are free to use, modify and adapt the rules and coloring to your needs, if you have improvements you can drop me a mail or ping me on IRC, the latest version is on my wiki page.
Now that you should already know how to build a
live green screen
and an
EyeToy-like mini-game
using nothing but plain JavaScript and a modern browser supporting WebRTC, let
us move on to another interesting example: simple motion detection in a live
video.
The initialization code
To detect motion in a video we need to compare at least two frames. We will use
typed arrays
to store the lightness data of the previous frames:
functioninitialize(){// ... code to initialize the canvas and video elements ...// Prepare buffers to store lightness data.for(vari=0;i<2;i++){buffers.push(newUint8Array(width*height));}// Get the webcam's stream.nav.getUserMedia({video:true},startStream,function(){});}
We want two frame buffers - a single one results in a heavily
flickering motion video but the more frames we store the more motion blur
we will see. Two seems like a good value for demonstration purposes.
Illustrating lightness changes
The main draw() function from
part 1
did not change except that we now call markLightnessChanges() for every frame.
This is also the probably most interesting function of the whole demo:
functionmarkLightnessChanges(data){// Pick the next buffer (round-robin).varbuffer=buffers[bufidx++%buffers.length];for(vari=0,j=0;i<buffer.length;i++,j+=4){// Determine lightness value.varcurrent=lightnessValue(data[j],data[j+1],data[j+2]);// Set color to black.data[j]=data[j+1]=data[j+2]=0;// Full opacity for changes.data[j+3]=255*lightnessHasChanged(i,current);// Store current lightness value.buffer[i]=current;}}
We determine the lightness value of every pixel in the canvas and compare it
to its values in the previously captured frames. If the difference to one of
those buffers exceeds a specific threshold the pixel will be black, if not it
becomes transparent.
The simple method we use to detect motion is called a
blend mode difference.
That is a quite fancy word to say: we compare two images (also called layers
or frames) by putting them on top of each other and subtracting the bottom from
the top layer. In this example we do it for every pixel’s L-value of the
HSL color model.
If the current frame is identical to the previous one, the lightness
difference will be exactly zero for all pixels. If the frames differ because
something in that picture has moved then there is a good chance that lightness
values change where motion occured. A small threshold ensures that we ignore
noise in the signal.
Demo and screencast
That is all! Take a look at the live demo or watch
the screencast below:
You can create some really great demos with this simple technique. Here is a
neat one of
a xylophone you can play by waving your hands
(which unfortunately does not work in Firefox).
Whatever your ideas may be, I encourage you to fiddle around with the small
demos I provided in my three getUserMedia() examples so far and let me know if
you built something amazing!
For several years now, the Firefox project’s official development discussion forum has been mozilla.dev.apps.firefox. It has served us well, but I don’t really ever recall it being an optimally useful tool for development discussions.
I think there are a few reasons for this. I think the primary reason is that the list does not have a moderation policy. We don’t have one partially because it is hard to do given the tools we are using (a custom mash-up of NNTP, Google Groups and a mailman mailing list), but also partially because Mozilla discussion forums have just not traditionally had them. Given the size and diversity of the Firefox user base and community, no moderation means that inevitably there are posts from users seeking support, abusive posts from people upset with our decisions, or off-topic/bike shed threads that dragged on forever and didn’t end up anywhere useful. The combination of these results in a mailing list with a low signal-to-noise ratio, that many core Firefox contributors either don’t read at all, don’t follow closely, or need to filter aggressively. That’s a poor situation to be in, and often means that some of our development discussion ends up occurring in other less accessible, less reference-able venues (e.g. on IRC, or in video meetings).
Three years ago, the Thunderbird folks saw many of these same issues with their development forum, and came up with a solution in the form of tb-planning. That list and its policies have succeeded in creating a more productive and useful venue for discussion. So I’d like to try the same experiment for Firefox development.
firefox-dev is a new list whose goal is to offer an easy, transparent venue for getting constructive, Firefox-related development work done. Some members of the Firefox development team have already started using the list to that end. Its moderation policy has been shamelessly stolen from tb-planning. For the moment, it will co-exist with mozilla.dev.apps.firefox. It’s a mailing list only (no NNTP mirroring update: there’s an NNTP read-only mirror provided by gmane), but the archives are also available (read-only) via Google Groups.
If you’re interested in following or contributing to our development discussions, please subscribe to the new list!
Back in October 2012 I wrote two blog posts,
getUserMedia part 1
and part 2,
including demos which unfortunately would run in Firefox, only. I did not
explicitly want to be exclusive but I think I just did not feel like looking up
why my code did not work in Opera and why exactly webkitGetUserMedia() behaved
differently than mozGetUserMedia(). I was being lazy.
I also intended to mix in a couple of nice JavaScript features, like
block-scoped variable definitions with
let,
destructuring assignments
or Sets
(did I just do it again?). In hindsight this does not really make sense as I
should not expect visitors to want to learn about cutting-edge JavaScript
features when viewing a getUserMedia() post.
Before finishing my third piece on getUserMedia() I decided to update the demos
of my older posts to run in any modern browser. I also seized the chance to
overhaul code examples which did not adhere to my coding standards anymore.
If you should ever be in a similar situation - please take a couple of minutes
to write code that runs in all modern browsers so people can enjoy your demos in
their browser of choice. Please don’t be lazy.
You’re three. You can count, you can sound out words with help, and you can sing. Thanks to your mom you’re a big fan of Mary Poppins and thanks to me you’re a big fan of O Brother Where Art Thou but I think you still sing mostly to Raffi and One Direction. For One Direction you also dance, which involves more hip motion than I’m really comfortable with.
You seemed to understand Halloween and Christmas much better this year, and you definitely understand your birthday. You want 3 star-shaped candles on your cake. You want star candles because your mom put glow-in-the-dark stars on the ceiling of your room. Every night when I put you to bed we turn off the lights and we sit in the rocking chair and we stare at the stars and talk about which one is your favourite. It’s basically the best thing ever.
You’re developing complex thoughts and emotions now at a dizzying pace. Like “awkwardness of forgetting someone’s name.” You try to remember, wrestle with it visibly, and then call them, “that one,” quietly, half-embarrassed. “Patience with daddy clearly being an idiot” is another one that’s coming along nicely.
The one that stopped my heart, though, was a story from day care. You’ve been in day care for 6 months, and I wondered how it would go since it was your first real socialization with other kids outside of occasional visits. It’s a big day care with a different groups for different ages. A month or two ago, a new boy came in to the group next to yours in the facility. He was pretty sad on his first day and, during naptime, he was lying on his mat and crying. Your mat was nearby, on the other side of a half-height dividing wall. When your daycare supervisor walked over, she saw that you were awake, and speaking softly to him through the wall saying,
It’s okay. You don’t need to cry. Your mommy will come back. Mommies and daddies always come back.
You break my heart, kiddo, in all the very best ways. Happy birthday. I love you I love you I love you.
You may have noticed that lately I've been somewhat absent from, uh, everything. Dead to the world for most of December, and just brief ghostly appearances so far in January. I've posted a couple of times on Twitter about why, but I wanted to write something a bit more substantial about it all, now that I'm able to do so. Thus begins my tale of woe and boredom…
Once upon a time (1st December 2012), in a land far far away (New Zealand), there lived a great bearded wizard (that's me), tormented by an evil troll.
Ok, so that's not a troll — it's our old garden shed. Although I do consider it to be slightly evil now.
Notice the grape vine creeping up the trellis; I was attaching the trellis to the wall of the shed one bright Saturday afternoon. I bent down to pick something up, stood up and turned around, and in a fit of bloody revenge the shed viciously attacked me. Or I may have just hit my head on the corner of the shed — I don't specifically remember that part. I vaguely remember feeling well enough afterwards to finish the job and clean up; though afterwards I did need to retire inside for a rest on the couch, then have an early night.
Sunday morning was quite the opposite of “feeling well enough”. “Awful” is a much more accurate description. I'm usually very resistant to see any doctor, but I got there as soon as I could on Monday. The medical field seems to involve a lot of inexact science (or as I like to call it, “guessing”), and my doctor's best guess was a pinched nerve in my neck and a concussion. I knew very little about concussions, but my doctor warned me to stay away from computer screens and books.
Now, I'll admit to a fair amount of ignorance here, as at this stage I expected to have an easy (if somewhat boring) time and be back at work after a week. Obviously, that didn't exactly go to plan.
In fact, I was so wrong that on Tuesday Anne and I planned to take a trip out of town (Anne driving, of course) so I wouldn't be completely bored out of my mind. We got as far as the emergency department of the hospital. Nothing serious, but I did learn that even sitting as a passenger in a moving car was enough to bring on some very worrying symptoms. Confusion, disorientation, difficulty focusing attention, blurry vision, double vision, atrocious headache, nausea, etc. All of which turned out to be normal, for a concussion — but nevertheless scary to experience.
I think most people don't have much of an understanding as to how a concussion (or any brain injury) can affect a person. I certainly didn't. This lack of understanding, and the types of symptoms and limitations, can be very isolating. As it turns out, being a programmer involves doing everything that you're not allowed to do when you have a concussion:
In front of a screen
Reading
Concentrating
Thinking
Yea, really — I was pretty much banned from thinking. And for good reason — thinking made my head feel awful. Interestingly, I was also banned from doing much physical exercise. I found I was very easily physically exhausted, as well as mentally exhausted. Conversations with people overloaded my brain very easily, and I couldn't cope at all with listening to groups of people. Both the mental and physical symptoms are caused by what's called neurogenic fatigue — which apparently is remarkably similar to sleep deprivation. And so the trouble with a concussion is that you can't push yourself to recover faster — it just ends up making things worse.
So I was stuck for most of December trying my best to do as little as possible. I plan on writing a separate blog post about this, but it's actually quite difficult to do nothing — really do nothing. I spent a lot of time sleeping, or laying on the couch or outside trying to keep my mind blank. Some forms of meditation worked, but many involve too much concentration. Most days I had a short trip into a quiet café somewhere — I've never been in cafés so often before in my life. Needless to say, it was a remarkably boring time. But thankfully this was during a very pleasant New Zealand summer, which permitted plenty of time lounging in the sun and quiet walks along the waterfront of St Clair beach (yea, such a hard life).
Oh, and of course it helped having my attentive friend Harley keeping me company:
On 18th December I was given the all-clear to start slowly returning to normalcy. On 3rd January I was told I could start reading work email for an hour, spread out over a day, every second day. It took me until 1st February to build up to being able to work half a day, albeit still not coding. If this seems slow, it was — agonisingly slow.
It's 14th February now (for me, at least - yay timezones) and I'm still doing roughly half days, but building up what I'm doing. So I'm finally getting through my review queue, some technical reading, and generally catching up on things I missed. Hopefully I'll soon be able to get back into some serious coding, help finish that little project I started last year, and generally be back into my normal routine. In the meantime, I'm a delicate little flower, so please don't bury me with too much work :)
While planning a workshop for Dare2BDigital, a technology conference for young women, Lukas and I were looking for an easy way for girls to edit and test their own Firefox OS apps. We were trying to think of where we could host these apps when we decided to try using Github pages.
I’d never actually made a Github page before, but I learned it’s as easy as making a magically named “gh-pages” branch in your repo. To experiment, I decided to test this out on a simple wallpaper app I’ve been working on.
And voila! My app showed up at http://leibovic.github.com/mural/. This seems great for development because you can just push changes to the gh-pages branch to update a hosted app. But as a bonus for our workshop, we found you can easily modify the app by hitting the “Edit” button at the top of a file on Github, then committing your changes through the web interface.
Note: After the first push it can take up to 10 minutes for the page to appear. So be patient.
We’re now a big step closer to shipping the SDK APIs with Firefox and other apps, we’ve uplifted the SDK code from our git repository to mozilla-inbound and assuming it sticks we will be on the trains for releasing. We’ll be doing weekly uplifts to keep the code in mozilla-central current.
What’s changed?
Not a lot yet. Existing add-ons and add-ons built with the current version of the SDK still use their own versions of the APIs from their XPIs. Add-ons built with the next version of the SDK may start to try to use the APIs in Firefox in preference to those shipped with the XPI and then a future version will only use those in Firefox. We’re also talking about the possibility of making Firefox override the APIs in any SDK based add-on and use the shipped ones automatically so the add-on author wouldn’t need to do anything.
We’re working on getting the Jetpack tests running on tinderbox switched over to use the in-tree code, once we do we will be unhiding them so other developers can immediately see when their changes break the SDK code. You can now run the Jetpack tests with a mach command or just with make jetpack-tests from the object directory. Those commands are a bit rudimentary right now, they don’t give you a way to choose individual tests to run. We’ll get to that.
Can I use it now?
If you’re brave, sure. Once a build including the SDKs is out (might be a day or so for nightlies) fire up a chrome context scratch pad and put this code in it:
var { Loader } = Components.utils.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
var loader = Loader.Loader({
paths: {
"sdk/": "resource://gre/modules/commonjs/sdk/",
"": "globals:///"
},
resolve: function(id, base) {
if (id == "chrome" || id.startsWith("@"))
return id;
return Loader.resolve(id, base);
}
});
var module = Loader.Module("main", "scratchpad://");
var require = Loader.Require(loader, module);
var { notify } = require("sdk/notifications");
notify({
text: "Hello from the SDK!"
});
Everything but the last 4 lines sets up the SDK loader so it knows where to get the APIs from and creates you a require function to call. The rest can just be code as you’d include in an SDK add-on. You probably shouldn’t use this for anything serious yet, in fact I haven’t included the code to tell the module loader to unload so this code example may leak things for the rest of the life of the application.
This is too long of course (longer than it should be right now because of a bug too) so one thing we’ll probably do is create a simple JSM that can give you a require function in one line as well as take care of unloading when the app goes away.
This is a re-post from mozilla.dev.extensions to try to reach a broader add-ons developers public.
Dear add-ons developers, as part of our goal to make history and bookmarks asynchronous, we are starting removing some APIs, that in the last years have been replaced by new asynchronous ones. We are currently removing the last uses in the tests harness, but we are not too far from the target. Current goal is Firefox21.
Please let me know (either in the newsgroup or in the bug) if you have doubts, or part of these changes should be blocked for major problems, or there's some use-case you need that is not well-covered by the new APIs.
Fade in.
She: You stop shaving?
He: Yep.
She: Like, your mustache? The charity thing?
He: No, that’s Movember. Which is awesome. But different.
She: So you don’t shave at all?
He: Right.
She: For a month?
He: No Shaving in December. Right.
She: Ew.
A brief pause.
She: Why? Because some guy on the internet told you to?
He: He… no. I mean. That’s how I found out about it. But that’s not why.
She: Why then? Doesn’t it itch?
He: It itches for a while. That’s part of the whole thing.
She: Part of what whole thing? Why put yourself through that?
He: Just because. Don’t worry about it.
She: No. No way. If have to live with it for a month, I want to know why.
He: No. Anyhow, you’ll think it’s silly.
She: Probably.
A brief pause.
He: I do it to be free.
She: You do it to be free.
He: I do it to be free. I do it because the world finds a hundred ways each day to silence the songs of my heart. I do it because I need a counterpoint to neckties and filing cabinets and oxford commas. I do it because so much of my life is multivitamins and single-file lines and carpet tiles and checklists and parallel parking and sugar free sweetener and appointment reminders and hand sanitizer and whiteboards that the idea of running a razor across my neck every day in an effort to fit in better is simply more than I will accept. I do it to push back that cloud of oppressive, pervasive, repressive cleanliness by half an inch; to give myself space to breathe, and to be.
A brief pause.
She: Multivitamins. Is that what the guy on the internet told you? Multivitamins?
He: We also get to tweet about it and post photos.
She: Oh good.
While helping new contributors start hacking on Firefox for Android and Firefox OS, I’ve realized that getting comfortable with Bugzilla is a really important part of getting ramped up. Over the years, people have come up with various tips, tricks and tools for making Bugzilla easier to use, and I thought it would be helpful to gather those into one handy blog post!
To start, if you’ve never used Bugzilla before (or even if you have), you should watch a video johnath made called “Bugzilla for Humans”. It gives a nice overview of key Bugzilla features, as well as tips for more advanced users.
After that, you should watch beltzner’s quicksearch video to get a more familiar with Bugzilla’s quicksearch feature. In your browser, you should add a bookmark keyword to search for bugs from your location bar. You can also add Bugzilla to your list of available search engines in your search bar. For a complete list of things you can do with quicksearch, check out the quicksearch reference on Bugzilla.
If you find yourself interested in a certain area of the Mozilla project, you can opt to watch its Bugzilla component. You can also watch certain users, which is a neat feature if you’re a new contributor looking to follow the activity of a more experienced developer. If you’re a new contributor working on a mentor bug, you should watch your mentor to see what he or she is up to! If you start watching components you’ll definitely want to set up some sort of filter to handle your bugmail. For inspiration, you can see what other Bugzilla usershave done tohandle their Bugmail.
Last, but not least, you should read Bugzilla’s etiquette guidelines to understand what behavior is expected of Bugzilla users. In general, just be a nice person and everyone will be happy!
This is just a quick overview, but if anyone out there has more helpful tips, please share them in the comments!
I recently posted in the newsgroups about a concern over super-review. In some cases patches that seem to meet the policy aren’t getting super-reviewed. Part of the problem here is that the policy is a little ambiguous. It says that any API or pseudo-API requires super-review but depending on how you read that section it could mean any patch that changes the signature of a JS function is classed as an API. We need to be smarter than that. Here is a straw-man proposal for defining what is an API:
Any code that is intended to be used by other parts of the application, add-ons or web content is an API and requires super-review when added or its interface is changed
Some concrete examples to demonstrate what I think this statement covers:
JS modules and XPCOM components in toolkit are almost all intended to be used by applications or add-ons and so are APIs
UI code in toolkit (such as extensions.js) aren’t meant to be used elsewhere and so aren’t APIs (though they may contain a few cases such as observer notifications, these should be clearly marked out in the file)
Any functions or objects exposed to web content are APIs
The majority of code in browser/ is only meant to be used within browser/ and so isn’t an API. There are some exceptions to this where extensions rely on certain functionality such as tabbrowser.xml
Do you think my simple statement above matches those cases and others that you can think of? Is this a good way to define what needs super-review?
Implementing Australis, the new theme for Firefox, is one of the top goals for the desktop team this quarter. As a result, I've recently taken over work on the tab strip visual redesign portion of the project. At this point the tab shape and styling has been implemented on Windows and is undergoing review so it's a good time for testing from a wider audience so the feature can get some polish before development starts on OS X and Linux in the upcoming weeks. The following is a screenshot of a build with the the latest patch.
To test the new design, install the Firefox UX Nightly on Windows (exe, zip). The changes are in code review and there is still some work to be done in follow-ups but at this point there aren't any known bugs which will hinder browser usage so go ahead and give it a try. Polish for background themes and Windows 8 will be added in follow-up bugs.
Some of you have been waiting for Australis since the designs were created over a year ago and you may be wondering why it takes so long to be implemented. The answer is that Firefox UI is very flexible and tries to adapt to various configurations and getting this right with a new theme can be a complex process. Here are just some of the variables that are taken into account while balancing the aesthetics, complexity, and performance of the implementation:
Operating system version/theme
Classic, XP, Aero Basic, Aero Glass, Windows 8, High Contrast
Background themes for Firefox
Window state - maximized/restored/fullscreen
Tabs in the titlebar
Tabs on top/bottom
Integration with system color, font and DPI settings
Tab overflow
Pinned/app tabs
Customization mode
Text direction – Left-to-right vs. right-to-left
Customized toolbar buttons
Tab drag-and-drop
Menu bar visibility
You can follow the remaining Australis tab work from the meta bug. Report issues with the current implementation in the comments on this post or in the bug (if they haven't already been covered there or in the etherpad).
In working on the Web Crypto API specification, the valuable feedback and criticism keeps going back to the main pitfall: DOM malleability. The many attack surfaces in each web page makes handing over crypto keys and crypto primitives quite dangerous. As the W3 working group approaches this API we have this issue in mind, but, the API(s) we want to deliver are not going to solve the DOM-is-dangerous problem. Luckily, browser vendors are working on this – and have been – for years, and the work continues.
Firefox OS will introduce signed “privileged” and “certified” web apps that by default have very strict CSP applied to them. No eval(), no remote scripts or styles – the app is pretty well sandboxed against the most common attacks. These apps are signed and verified before installation and update. Let’s hope these kinds of approaches will help make web apps more “trustworthy”:)
So, how can we use crypto in web pages and not expose anything like keys or actual crypto functions or properties to the DOM? What does that look like? After thinking about the use case for this: web-based messaging, digital signatures for code and document verification – among others, I came up with what I am calling a ‘bridge’ API, I have named it “nulltxt”.
It has one method: window.navigator.bridge.getCipherObject()
This function creates a DOMRequest object, which you can attach event handlers to: “success” and “error”.
To generate a keypair, you pass a config object:
{type: "keygen", format: "DER_BASE64"}
into “getCipherObject”:
var request = window.navigator.bridge.getCipherObject({type: "keygen",format: "DER_BASE64"});
request.onsuccess = function (){ */ this.result.publicKey is our key /* };
request.onerror = function (error){};
Once your keypair is generated, the success callback is executed, handing you a public key and an ID you’ll need to decrypt or sign with that particular key. Multiple keys can be generated per origin.
To encrypt data, you call the same function with a different config object:
This operation opens a special writing widget in the browser chrome where you can safely write plain text outside of the DOM:
Write some plain text, then click the encrypt button. The browser encrypts the data and returns it to your success event handler. The encrypted JSON blob is now available to send to the server where it can be received by Alice.
Reading plain text is the reverse process, your app will need to change some of the properties of the received object:
var readCipherObject = receivedCipherObj; // an object received via the app
readCipherObject.type = "read";
readCipherObject.authorName = "Alice";
readCipherObject.keyID = myKeyID;
var request = window.navigator.bridge.getCipherObject(readCipherObject);
request.onsuccess = function (){ */ this.result.verification contains the 'verification' boolean /* };
request.onerror = function (error){};
The reading UI looks like:
Upon clicking “Decrypt”, the content changes to plaintext:
The plain text is read inside the reading widget and is keep out of the content DOM. A validation boolean property is returned in the success event handler, none of the text.
This UI in this addon is only a part of the point of it. I have long wondered how crypto can be used more safely in web apps – where we don’t have to worry about keys being stolen and primitives being ‘monkeypatched’. I am fairly certain the UX can be made much better. The main idea I want to get across is the internal API. It is quite simple. Once you have a keypair, you can do “hide()” and “show()” – similar to the simplicity of Dan Bernstein’s NaCL (box/unbox).
Sign() and Verify() are also in the works. I would also like for this API to support IETF’s JOSE formats.
Let me know what you think of this approach. I can imagine a web application where the web site only ever handles ciphered data and provides no crypto in the DOM – offloading all of it to the browser chrome. Of course, there are still attack surfaces here, mainly around spoofing the browser chrome UI. With a severe CSP in place, I think this approach might work well.
Check out third place, just edging out bsmith and gaining on masayuki.
Now, before you get all uppity and start accusing Victor of abusing the Try servers, know this: He’s been making great progress beating down our intermittent failures. Earlier this year, we shipped the 3D View which Victor implemented. It has 21 bugs filed on it which either means it’s extremely solid code (it is) or nobody’s using it (they might not be).
Well, that’s not all! Victor has also been doing a fantastic job on our Debugger front end. Just recently he’s completed a massive reorganization of the front-end code making it better and some useful pieces reusable for our other tools. Expect to see some improved Variable Views in our object inspectors, web console and scratchpad very soon as a result.
Please join me in congratulating our latest Firefox Developer Tools Peer by sending him code reviews for the Debugger, Tilt and whatever else you might have for him.
Who are the Jetpack team? What are they here for? A lot of people in Mozilla don’t know that Jetpack still exists (or never knew it existed). Others still think of it as the original prototype which we dropped in early 2010. Our goals have changed a lot since then. Even people who think they know what we’re about might be surprised at what our current work involves.
Let’s start with this basic statement:
Jetpack makes it easier to develop features for Firefox
There are a couple of points wrapped up in this statement:
The Jetpack team doesn’t develop features. We enable others to develop features. We should be an API and tools team. We’ve done a lot of API development, but we should work with the developer tools team more to make sure that Firefox developer tools work for Firefox development, too.
I didn’t say “add-ons.” I said “features”. The APIs we develop shouldn’t be just for add-on developers, Firefox developers should be able to use them too. If the APIs we create are the best they can be, then everyone should want to use them. They should demand to use them, in fact. It follows that this should make it easier for add-ons to transition into full Firefox features, or vice versa.
We happen to think that a modular approach to developing features makes more sense than the old style of using overlays and xpcom. All of the APIs we develop are common-js style modules (as used in Node and elsewhere) and we’ve built the add-on SDK to simplify this style of add-on development. That work includes a loader for common-js modules which has now landed in Firefox and is available to all feature developers. It also includes tools to take directories of common-js modules and convert them into a standalone XPI that can be installed into Firefox.
The next step in supporting Firefox and add-on developers is to land our APIs into Firefox itself so they are available to everyone. We hope to complete that by the end of this year and it will bring some great benefits, including smaller add-ons and the ability to fix certain problems in SDK based add-ons with Firefox updates.
Mythical goals
Jetpack has been around for a while and in that time our focus has changed. There are a few cases where I think people are mistaken about the goals we have. Here are the common things that were talked about as hard-goals in the past but I don’t are any longer.
Displace classic add-ons
Most people think Jetpack’s main goal is to displace classic add-ons. It’s obvious that we’ve failed to do that. Were we ever in a position to do so? Expecting the developers of large add-ons to switch to a different style of coding (even a clearly better one) without some forcing factor doesn’t work. The electrolysis project might have done it, but even supporting e10s was easier than converting a large codebase to the add-on SDK. The extension ecosystem of today still includes a lot of classic addons, and the APIs we build should be usable by their developers, too.
Forwards compatibility
Users hate it when Firefox updates break their add-ons. Perfect forwards compatibility was another intended benefit of the SDK. Shipping our APIs with Firefox will help a lot, as the add-ons that use them will work even if the specific implementation of the APIs needs to change under the hood over time. It won’t be perfect, though. We’re going to maintain the APIs vigorously, but we aren’t fortune tellers. Sometimes parts of Firefox will change in ways that force us to break APIs that didn’t anticipate those changes.
What we can do though is get better at figuring out which add-ons will be broken by API changes and reach out to those developers to help them update their code. All add-on SDK based add-ons include a file that lists exactly which APIs they use making it straightforward to identify those that might be affected by a change.
Cross-device compatibility
There’s a theory that says that as long as you’re only using SDK APIs to build your add-on, it will magically work on mobile devices as well as it does on desktop. Clearly we aren’t there yet either. We are making great strides, but the goal isn’t entirely realistic either. Developers want to be able to use as many features as they can in Firefox to make their new feature great. But many features in one device don’t exist or make no sense on other devices. Pinned tabs exist on desktop and the SDK includes API support for pinning and un-pinning tabs. But on mobile there is currently no support for pinned tabs. Honestly, I don’t think it’s something we even should have for phone devices. Adding APIs for add-ons to create their own toolbars makes perfect sense on desktop, but again for phones makes no sense at all.
So, do we make the APIs only support the lowest common denominator across all devices Firefox works on? Can we even know what that is? No. We will support APIs on the devices where it makes sense, but in some cases we will have to say that the API simply isn’t supported on phones, or tablets, or maybe desktops. What we can do, again by having a better handle on which APIs developers are using, is make device compatibility more obvious to developers, allowing them to make the final call on which APIs to employ.
Hopefully that has told you something you didn’t know before. Did it surprise you?
First, we will add a variable called revealed that keeps track of all pixels
that have already been revealed by holding a green object in front of the
camera. Instead of replaceGreen() we will call our method revealGreen()
from now on:
functionrevealGreen(data){varlen=width*height;for(vari=0,j=0;i<len;i++,j+=4){// This pixel has already been revealed.if(iinrevealed){data[j+3]=0;continue;}
When iterating over all of the canvas’ pixels we check whether the current index
is marked as revealed. If so we do not need to check its color but set its
opacity to zero and continue with the next iteration.
// Convert from RGB to HSL...varhsl=rgb2hsl(data[j],data[j+1],data[j+2]);varh=hsl[0],s=hsl[1],l=hsl[2];// ... and check if we have a somewhat green pixel.if(h>=90&&h<=160&&s>=25&&s<=90&&l>=20&&l<=75){data[j+3]=0;revealed[i]=true;}}}
If the pixel has not been revealed yet but is a green one, we make it
transparent like before and mark it to stay that way.
Demo and screencast
That is all! Take a look at the live demo or watch the
screencast below:
I know…
… this is not much of a game but rather a small demo one could turn into a
mini-game with little effort. Play around with the code and see what you can
come up with!
While recently watching a talk about the new WebRTC features I was reminded of
Paul Rouget’s great
green screen demo
and thought that this would be a cool thing to have for live video as well.
Let us build a live green screen!
Those are the parts we need. A <video> element that plays the media stream
and a canvas we will use to read and transform image data.
The JavaScript
functioninitialize(){// Get the webcam's stream.navigator.getUserMedia({video:true},startStream,function(){});}functionstartStream(stream){video.src=URL.createObjectURL(stream);video.play();// Ready! Let's start drawing.requestAnimationFrame(draw);}
We call navigator.getUserMedia()
and pass {video: true} as the first argument which indicates that we want to
receive a video stream. We assign the MediaStream to the video’s .src property
to connect it to the <video> element.
The video starts playing (which means the camera will be activated and you will
see your webcam’s live video) and we request an animation frame using the
requestAnimationFrame() API.
This is perfect for drawing to our canvas as the browser schedules the next
repaint and we will be called immediately before that happens. Now for the last
and most important part of our green screen:
functiondraw(){varframe=readFrame();if(frame){replaceGreen(frame.data);context.putImageData(frame,0,0);}// Wait for the next frame.requestAnimationFrame(draw);}functionreplaceGreen(data){varlen=data.length;for(vari=0,j=0;j<len;i++,j+=4){// Convert from RGB to HSL...varhsl=rgb2hsl(data[j],data[j+1],data[j+2]);varh=hsl[0],s=hsl[1],l=hsl[2];// ... and check if we have a somewhat green pixel.if(h>=90&&h<=160&&s>=25&&s<=90&&l>=20&&l<=75){data[j+3]=0;}}}
What happens here is actually quite simple: we read the current video frame and
extract its image data. We then iterate over all pixels in the frame and check
if we found a green one - if so its opacity byte is set to zero, which means
fully transparent. The manipulated image data is put back into the canvas and
we are done for now until the next animation frame is ready.
The demo
Take a look at the live demo, you will need a recent
Firefox/Chrome/Opera build. Make sure that getUserMedia() support is enabled
in your browser of choice. Hold a green object in front of the the camera and
try it out yourself. Your camera and light setup is probably very different
from mine so you might need to adjust the color check a little to make it work.
Alternatively, here is a screencast of the demo:
The end
This is an admittedly very simple example of a green screen but you can use
this little template to manipulate your webcam’s live video stream and build all
kinds of fancy demos with it.
Planet Mozilla readers are undoubtedly familiar with Jared Wein (a.k.a. jaws) – he joined the Firefox team in June 2011, and has been blogging actively about his work since then. He’s worked on HTML5 video controls, helped mentor and coordinate work on in-content prefs in Firefox, created the Cheevos add-on, been involved with diagnosing and fixing all sorts of Snappy bugs, and many more things that I’m sure I’m forgetting now.
Most recently, Jared’s been spending much of this time helping Felipe, Mark, Shane, and I get Firefox’s Social API ready for Firefox 17. This took a massive amount of work, and while we’re not still not done, we really couldn’t have gotten to where we are without his help.
Jared has been unofficially reviewing code for a while now, and has definitely proven that he’s collected the knowledge and experience required to review Firefox code. So it pleases me to announce that Jared is now officially a Firefox reviewer. Congratulations, Jared!
This preview will give you a glimpse of what Firefox on Metro will be like, but it is not meant to be complete. Several incomplete features will exist, which is normal at this point in development.
The preview is meant to be installed on Windows 8 RTM and later. It is built with PGO optimizations turned off, so it will be slightly slower than the default installs. PGO will be turned on at some point in a future update.
The Metro Firefox Preview has nightly updates enabled
The Firefox Metro preview will have updates enabled on its own channel. That means that from here on out, you can keep up to date on what we're up to with the Metro browser by actually trying it.
Desktop Firefox is responsible for applying the updates for both the Desktop and Metro front ends currently. You may encounter an update error where updates will fail to apply if both of your Desktop and Metro browsers are open at the same time. This will be resolved at some point in a future update.
Some features to look for in the Metro Firefox Preview
This preview will also include the following highlights:
Metro browser registration capable installer
Zip builds which do registration upon setting default browser from within Firefox
Updates enabled
New navigation URL bar inspired by the australis theme
New tab bar with tab previews (double swipe from the top edge or bottom edge to expose the tab previews)
Alternate tab bar with always visible tabs
Auto complete screen with tile suggestions as you type
New touch optimized start screen with tiles
Windows 8 App bar with common functionality
Changes to the default theme to fit into Metro
Various new touch capabilities
Various keyboard shortcuts
On screen keyboard handling
Gesture support
In-page text selection
Crash reporting
Telemetry support
Context sensitive default handling, if in Metro stay in Metro for link clicks
Sync support with browser through remote Firefox sync (Set it up through settings)
Support for the share data contract to share the current page with another Metro application
Support for the search contract to search inside Firefox whether or not Firefox is already open
Support for the settings contract accessible via the settings charm
Support for snap and filled states, to use Firefox and another Metro application at the same time
Metro open and save file picker support
Support for secondary tiles (pinned websites to your start screen)
View current page on desktop functionality
Support for pdfjs: In content PDF viewer built in JavaScript
Spell checking enabled
And a lot more
Reminder on defaults handling
Metro browsers can only be used in Windows 8 if the browser is set as your default. So if you want to keep this preview installed and get updates, you'll need to keep it as the default.
To set the default browser, simply open Desktop Firefox options, go to the advanced -> General tab, and click on the "Make Firefox the default browser" button. This will launch Control Panel, you will need to select the browser from the list and set all defaults.
Things not yet implemented or disabled
Although we have plans for Flash support, the preview currently has it disabled. You can add support for windowless plugins by setting plugin.disable to false in about:config.
As previously mentioned, for the Metro environment only, even in the initial release, we will not have add-ons enabled. We will eventually add support for add-ons through the add-on SDK.
Panning and zooming support is currently disabled. Scrolling with the mouse wheel is broken at the moment as well. Scrolling with the mouse wheel was fixed on the Nightly update the day after the initial preview. You will have to use your keyboard for scrolling, or use touch. Minimum system requirements are the same as Windows 8 except that DirectX 9 is not supported yet.
This past week, a few members of Firefox team were asked to help out with the big pile of bugs blocking the initial release of Gaia, the Boot to Gecko user interface. I’m no stranger to jumping into a new project, so I figured this would be a fun opportunity to do something different for a few months. I ran into some problems getting my Gaia development environment set up, and I wanted to document them in an effort to improve the experience for other new contributors.
This being Mozilla, the first thing I did was find the wiki page about getting a build environment set up. I don’t have a B2G device yet, so I was looking to set up a desktop development environment. The “quick start” instructions said that I just needed to clone Gaia from github, and then I could run it in a desktop Firefox nightly build. Sounds simple!
git clone git://github.com/mozilla-b2g/gaia
cd gaia
make && /path/to/nightly -profile `pwd`/profile -no-remote http://system.gaiamobile.org:8080
However, when I tried doing that, I ended up with an empty home screen.
I saw that the wiki also mentioned I could download a desktop B2G build, so I tried that next.
/path/to/b2g -profile `pwd`/profile
I still ended up with the same blank home screen. On IRC, I heard ttaubert say he was using his own B2G desktop build, built from mozilla-central. Since I already had a mozilla-central development environment set up, building B2G was as easy as creating a new mozconfig.
cd /path/to/mozilla-central MOZCONFIG=mozconfig-b2g make -f client.mk build cd /path/to/gaia /path/to/my-b2g -profile `pwd`/profile
And that worked! Time to start hacking. I looked through the list of “mentored” github issues, and I found an simple-looking bug in the browser app. The first thing I wanted to do was add some logging in a file. To enable console logging, I heard on IRC that I needed to be running DEBUG=1 make in my gaia directory, not just plain make. I made that change, but this time when I launched my B2G desktop app, I got a completely blank white screen!
There were no error messages in my terminal window, but I learned that I could use the -jsconsole flag to open the JavaScript console. When I did that, I saw some errors in core B2G code.
No one on IRC in #gaia was able to help me figure out this issue, and I was feeling pretty frustrated. I ended up talking to a B2G developer in the office, and he said that Gaia’s debug mode is often unstable. He suggested that instead of running Gaia in debug mode, I should make a debug B2G build and use dump statements for my print-based debugging. Following this suggestion, I finally ended up in a place to try to start making a patch. However, the instructions for running Gaia’s unit tests say you should be using debug mode, so I don’t know if this is a real long-term solution.
I haven’t finished my patch yet, so I may run into more issues along the way, but I want to encourage developers to update documentation regularly, and to make sure that documentation works. I’m employed by Mozilla, so I’m required to have the patience to sort through issues like these, but they can be a real hurdle for volunteer contributors to get involved in the project. Let’s try to fix that!
Last week, the Firefox Devtools teams got together in London for some together-time. We kicked the show off on Tuesday with some lightning talks, followed by hack sessions over the rest of the week. As always, it’s incredible getting together with everybody — I’m kind of a fan. We’ll be finishing things we worked on this week for the next couple of months and it will be awesome.
My lightning talk was an example of how you can write a Jetpack addon using gozala‘s Scratch-kit. I cooked up a non-working demo the morning before our talks and managed to get the addon prototype to a state where it kind of works. The addon itself is ultimately intended to be a button you can use to share posts on app.net (the I-have-fifty-dollars social network).
The Code looks like this:
The remaining time was spent hacking on bigger targets. I got to sit down with Benoit Girard and work on integrating a JS-only version of the SPS Profiler. In two days, we were able to put up patches for a stripped-down version replacing the addon and integrating the Cleopatra web app. We’re going to be continuing that work over the next little while to get it polished and tested. See bug 795262 to track our progress.
I could not be happier ever since I switched from Wordpress to Octopress.
I usually write and publish blog posts from where I live, Berlin. The time zone
here is CET (UTC+1). While recently visiting Mozilla’s HQ in Mountain View I
wrote another blog post just as usual and typed “rake generate” to turn my
Markdown files into static HTML files.
Looking at the output though, got me a little puzzled. All timestamps were
changed to be calculated off the PDT time zone. While certainly that is not a
big deal as they are still the same timestamps, I did not feel like changing
all of those every now and then I am somewhere in a different time zone.
If you want to use a “static” time zone when generating your page, do it like
this:
TZ=CET rake generate
TL;DR - put your time zone into the TZ variable if you want to force Jekyll
to use a specific time zone when generating your HTML files.
CSS transitions are
awesome. You can use them to easily animate the transition of one or multiple
CSS properties from a given state to another. But how does that work if your
element has just been created and inserted into the DOM dynamically?
Let’s take a look at this simple example:
div{/* ... */transition:opacity500ms;}
varelem=document.createElement("div");document.body.appendChild(elem);// Make the element fully transparent.elem.style.opacity=0;// Fade it in.elem.style.opacity=1;
We dynamically insert a new <div> element into the DOM with its initial
opacity set to zero. Subsequently we want it to fade to full opacity.
This - as you might have guessed - does of course not work that way.
How about a timeout?
It is clear that we somehow need to make sure the initial state with zero
opacity is “applied” before trying to fade in:
varelem=document.createElement("div");document.body.appendChild(elem);// Make the element fully transparent.elem.style.opacity=0;// Make sure the initial opacity value is applied.setTimeout(function(){// Fade it in.elem.style.opacity=1;},0);
This is only marginally better. It seems to work with Webkit and Opera (and
maybe even IE) but not in Firefox (in 99% of the cases). Using setTimeout()
is a little too much overhead and nobody guarantees you that the style has
really been applied after some milliseconds. It may be unsupported and
unreliable, we need something better.
getComputedStyle to the rescue
There is another way to apply the element’s current style that even works
synchronously:
varelem=document.createElement("div");document.body.appendChild(elem);// Make the element fully transparent.elem.style.opacity=0;// Make sure the initial state is applied.window.getComputedStyle(elem).opacity;// Fade it in.elem.style.opacity=1;
Although it looks like we only query the current opacity value, getComputedStyle()
in combination with accessing a property value actually flushes all pending
style changes and forces the layout engine to compute our <div>’s current
state. This workaround works in all major browsers and does not yield different
results like the setTimeout() approach.
It seems like most developers at Mozilla have their own optimized bugmail workflow, but today a conversation on IRC inspired me to share mine.
I created a set of gmail filters to group my bugmail into buckets of varying importance. Although gmail doesn’t support filtering based on email headers, I found that string matches do a pretty good job (since most people don’t write things like “You are the assignee for the bug” in a bug comment).
Here’s how I group the things I care about:
Matches: from:(bugzilla-daemon@mozilla.org) subject:((review requested:) OR (feedback requested:)) Do this: Skip Inbox, Apply label “b:review”
Matches: from:(bugzilla-daemon@mozilla.org) “You are the assignee for the bug.” Do this: Skip Inbox, Apply label “b:assigned”
Matches: from:(bugzilla-daemon@mozilla.org) (“You are on the CC list for the bug.” OR “You reported the bug.”) -{“You are the assignee for the bug.”} Do this: Skip Inbox, Apply label “b:cc”
And here’s how I catch everything else:
Matches: from:(bugzilla-daemon@mozilla.org) -{“You are on the CC list for the bug.” OR “You reported the bug.” OR “You are the assignee for the bug.” OR “review requested:” OR “feedback requested:”} Do this: Skip Inbox, Apply label “b”
This is how I can get away with watching the whole Firefox for Android component, but still make sure I see important bugmail in a timely fashion. It’s especially excellent for post-vacation catch-up!
As of the end of August, two awesome Mozilla hackers, Matt Brubeck and Frank Yan started tearing through front end bugs for the Metro browser.
Mark Finkle who is the mobile front end lead has also been joining in and sharing invaluable insight.
Jonathan Wilde has been working on making the Metro UI mockups a reality for the past few months. Jonathan Wilde's internship is complete, but he is still contributing.
Tim Abraldes, Jim Mathies,and I do some work in front end code, but are all mostly focused on the core platform code.
Front end progress
Several keyboard shortcuts were added, the new tab page is now the default home page, and a ton of small glitches on the front end are now fixed.
There are 2 modes for tabs in the Metro Firefox front end. You can have tab previews above the URL bar when you swipe down, or you can have classic style tabs that are always showing. The mode-selection persists now when you toggle between the 2 modes.
An actual installer
We updated the Firefox installer to do the necessary metro registration and include all of the new Metro bits.
We also have zip builds which will do the needed Metro registration after you set the default browser from within Firefox preferences.
Default browser handling changes
In Windows 8 RTM, Microsoft protects both the default protocol handler, and the default file type handlers (such as .html) with a cryptographic hash.
The only way for a browser to set itself as default now, is to ask the OS to do it. And the OS asks the user to do it.
For this reason, we're switching the startup check to be a nice Windows 8 fly out which asks you to select your default browser. This fly out only has the ability to set the HTTP defaults though.
The check in preferences is also updated to simply open control panel's Control Panel\Programs\Default Programs\Set Default Programs.
When you set your defaults in control panel, you can set both HTTP and HTML defaults at the same time. We're opting for not showing the control panel screen for startup checks because the UI is complex. I'm hoping a new UI will be introduced in Windows 9 that will more easily allow the user to set both HTTP and HTML defaults at once without using the Control Panel screen.
We also added code to do the needed Metro registration on Windows 8 after each upgrade. So when we release support on Windows 8, you'll have the needed registration.
Default browser handling and UAC
Due to the way default browser registration works, depending on what your default browser was previously, Firefox would sometimes have to prompt you with a UAC window on Windows 7 and Vista. In Windows 8 Microsoft changed this so that you can do this registration entirely in HKCU.
We updated our code to take advantage of this, so as of Windows 8, you will never see a UAC dialog for default browser handling in Firefox.
Things we disabled
We disabled the code for loading external add-ons since we don't plan to have add-on support for the initial release. We will have add-ons through the add-on SDK after the initial release though.
The Flash support that we currently do have is disabled for the preview as well.
Build changes
The platform splitting bug that was holding us up from landing on mozilla-central is complete as far as our needs are concerned. It landed on elm which is where we'll do the Metro preview from. There was a lot of fallout from these changes that got fixed up as well.
Various other changes
We synced up the user agent string with the desktop one, did some crash reporting fixes, improved text selection, fixed up things for mouse and touch, fixed the Metro clipboard handling, added support for anonymous opt-in telemetry data reporting, and fixed several other bugs.
We added a save file picker, context menu items for saving images, enabled spell checking, and more.
Landing on mozilla-central
The platform splitting bug is complete enough for our needs but I think there is still a bit of work before it can land on m-c.
We also need to make a decision on if we will wait for Microsoft to add VS2012 Windows XP targeting support. They will be adding it soon, but if we don't hear an exact date we'll be switching out all of our C++/CX code for WRL code.
That switch won't take us too long, I would guess a week of long hours, or slightly more. Dropping C++/CX support would mean we can use VS2010 and the Windows 8 SDK.
Good news! With a lot of hard work – I want to tip my hat to Ryan Sleevi at Google – the W3C Web Crypto API First Public Working Draft has been published: http://www.w3.org/TR/WebCryptoAPI/
If you have an interest in cryptography or DOM APIs and especially an interest in crypto-in-the-DOM, please read the draft and forward any commentary to the comments mailing list: public-webcrypto-comments@w3.org
This past weekend I attended MozCamp EU in Warsaw, and it was really energizing to see so many awesome Mozilla contributors come together. The theme of this MozCamp was “Mobilize Mozilla”, and I co-hosted a session about developing add-ons for Firefox for Android.
In the first part of this session, we walked through the basics of developing a simple restartless add-on. After that, we set developers loose to start hacking on their own add-ons, encouraging them to start with a bootstrapped add-on skeleton. Before long, we saw a bunch of excited developers pointing to test menuitems and notifications appearing on their phones, followed by discussion about all the cool things they wanted to build. This was one of my favorite parts of MozCamp!
Although this session proved that it’s not too hard to get started with mobile add-on development, there are definitely some pain points. Here are some things we need to work on:
Create an easier workflow for getting an add-on from your development machine to your phone. Right now the easiest way to do this is using adb, but some developers want to be able to test their add-ons without installing the Android SDK.
Fully support using the Android emulator to develop mobile add-ons. Some of the developers attending the talk didn’t own Android phones; we had extra phones on hand to lend to them, but that’s not a long term solution. I know that work has been done to run Firefox in the emulator, but I don’t know of anyone on the mobile team actively testing this to make sure it always works.
Better documentation! This is always true of everything, but I want to call it out. In particular, I think we need more documentation about manipulating content from mobile add-ons. Even though this is very similar to what you would do for a desktop add-on, getting at the content window is different, and this confused some developers.
I’m looking forward to seeing more mobile add-ons, and I’d like to know if there’s anything else we can do to make it easier to develop add-ons for Firefox for Android. The mobile team is always hanging out in #mobile on irc.mozilla.org, so please jump in there if you have any ideas, or if you need help developing your add-on!
It’s the first day back at work after spending a great work week in London with the Jetpack team last week. I was going to write a summary of everything that went on but it turns out that Jeff beat me to it. That’s probably a good thing as he’s a better writer than I so go there and read up on all the fun stuff that we got done.
All I’ll add is that it was fantastic getting the whole team into a room to talk about what we’re working on and get a load of stuff done. I ran a discussion on what the goals of the Jetpack project are (I’ll follow up on this in another blog post to come later this week) and was delighted that everyone on the team is on the same page. Employing people from all around the world is one of Mozilla’s great strengths but also a potential risk. It’s vital for us to keep doing work weeks and all hands like this to make sure everyone gets to know everyone and is working together towards the same goals.
What you need to know: If you set a breakpoint in the Debugger in Firefox 15 and then hit “Reload”, the Debugger is going to shutdown. This has been fixed in Firefox 16.
And now the story…
A couple of weeks ago, Dave Herman (aka @littlecalculist) CC’d me on a tweet. That led to this tweet:
@littlecalculist That was an earnest question, not snark. I couldn’t get debugger statements or breakpoints to work.
Initially, I didn’t know what was going on. I’ve been using the debugger daily but not in any deep way. I’ve seen breakpoints and debug statements work regularly. After a couple more exchanges, Tom pointed us to a video of his situation which was setting a breakpoint early in his script and then hitting reload, expecting the breakpoint to hit during the parsing phase.
This too I know I’d seen work, so there was definitely something wrong so I filed bug 783393. Panos wasn’t around so I asked Dave (Camp) what he thought and he poked around at it for a bit. He determined that we had a nasty race condition in our Debugger reattach mechanics. Dave still knows the Debug Protocol code as well as anyone (despite his protests) and he agreed to hack up a patch for us.
By now it’s late Thursday, August 16th. Twelve days before the merge.
What’s a merge you ask? That’s where we take our Nightly browser and push it up to Aurora. Aurora becomes Beta and Beta becomes the new Firefox. Yes, that’s right, we have 4 branches we maintain and shuttle through our release processes. Who takes care of each of these channels? Our release managers!
By Monday, dcamp had a decent patch to deal with the race condition. It required rewriting the way the Debugger detaches and reattaches to content on navigation. It had gotten a little complex, but it was something. Panos was back from the beach and we brought him up to speed on the story and handed the patch over to him. He’d just gotten back from the beach and seemed very relaxed.
Dave and I decided it would be best if we had a patch to disable the debugger on reloads and navigation in Beta. The likelihood of the full fix making it in was minimal, so I wrote the tiniest patch I could think of to do it. A total hack job. Dave had switched back to getting his new markup panel for the inspector into a shippable state. I could have sworn I heard the sepulchral undertones of Norwegian metal when I spoke to him in IRC.
By Tuesday, Panos was still grinding on the patch, fixing failing tests, rewiring parts of it and dealing with the fallout. The patch was mutating a little but Panos was improving it. The beard he’d grown the previous week on the beach was starting to itch but he clung to it. I think it helped him code. Kept him in a beachy state of mind. I pung Lukas Blakk to tell her what was going on and warn her that we were going to have to try to get something into Beta. We didn’t know what at that point because we weren’t sure we’d be able to port Dave and Panos’ fix that far forward.
I gave an update in the engineering meeting that went something like, “yeah. breakpoints in reload. not so much. working on it…” Afterwards, Lukas, Dave and I went through our freshly-cooked plan to ship the shutdown patch on Beta and the real fix on Nightly and Aurora which should be ready Any Minute Now. Lukas agreed this was a sensible approach. The alternatives were waiting for a patch that might not work on Beta or kill-switching the feature. We felt the Debugger was still useful enough without reload breakpoints working that it was worth shipping and I still believe that’s true. It just might require some additional debugging strategy or a jump to the new Beta or Aurora (where most devs should probably be anyway).
Wednesday. The patch was not ready yet. I started wondering if we should kill reloads on Aurora as well. I was getting a little scared, but Panos’ beard gave me hope. Then he shaved it off.
Thursday and we had our tests passing. The patch was ready, but not quite perfect. I encouraged us to move ahead with an imperfect patch. I reviewed a couple of things Victor had been working on. Little things like full script search and some collapsible panels in the debugger. Nice things he’d been patiently waiting to land.
Friday the patch was ready. Panos landed it amidst a tree of fire and watched the tests pass. It was glorious. I conferred with Lukas one last time to get preapproval for Aurora. I’d be landing it on Saturday, but that was cool. Stuff was landing. The devtools team was pushing features into the fx-team repository at a shocking pace. It was like that scene from Mission Control when the rover touched down and everybody including mohawk guy were awkwardly high-fiving and cheering. Yes it was that good.
On Saturday, Victor and I hung out and rebased Panos’ patch for Aurora. Fixed some tests. Made it work. Victor did most of the work. He’s good that way.
What’s really impressive to me is how this whole thing unfolded from start to finish. An innocuous tweet about one feature from someone outside the project could turn into a flurry of activity and have such an excellent resolution in a very short time-scale. Everybody worked really hard on this thing and if we’d shipped without those breakpoints working on reload, it would’ve undermined people’s confidence in it. I think this extra effort makes the Debugger that much more usable. I’m also really impressed with how Dave, Panos, Victor, Mihai, Lukas and Nick dealt with all of this. It’s a huge privilege to work with such amazing and talented people.
Also, thanks to Tom Dale for reaching out to us and asking a question. This couldn’t have happened without him and Dave Herman pointing us to it.
So yeah. We have a JavaScript Debugger now. It’s in Firefox 15 and up. You should probably use Beta or Aurora for serious debugging. I hope you like it.
Firefox 17 (Nightly, that soon becomes Aurora) includes two improvements for
the new tab page introduced by version 13.
Customize the number of tiles
Bug 752841
introduced two preferences that allow you to adjust the number of tiles on your
new tab page to your likings. All you have to do is open “about:config” and
modify one or both of the following preferences:
Your changes will be applied instantly and all open new tab pages will be
updated. There is no positive limit to the number of rows and columns so feel
free to experiment with those values.
Restore sites you removed from the grid
With the landing of bug 722234
you will finally be able to undo the removal of sites from your new tab page.
As soon as you remove a site from the grid we will show you a dialog that ask
whether you want to undo the last change or to restore all sites you ever
removed from the grid.
Work on the Metro style enabled desktop browser has progressed steadily and things are looking really good.
We have a Q3 goal of delivering a Metro preview. This preview will include primary browser UI for navigation and tabs, and will be delivered as a combined classic + metro browser. I believe there is a Q4 goal for a beta release as well.
We made significant progress since the last update, but there is still a lot to do.
In particular we got the following working:
Crash reporting
pdfjs (Built in PDF viewer without the need for a plugin)
Windowless Flash, although full screen flash doesn't work yet
Some accessibility hooks
Front end event refactoring to be faster and to treat mouse input normally and distinct from touch input
File pickers updated to be asynchronous on all platforms because it was needed for WinRT
Front end awesomescreen work was done with results coming up as you type in the urlbar.
While in metro, we also have the 'view this page on desktop' functionality working
Various keyboard shortcuts added
Various other fixes and refactoring
Add-ons will not be part of the initial release, but we will eventually be supporting Add-ons via the Add-on SDK. These initial limitations are only when in the Metro version of the browser on Windows 8.
We'll have some kind of sync functionality to sync data between your Metro interface and your desktop interface. We're hoping for a local, no setup sync functionality, but at worst it will be done through the current sync functionality.
We haven't merged to mozilla-central yet, which is where Nightly builds will show up. This is mainly because we're waiting on bug 755724 to be complete, which is to split platform and app resources up so that they can be loaded individually.
As you probably already know, Firefox 13 introduced a neat new feature - the
new tab page.
We replaced the old blank page with a list of thumbnails of recently visited
sites. While the feature itself works great for many people it has definitely
made opening new tabs a little more noisy.
Do not show loading indicators
As we are now loading a real (although local) page, there are loading indicators
when opening a new tab. The throbber starts to spin and the tab title changes
to “Connecting…” until the page has loaded. That is a lot of unnecessary noise.
In bug 716108
(Firefox 17) we removed loading indicators for newly opened tabs. No spinning
throbber, no flickering tab label. It only is a very subtle change but the whole
action of opening a new tab feels a lot smoother again.
Preload new tab pages in the background
If you happen to have a slower machine you will notice that loading the new tab
page takes a little while. It is a normal HTML (and partly XUL) page that we
need to parse and render. As all tabs start out with a blank docShell you will
first see a white canvas that then is replaced by “about:newtab”. As a last step
all thumbnails will be loaded and drawn progressively.
Opening a new tab is a very frequent action so it should feel snappy and not get
in your way at all. As optimizing the parsing and rendering stages any further
is more than a non-trivial task I came up with a little trick in
bug 753448.
The idea is to preload the new tab page in the background so it has already
loaded when users open a new tab. All we now have to do is switch docShells
and the new tab page gets shown instantly.
You can give it a try as it landed in yesterday’s Nightly (2012-08-14). Just go
to “about:config” and set “browser.newtab.preload” to “true”. This option is
not yet enabled by default as we first have to figure out some minor talos
regressions until it is ready for prime time.