Benjamin Kerensa: UbuConLA: Firefox OS on show in Cartagena |
If you are attending UbuConLA I would strongly encourage you to check out the talks on Firefox OS and Webmaker. In addition to the talks, there will also be a Firefox OS workshop where attendees can go more hands on.
When the organizers of UbuConLA reached out to me several months ago, I knew we really had to have a Mozilla presence at this event so that Ubuntu Users who are already using Firefox as their browser of choice could learn about other initiatives like Firefox OS and Webmaker.
People in Latin America always have had a very strong ethos in terms of their support and use of Free Software and we have an amazingly vibrant community there in Columbia.
So if you will be anywhere near Universidad Tecnol'ogica De Bol'ivar in Catagena, Columbia, please go see the talks and learn why Firefox OS is the mobile platform that makes the open web a first class citizen.
Learn how you can build apps and test them in Firefox on Ubuntu! A big thanks to Guillermo Movia for helping us get some speakers lined up here! I really look forward to seeing some awesome Firefox OS apps getting published as a result of our presence at UbuConLA as I am sure the developers will love what Firefox OS has to offer.
Feliz Conferencia!
|
Fredy Rouge: OpenBadges at Duolingo test center |
Duolingo is starting a new certification program:
I think is good idea if anyone at MoFo (pay staff) write or call this people to propose the integration of http://openbadges.org/ in their certification program.
I really don’t have friends at MoFo/OpenBadges if you think is a good idea and you know anyone at OpenBadges please FW this idea.
http://fredyrouge.wordpress.com/2014/08/12/openbadges-at-duolingo-test-center/
|
Byron Jones: happy bmo push day! |
the following changes have been pushed to bugzilla.mozilla.org:
discuss these changes on mozilla.tools.bmo.
http://globau.wordpress.com/2014/08/12/happy-bmo-push-day-107/
|
Hannah Kane: Maker Party Engagement Week 4 |
We’re almost at the halfway point!
Here’s some fodder for this week’s Peace Room meetings.
tl;dr potential topics of discussion:
Fun fact: this approach is generating a typical month’s worth of new webmaker users every three days.
——–
Overall stats:
http://hannahgrams.com/2014/08/11/maker-party-engagement-week-4/
|
Sean Martell: What is a Living Brand? |
Today, we’re starting the Mozilla ID project, which will be an exploration into how to make the Mozilla identity system as bold and dynamic as the Mozilla project itself. The project will look into tackling three of our brand elements – typography, color, and the logo. Of these three, the biggest challenge will be creating a new logo since we currently don’t have an official mark at the moment. Mozilla’s previous logo was the ever amazing dino head that we all love, which has now been set as a key branding element for our community-facing properties. Its replacement should embody everything that Mozilla is, and our goal is to bake as much of our nature into the visual as we can while keeping it clean and modern. In order to do this, we’re embracing the idea of creating a living brand.
I’m pleased to announce you already know what a living brand is, you just may not know it under that term. If you’ve ever seen the MTV logo – designed in 1981 by Manhattan Design – you’ve witnessed a living brand. The iconic M and TV shapes are the base elements for their brand and building on that with style, color, illustrations and animations creates the dynamic identity system that brings it alive. Their system allows designers to explore unlimited variants of the logo, while maintaining brand consistency with the underlying recognizable shapes. As you can tell through this example, a living brand can unlock so much potential for a logo, opening up so many possibilities for change and customization. It’s because of this that we feel a living brand is perfect for Mozilla – we’ll be able to represent who we are through an open visual system of customization and creative expression.
You may be wondering how this is so open if Mozilla Creative will be doing all of the variants for this new brand? Here’s the exciting part. We’re going to be helping define the visual system, yes, but we’re exploring dynamic creation of the visual itself through code and data visualization. We’re also going to be creating the visual output using HTML5 and Web technologies, baking the building blocks of the Web we love and protect into our core brand logo.
In order to have this “organized infinity” allow a strong level of brand recognition, we plan to have a constant mark as part of the logo, similar to how MTV did it with the base shapes. Here’s the fun part and one of several ways you can get involved – we’ll be live streaming the process with a newly minted YouTube channel where you can follow along as we explore everything from wordmark choices to building out those base logo shapes and data viz styles. Yay! Open design process!
So there it is. Our new fun project. Stay tuned to various channels coming out of Creative – this blog, my Twitter account, the Mozilla Creative blog and Twitter account – and we’ll update you shortly on how you’ll be able to take part in the process. For now, fell free to jump in to #mologo on IRC to say hi and discuss all things Mozilla brand!
It’s a magical time for design, Mozilla. Let’s go exploring!
http://blog.seanmartell.com/2014/08/11/what-is-a-living-brand/
|
Gervase Markham: Accessing Vidyo Meetings Using Free Software: Help Needed |
For a long time now, Mozilla has been a heavy user of the Vidyo video-conferencing system. Like Skype, it’s a “pretty much just works” solution where, sadly, the free software and open standards solutions don’t yet cut it in terms of usability. We hope WebRTC might change this. Anyway, in the mean time, we use it, which means that Mozilla staff have had to use a proprietary client, and those without a Vidyo login of their own have had to use a Flash applet. Ick. (I use a dedicated Android tablet for Vidyo, so I don’t have to install either.)
However, this sad situation may now have changed. In this bug, it seems that SIP and H.263/H.264 gateways have been enabled on our Vidyo setup, which should enable people to call in using standards-compliant free software clients. However, I can’t get video to work properly, using Linphone. Is there anyone out there in the Mozilla world who can read the bug and figure out how to do it?
http://feedproxy.google.com/~r/HackingForChrist/~3/f5KEEuHYNLM/
|
Gervase Markham: It’s Not All About Efficiency |
Delegation is not merely a way to spread the workload around; it is also a political and social tool. Consider all the effects when you ask someone to do something. The most obvious effect is that, if he accepts, he does the task and you don’t. But another effect is that he is made aware that you trusted him to handle the task. Furthermore, if you made the request in a public forum, then he knows that others in the group have been made aware of that trust too. He may also feel some pressure to accept, which means you must ask in a way that allows him to decline gracefully if he doesn’t really want the job. If the task requires coordination with others in the project, you are effectively proposing that he become more involved, form bonds that might not otherwise have been formed, and perhaps become a source of authority in some subdomain of the project. The added involvement may be daunting, or it may lead him to become engaged in other ways as well, from an increased feeling of overall commitment.
Because of all these effects, it often makes sense to ask someone else to do something even when you know you could do it faster or better yourself.
– Karl Fogel, Producing Open Source Software
http://feedproxy.google.com/~r/HackingForChrist/~3/R5jtDBWrvdY/
|
Just Browsing: “Because We Can” is Not a Good Reason |
The two business books that have most influenced me are Geoffrey Moore’s Crossing the Chasm and Andy Grove’s Only the Paranoid Survive. Grove’s book explains that, for long-term success, established businesses must periodically navigate “strategic inflection points”, moments when a paradigm shift forces them to adopt a new strategy or fade into irrelevance. Moore’s book could be seen as a prequel, outlining strategies for nascent companies to break through and become established themselves.
The key idea of Crossing the Chasm is that technology startups must focus ruthlessly in order to make the jump from early adopters (who will use new products just because they are cool and different) into the mainstream. Moore presents a detailed strategy for marketing discontinuous hi-tech products, but to my mind his broad message is relevant to any company founder. You have a better chance of succeeding if you restrict the scope of your ambitions to the absolute minimum, create a viable business and then grow it from there.
This seems obvious: to compete with companies who have far more resources, a newcomer needs to target a niche where it can fight on an even footing with the big boys (and defeat them with its snazzy new technology). Taking on too much means that financial investment, engineering talent and, worst of all, management attention are diluted by spreading them across multiple projects.
So why do founders consistently jeopardize their prospects by trying to do too much? Let me count the ways.
In my experience the most common issue is an inability to pass up a promising opportunity. The same kind of person who starts their own company tends to be a go-getter with a bias towards action, so they never want to waste a good idea. In the very early stages this is great. Creativity is all about trying as many ideas as possible and seeing what sticks. But once you’ve committed to something that you believe in, taking more bets doesn’t increase your chances of success, it radically decreases them.
Another mistake is not recognizing quickly enough that a project has failed. Failure is rarely total. Every product will have a core group of passionate users or a flashy demo or some unique technology that should be worth something, dammit! The temptation is to let the project drag on even as you move on. Better to take a deep breath and kill it off so you can concentrate on your new challenges, rather than letting it weigh you down for months or years… until you inevitably cancel it anyway.
Sometimes lines of business need to be abandoned even if they are successful. Let’s say you start a small but prosperous company selling specialized accounting software to Lithuanian nail salons. You add a cash-flow forecasting feature and realize after a while that it is better than anything else on the market. Now you have a product that you can sell to any business in any country. But you might as well keep selling your highly specialized accounting package in the meantime, right? After all, it’s still contributing to your top-line revenue. Wrong! You’ve found a much bigger opportunity now and you should dump your older business as soon as financially possible.
Last, but certainly not least, there is the common temptation to try to pack too much into a new product. I’ve talked to many enthusiastic entrepreneurs who are convinced that their product will be complete garbage unless it includes every minute detail of their vast strategic vision. What they don’t realize is that it is going to take much longer than they think to develop something far simpler than what they have in mind. This is where all the hype about the Lean Startup and Minimum Viable Products is spot on. They force you to make tough choices about what you really need before going to market. In the early stages you should be hacking away big chunks of your product spec with a metaphorical machete, not agonizing over every “essential” feature you have to let go.
The common thread is that ambitious, hard-charging individuals, the kind who start companies, have a tough time seeing the downside of plugging away endlessly at old projects, milking every last drop out of old lines of business and taking on every interesting new challenge that comes their way. But if you don’t have a coherent, disciplined strategic view of what you are trying to achieve, if you aren’t willing to strip away every activity that doesn’t contribute to this vision, then you probably aren’t working on the right things.
http://feedproxy.google.com/~r/justdiscourse/browsing/~3/qIgu4yf-jUY/
|
Roberto A. Vitillo: Dasbhoard generator for custom Telemetry jobs |
tldr: Next time you are in need of a dashboard similar to the one used to monitor main-thread IO, please consider using my dashboard generator which takes care of displaying periodically generated data.
So you wrote your custom analysis for Telemetry, your map-reduce job is finally giving you the desired data and you want to set it up so that it runs periodically. You will need some sort of dashboard to monitor the weekly runs but since you don’t really care how it’s done what do you do? You copy paste the code of one of our current dashboards, a little tweak here and there and off you go.
That basically describes all of the recent dashboards, like the one for main-thread IO (mea culpa). Writing dashboards is painful when the only thing you care about is data. Once you finally have what you were looking for, the way you present is often considered an afterthought at best. But maintaining N dashboards becomes quickly unpleasant.
But what makes writing and maintaining dashboards so painful exactly? It’s simply that the more controls you have, the more the different kind events you have to handle and the easier things get out of hand quickly. You start with something small and beautiful that just displays some csv and presto you end up with what should have been properly described as a state machine but instead is a mess of intertwined event handlers.
What I was looking for was something on the line of Shiny for R, but in javascript and with the option to have a client-only based interface. It turns out that React does more or less what I want. It’s not necessary meant for data analysis so there aren’t any plotting facilities but everything is there to roll your own. What makes exactly Shiny and React so useful is that they embrace reactive programming. Once you define a state and a set of dependencies, i.e. a data flow graph in practical terms, changes that affect the state end up being automatically propagated to the right components. Even though this can be seen as overkill for small dashboards, it makes it extremely easy to extend them when the set of possible states expands, which is almost always what happens.
To make things easier for developers I wrote a dashboard generator, iacumus, for use-cases similar to the ones we currently have. It can be used in simple scenarios when:
Iacumus is customizable through a configuration file that is specified through a GET parameter. Since it’s hosted on github, it means you just have to provide the data and don’t even have to spend time deploying the dashboard somewhere, assuming the machine serving the configuration file supports CORS. Here is how the end result looks like using the data for the Add-on startup correlation dashboard. Note that currently Chrome doesn’t handle properly our gzipped datasets and is unable to display anything, in case you wonder…
My next immediate goal is to simplify writing map-reduce jobs for the above mentioned use cases or to the very least write down some guidelines. For instance, some of our dashboards are based on Firefox’s version numbers and not on build-ids, which is really what you want when you desire to make comparisons of Nightly on a weekly basis.
Another interesting thought would be to automatically detect differences in the dashboards and send alerts. That might be not as easy with the current data, since a quick look at the dashboards makes it clear that the rankings fluctuate quite a bit. We would have to collect daily reports and account for the variance of the ranking in those as just using a few weekly datapoints is not reliable enough to account for the deviation.
http://ravitillo.wordpress.com/2014/08/11/dasbhoard-generator-for-custom-telemetry-jobs/
|
Matt Brubeck: Let's build a browser engine! Part 2: Parsing HTML |
This is the second in a series of articles on building a toy browser rendering engine:
- Part 1: Getting started
- Part 2: Parsing HTML
- Part 3: CSS
This article is about parsing HTML source code to produce a tree of DOM nodes. Parsing is a fascinating topic, but I don’t have the time or expertise to give it the introduction it deserves. You can get a detailed introduction to parsing from any good course or book on compilers. Or get a hands-on start by going through the documentation for a parser generator that works with your chosen programming language.
HTML has its own unique parsing algorithm. Unlike parsers for most programming languages and file formats, the HTML parsing algorithm does not reject invalid input. Instead it includes specific error-handling instructions, so web browsers can agree on how to display every web page, even ones that don’t conform to the syntax rules. Web browsers have to do this to be usable: Since non-conforming HTML has been supported since the early days of the web, it is now used in a huge portion of existing web pages.
I didn’t even try to implement the standard HTML parsing algorithm. Instead I wrote a basic parser for a tiny subset of HTML syntax. My parser can handle simple pages like this:
Title
span> id="main" class="test">
Hello world!
The following syntax is allowed:
...
id="main"
world
Everything else is unsupported, including:
&
) and CDATA sections
or
with no closing tag
At each stage of this project I’m writing more or less the minimum code needed to support the later stages. But if you want to learn more about parsing theory and tools, you can be much more ambitious in your own project!
Next, let’s walk through my toy HTML parser, keeping in mind that this is just one way to do it (and probably not the best way). Its structure is based loosely on the tokenizer module from Servo’s cssparser library. It has no real error handling; in most cases, it just aborts when faced with unexpected syntax. The code is in Rust, but I hope it’s fairly readable to anyone who’s used similar-looking languages like Java, C++, or C#. It makes use of the DOM data structures from part 1.
The parser stores its input string and a current position within the string. The position is the index of the next character we haven’t processed yet.
struct Parser {
pos: uint,
input: String,
}
We can use this to implement some simple methods for peeking at the next characters in the input:
impl Parser {
/// Read the next character without consuming it.
fn next_char(&self) -> char {
self.input.as_slice().char_at(self.pos)
}
/// Do the next characters start with the given string?
fn starts_with(&self, s: &str) -> bool {
self.input.as_slice().slice_from(self.pos).starts_with(s)
}
/// Return true if all input is consumed.
fn eof(&self) -> bool {
self.pos >= self.input.len()
}
// ...
}
Rust strings are stored as UTF-8 byte arrays. To go to the next
character, we can’t just advance by one byte. Instead we use char_range_at
which correctly handles multi-byte characters. (If our string used fixed-width
characters, we could just increment pos
.)
/// Return the current character, and advance to the next character.
fn consume_char(&mut self) -> char {
let range = self.input.as_slice().char_range_at(self.pos);
self.pos = range.next;
range.ch
}
Often we will want to consume a string of consecutive characters. The
consume_while
method consumes characters that meet a given condition, and
returns them as a string:
/// Consume characters until `test` returns false.
fn consume_while(&mut self, test: |char| -> bool) -> String {
let mut result = String::new();
while !self.eof() && test(self.next_char()) {
result.push_char(self.consume_char());
}
result
}
We can use this to ignore a sequence of space characters, or to consume a string of alphanumeric characters:
/// Consume and discard zero or more whitespace characters.
fn consume_whitespace(&mut self) {
self.consume_while(|c| c.is_whitespace());
}
/// Parse a tag or attribute name.
fn parse_tag_name(&mut self) -> String {
self.consume_while(|c| match c {
'a'..'z' | 'A'..'Z' | '0'..'9' => true,
_ => false
})
}
Now we’re ready to start parsing HTML. To parse a single node, we look at its
first character to see if it is an element or a text node. In our simplified
version of HTML, a text node can contain any character except <
.
/// Parse a single node.
fn parse_node(&mut self) -> dom::Node {
match self.next_char() {
'<' => self.parse_element(),
_ => self.parse_text()
}
}
/// Parse a text node.
fn parse_text(&mut self) -> dom::Node {
dom::text(self.consume_while(|c| c != '<'))
}
An element is more complicated. It includes opening and closing tags, and between them any number of child nodes:
/// Parse a single element, including its open tag, contents, and closing tag.
fn parse_element(&mut self) -> dom::Node {
// Opening tag.
assert!(self.consume_char() == '<');
let tag_name = self.parse_tag_name();
let attrs = self.parse_attributes();
assert!(self.consume_char() == '>');
// Contents.
let children = self.parse_nodes();
// Closing tag.
assert!(self.consume_char() == '<');
assert!(self.consume_char() == '/');
assert!(self.parse_tag_name() == tag_name);
assert!(self.consume_char() == '>');
dom::elem(tag_name, attrs, children)
}
Parsing attributes is pretty easy in our simplified syntax. Until we reach
the end of the opening tag (>
) we repeatedly look for a name followed by =
and then a string enclosed in quotes.
/// Parse a single name="value" pair.
fn parse_attr(&mut self) -> (String, String) {
let name = self.parse_tag_name();
assert!(self.consume_char() == '=');
let value = self.parse_attr_value();
(name, value)
}
/// Parse a quoted value.
fn parse_attr_value(&mut self) -> String {
let open_quote = self.consume_char();
assert!(open_quote == '"' || open_quote == ''');
let value = self.consume_while(|c| c != open_quote);
assert!(self.consume_char() == open_quote);
value
}
/// Parse a list of name="value" pairs, separated by whitespace.
fn parse_attributes(&mut self) -> dom::AttrMap {
let mut attributes = HashMap::new();
loop {
self.consume_whitespace();
if self.next_char() == '>' {
break;
}
let (name, value) = self.parse_attr();
attributes.insert(name, value);
}
attributes
}
To parse the child nodes, we recursively call parse_node
in a loop until we
reach the closing tag:
/// Parse a sequence of sibling nodes.
fn parse_nodes(&mut self) -> Vec<dom::Node> {
let mut nodes = vec!();
loop {
self.consume_whitespace();
if self.eof() || self.starts_with("span>) {
break;
}
nodes.push(self.parse_node());
}
nodes
}
Finally, we can put this all together to parse an entire HTML document into a DOM tree. This function will create a root node for the document if it doesn’t include one explicitly; this is similar to what a real HTML parser does.
/// Parse an HTML document and return the root element.
pub fn parse(source: String) -> dom::Node {
let mut nodes = Parser { pos: 0u, input: source }.parse_nodes();
// If the document contains a root element, just return it. Otherwise, create one.
if nodes.len() == 1 {
nodes.swap_remove(0).unwrap()
} else {
dom::elem("html".to_string(), HashMap::new(), nodes)
}
}
That’s it! The entire code for the robinson HTML parser. The whole thing weighs in at just over 100 lines of code (not counting blank lines and comments). If you use a good library or parser generator, you can probably build a similar toy parser in even less space.
Here are a few alternate ways to try this out yourself. As before, you can choose one or more of them and ignore the others.
Build a parser (either “by hand” or with a library or parser generator) that takes a subset of HTML as input and produces a tree of DOM nodes.
Modify robinson’s HTML parser to add some missing features, like comments. Or replace it with a better parser, perhaps built with a library or generator.
Create an invalid HTML file that causes your parser (or mine) to fail. Modify the parser to recover from the error and produce a DOM tree for your test file.
If you want to skip parsing completely, you can build a DOM tree programmatically instead, by adding some code like this to your program (in pseudo-code; adjust it to match the DOM code you wrote in Part 1):
// Hello, world!
let root = element("html");
let body = element("body");
root.children.push(body);
body.children.push(text("Hello, world!"));
Or you can find an existing HTML parser and incorporate it into your program.
The next article in this series will cover CSS data structures and parsing.
http://limpet.net/mbrubeck/2014/08/11/toy-layout-engine-2.html
|
Christian Heilmann: Presenter tip: animated GIFs are not as cool as we think |
Disclaimer: I have no right to tell you what to do and how to present – how dare I? You can do whatever you want. I am not “hating” on anything – and I don’t like the term. I am also guilty and will be so in the future of the things I will talk about here. So, bear with me: as someone who spends most of his life currently presenting, being at conferences and coaching people to become presenters, I think it is time for an intervention.
If you are a technical presenter and you consider adding lots of animated GIFs to your slides, stop, and reconsider. Consider other ways to spend your time instead. For example:
Don’t fall for the “oh, but it is cool and everybody else does it” trap. Why? because when everybody does it there is nothing cool or new about it.
Animated GIFs are ubiquitous on the web right now and we all love them. They are short videos that work in any environment, they are funny and – being very pixelated – have a “punk” feel to them.
This, to me, was the reason presenters used them in technical presentations in the first place. They were a disruption, they were fresh, they were different.
We all got bored to tears by corporate presentations that had more bullets than the showdown in a Western movie. We all got fed up with amazingly brushed up presentations by visual aficionados that had just one too many inspiring butterfly or beautiful sunset.
We wanted something gritty, something closer to the metal – just as we are. Let’s be different, let’s disrupt, let’s show a seemingly unconnected animation full of pixels.
This is great and still there are many good reasons to use an animated GIF in our presentations:
But is it? Isn’t a trick that everybody uses way past being disruptive? Are we all unique and different when we all use the same content? How many more times do we have to endure the “this escalated quickly” GIF taken from a 10 year old movie? Let’s not even talk about the issue that we expect the audience to get the reference and why it would be funny.
We’re running the danger here of becoming predictable and boring. Especially when you see speakers who use an animated GIF and know it wasn’t needed and then try to shoe-horn it somehow into their narration. It is not a rite of passage. You should use the right presentation technique to achieve a certain response. A GIF that is in your slides just to be there is like an unused global variable in your code – distracting, bad practice and in general causing confusion.
The reasons why we use animated GIFs (or videos for that matter) in slides are also their main problem:
Well, it isn’t surprising any longer and it can be seen as a cheap way out for us as creators of a presentation. Filler material is filler material, no matter how quirky.
You don’t make a boring topic more interesting by adding animated images. You also don’t make a boring lecture more interesting by sitting on a fart cushion. Sure, it will wake people up and maybe get a giggle but it doesn’t give you a more focused audience. We stopped using 3D transforms in between slides and fiery text as they are seen as a sign of a bad presenter trying to make up for a lack of stage presence or lack of content with shiny things. Don’t be that person.
When it comes to technical presentations there is one important thing to remember: your slides do not matter and are not your presentation. You are.
Your slides are either:
If a slide doesn’t cover any of these cases – remove it. Wallpaper doesn’t blink. It is there to be in the background and make the person in front of it stand out more. You already have to compete with a lot of of other speakers, audience fatigue, technical problems, sound issues, the state of your body and bad lighting. Don’t add to the distractions you have to overcome by adding shiny trinkets of your own making.
You don’t make boring content more interesting by wrapping it in a shiny box. Instead, don’t talk about the boring parts. Make them interesting by approaching them differently, show a URL and a screenshot of the boring resources and tell people what they mean in the context of the topic you talk about. If you’re bored about something you can bet the audience is, too. How you come across is how the audience will react. And insincerity is the worst thing you can project. Being afraid or being shy or just being informative is totally fine. Don’t try too hard to please a current fashion – be yourself and be excited about what you present and the rest falls into place.
So, by all means, use animated GIFs when they fit – give humorous and irreverent presentations. But only do it when this really is you and the rest of your stage persona fits. There are masterful people out there doing this right – Jenn Schiffer comes to mind. If you go for this – go all in. Don’t let the fun parts of your talk steal your thunder. As a presenter, you are entertainer, educator and explainer. It is a mix, and as all mixes go, they only work when they feel rounded and in the right rhythm.
http://christianheilmann.com/2014/08/11/presenter-tip-animated-gifs-are-not-as-cool-as-we-think/
|
Nicholas Nethercote: Some good reading on sexual harassment and being a decent person |
Last week I attended a sexual harassment prevention training seminar. This was the first of several seminars that Mozilla is holding as part of its commendable Diversity and Inclusion Strategy. The content was basically “how to not get sued for sexual harassment in the workplace”. That’s a low bar, but also a reasonable place to start, and the speaker was both informative and entertaining. I’m looking forward to the next seminar on Unconcious Bias and Inclusion, which sounds like it will cover more subtle issues.
With the topic of sexual harassment in mind, I stumbled across a Metafilter discussion from last year about an essay by Genevieve Valentine in which she describes and discusses a number of incidents of sexual harassment that she has experienced throughout her life. I found the essay interesting, but the Metafilter discussion thread even more so. It’s a long thread (594 comments) but mostly high quality. It focuses initially on one kind of harassment that some men perform on public transport, but quickly broadens to be about (a) the full gamut of harassing behaviours that many women face regularly, (b) the responses women make towards these behaviours, and (c) the reactions, both helpful and unhelpful, that people can and do have towards those responses. Examples abound, ranging from the disconcerting to the horrifying.
There are, of course, many other resources on the web where one can learn about such topics. Nonetheless, the many stories that viscerally punctuate this particular thread (and the responses to those stories) helped my understanding of this topic — in particular, how bystanders can intervene when a woman is being harassed — more so than some dryer, more theoretical presentations have. It was well worth my time.
|
Jonas Finnemann Jensen: Using Aggregates from Telemetry Dashboard in Node.js |
When I was working on the aggregation code for telemetry histograms as displayed on the telemetry dashboard, I also wrote a Javascript library (telemetry.js) to access the aggregated histograms presented in the dashboard. The idea was separate concerns and simplify access to the aggregated histogram data, but also to allow others to write custom dashboards presenting this data in different ways. Since then two custom dashboards have appeared:
Both of these dashboards runs a cronjob that downloads the aggregated histogram data using telemetry.js and then aggregates or analyses it in an interesting way before publishing the results on the custom dashboard. However, telemetry.js
was written to be included from telemetry.mozilla.org/v1/telemetry.js, so that we could update the storage format, use a differnet data service, move to a bucket in another region, etc. I still want to maintain the ability to modify telemetry.js
without breaking all the deployments, so I decided to write a node.js module called telemetry-js-node that loads telemetry.js
from telemetry.mozilla.org/v1/telemetry.js.
As evident from the example below, this module is straight forward to use, and exhibits full compatibility with telemetry.js for better and worse.
// Include telemetry.js var Telemetry = require('telemetry-js-node'); // Initialize telemetry.js just the documentation says to Telemetry.init(function() { // Get all versions var versions = Telemetry.versions(); // Pick a version var version = versions[0]; // Load measures for version Telemetry.measures(version, function(measures) { // Print measures available console.log("Measures available for " + version); // List measures Object.keys(measures).forEach(function(measure) { console.log(measure); }); }); });
Whilst there certainly is some valid concerns (and risks) with loading Javascript code over http. This hack allows us to offer a stable API and minimize maintenance for people consuming the telemetry histogram aggregates. And as we’re reusing the existing code the extensive documentation for telemetry is still applicable. See the following links for further details.
Disclaimer: I know it’s not smart to load Javascript code into node.js over http. It’s mostly a security issue as you can’t use telemetry.js
without internet access anyway. But considering that most people will run this as an isolated cron job (using docker, lxc, heroku or an isolated EC2 instance), this seems like an acceptable solution.
By the way, if you make a custom telemetry dashboard, whether it’s using telemetry.js in the browser or Node.js, please file a pull request against telemetry-dashboard on github to have a link for your dashboard included on telemetry.mozilla.org.
http://jonasfj.dk/blog/2014/08/using-aggregates-from-telemetry-dashboard-in-node-js/
|
Jordan Lund: This Week In Releng - Aug 4th, 2014 |
Major Highlights:
Completed work (resolution is 'FIXED'):
http://jordan-lund.ghost.io/this-week-in-releng-aug-4th-2014/
|
Mike Conley: DocShell in a Nutshell – Part 2: The Wonder Years (1999 – 2004) |
When I first announced that I was going to be looking at the roots of DocShell, and how it has changed over the years, I thought I was going to be leafing through a lot of old CVS commits in order to see what went on before the switch to Mercurial.
I thought it’d be so, and indeed it was so. And it was painful. Having worked with DVCS’s like Mercurial and Git so much over the past couple of years, my brain was just not prepared to deal with CVS.
My solution? Take the old CVS tree, and attempt to make a Git repo out of it. Git I can handle.
And so I spent a number of hours trying to use cvs2git to convert my rsync’d mirror of the Mozilla CVS repository into something that I could browse with GitX.
“But why isn’t the CVS history in the Mercurial tree?” I hear you ask. And that’s a good question. It might have to do with the fact that converting the CVS history over is bloody hard – or at least that was my experience. cvs2git has the unfortunate habit of analyzing the entire repository / history and spitting out any errors or corruptions it found at the end.1 This is fine for small repositories, but the Mozilla CVS repo (even back in 1999) was quite substantial, and had quite a bit of history.
So my experience became: run cvs2git, wait 25 minutes, glare at an error message about corruption, scour the web for solutions to the issue, make random stabs at a solution, and repeat.
Not the greatest situation. I did what most people in my position would do, and cast my frustration into the cold, unfeeling void that is Twitter.
But, lo and behold, somebody on the other side of the planet was listening. Unfocused informed me that whoever created the gecko-dev Github mirror somehow managed to type in the black-magic incantations that would import all of the old CVS history into the Git mirror. I simply had to clone gecko-dev, and I was golden.
Thanks Unfocused.
So I had my tree. I cracked open Gitx, put some tea on, and started pouring through the commits from the initial creation of the docshell folder (October 15, 1999) to the last change in that folder just before the switch over to 2005 (December 15, 2004)2.
The following are my notes as I peered through those commits.
Artist’s rendering of me reading some old commit messages. I’m not claiming to have magic powers.
That’s the message for the first commit when the docshell/ folder was first created by Travis Bogard.
Without even looking at the code, that’s a pretty strange commit just by the message alone. No bug number, no reviewer, no approval, nothing even approximating a vague description of what was going on.
Leafing through these early commits, I was surprised to find that quite common. In fact, I learned that it was about a year after this work started that code review suddenly became mandatory for commits.
So, for these first bits of code, nobody seems to be reviewing it – or at least, nobody is signing off on it in commit messages.
Like I mentioned, the date for this commit is October 15, 1999. If the timeline in this Wikipedia article about the history of the Mozilla Suite is reliable, that puts us somewhere between Milestone 10 and Milestone 11 of the first 1.0 Mozilla Suite release.3
That means that at the time that this docshell/ folder was created, the Mozilla source code had been publicly available for over a year4, but nothing had been released from it yet.
Before we continue, who is this intrepid Travis Bogard who is spearheading this embedding initiative and the DocShell / WebShell rewrite?
At the time, according to his LinkedIn page, he worked for America Online (which at this point in time owned Netscape.5) He’d been working for AOL since 1996, working his way up the ranks from lowly intern all the way to Principal Software Engineer.
Travis was the one who originally wrote the wiki page about how painful it was embedding the web engine, and how unwieldy nsWebShell was.6 It was Travis who led the charge to strip away all of the complexity and mess inside of WebShell, and create smaller, more specialized interfaces for the behind the scenes DocShell class, which would carry out most of the work that WebShell had been doing up until that point.7
So, for these first few months, it was Travis who would be doing most of the work on DocShell.
These first few months, Travis puts the pedal to the metal moving things out of WebShell and into DocShell. Remember – the idea was to have a thin, simple nsWebBrowser that embedders could touch, and a fat, complex DocShell that was privately used within Gecko that was accessible via many small, specialized interfaces.
Wholesale replacing or refactoring a major part of the engine is no easy task, however – and since WebShell was core to the very function of the browser (and the mail/news client, and a bunch of other things), there were two copies of WebShell made.
The original WebShell existed in webshell/ under the root directory. The second WebShell, the one that would eventually replace it, existed under docshell/base. The one under docshell/base is the one that Travis was stripping down, but nobody was using it until it was stable. They’d continue using the one under webshell/, until they were satisfied with their implementation by both manual and automated testing.
When they were satisfied, they’d branch off of the main development line, and start removing occurances of WebShell where they didn’t need to be, and replace them with nsWebBrowser or DocShell where appropriate. When they were done that, they’d merge into main line, and celebrate!
At least, that was the plan.
That plan is spelled out here in the Plan of Attack for the redesign. That plan sketches out a rough schedule as well, and targets November 30th, 1999 as the completion point of the project.
This parallel development means that any bugs that get discovered in WebShell during the redesign needs to get fixed in two places – both under webshell/ and docshell/base.
So what was actually changing in the code? In Travis’ first commit, he adds the following interfaces:
along with some build files. Something interesting here is this nsIHTMLDocShell – where it looked like at this point, the plan was to have different DocShell interfaces depending on the type of document being displayed. Later on, we see this idea dissipate.
If DocShell was a person, these are its baby pictures. At this point, nsIDocShell has just two methods: LoadDocument, LoadDocumentVia, and a single nsIDOMDocument attribute for the document.
And here’s the interface for WebShell, which Travis was basing these new interfaces off of. Note that there’s no LoadDocument, or LoadDocumentVia, or an attribute for an nsIDOMDocument. So it seems this wasn’t just a straight-forward breakup into smaller interfaces – this was a rewrite, with new interfaces to replace the functionality of the old one.8
This is consistent with the remarks in this wikipage where it was mentioned that the new DocShell interfaces should have an API for the caller to supply a document, instead of a URI – thus taking the responsibility of calling into the networking library away from DocShell and putting it on the caller.
nsIDocShellEdit seems to be a replacement for some of the functions of the old nsIClipboardCommands methods that WebShell relied upon. Specifically, this interface was concerned with cutting, copying and pasting selections within the document. There is also a method for searching. These methods are all just stubbed out, and don’t do much at this point.
nsIDocShellFile seems to be the interface used for printing and saving documents.
nsIGenericWindow (which I believe is the ancestor of nsIBaseWindow), seems to be an interface that some embedding window must implement in order for the new nsWebBrowser / DocShell to be embedded in it. I think. I’m not too clear on this. At the very least, I think it’s supposed to be a generic interface for windows supplied by the underlying operating system.
nsIGlobalHistory is an interface for, well, browsing history. This was before tabs, so we had just a single, linear global history to maintain, and I guess that’s what this interface was for.
nsIScrollable is an interface for manipulating the scroll position of a document.
So these magnificent seven new interfaces were the first steps in breaking up WebShell… what was next?
nsIDocShellContainer was created so that the DocShells could be formed into a tree and enumerated, and so that child DocShells could be named. It was introduced in this commit.
In this commit, only five days after the first landing, Travis appears to reverse the decision to pass the responsibility of loading the document onto the caller of DocShell. LoadDocument and LoadDocumentVia are replaced by LoadURI and LoadURIVia. Steve Clark (aka “buster”) is also added to the authors list of the nsIDocShell interface. It’s not clear to me why this decision was reversed, but if I had to guess, I’d say it proved to be too much of a burden on the callers to load all of the documents themselves. Perhaps they punted on that goal, and decided to tackle it again later (though I will point out that today’s nsIDocShell still has LoadURI defined in it).
The first implementation of nsIDocShell showed up on October 25, 1999. It was nsHTMLDocShell, and with the exception of nsIGlobalHistory, it implemented all of the other interfaces that I listed in Travis’ first landing.
On October 25th, the stubs of a DocShell base implementation showed up in the repository. The idea, I would imagine, is that for each of the document types that Gecko can display, we’d have a DocShell implementation, and each of these DocShell implementations would inherit from this DocShell base class, and only override the things that they need specialized for their particular document type.
Later on, when the idea of having specialized DocShell implementations evaporates, this base class will end up being nsDocShell.cpp.
The message for this commit on October 27th, 1999 is pretty interesting. It reads:
added a bunch of initial implementation. does not compile yet, but that’s ok because docshell isn’t part of the build yet.
So not only are none of these patches being reviewed (as far as I can tell), and are not mapped to any bugs in the bug tracker, but the patches themselves just straight-up do not build. They are not building on tinderbox.
This is in pretty stark contrast to today’s code conventions. While it’s true that we might land code that is not entered for most Nightly users, we usually hide such code behind an about:config pref so that developers can flip it on to test it. And I think it’s pretty rare (if it ever occurs) for us to land code in mozilla-central that’s not immediately put into the build system.
Perhaps the WebShell tests that were part of the Plan of Attack were being written in parallel and just haven’t landed, but I suspect that they haven’t been written at all at this point. I suspect that the team was trying to stand something up and make it partially work, and then write tests for WebShell and try to make them pass for both old WebShell and DocShell. Or maybe just the latter.
These days, I think that’s probably how we’d go about such a major re-architecture / redesign / refactor; we’d write tests for the old component, land code that builds but is only entered via an about:config pref, and then work on porting the tests over to the new component. Once the tests pass for both, flip the pref for our Nightly users and let people test the new stuff. Once it feels stable, take it up the trains. And once it ships and it doesn’t look like anything is critically wrong with the new component, begin the process of removing the old component / tests and getting rid of the about:config pref.
Note that I’m not at all bashing Travis or the other developers who were working on this stuff back then – I’m simply remarking on how far we’ve come in terms of development practices.
Tangentially, I’m seeing some patches go by that have to do with hooking up some kind of “Keyword” support to WebShell.
Remember those keywords? This was the pre-Google era where there were only a few simplistic search engines around, and people were still trying to solve discoverability of things on the web. Keywords was, I believe, AOL’s attempt at a solution.
You can read up on AOL Keywords here. I just thought it was interesting to find some Keywords support being written in here.
Now that we have decided that there is only one docshell for all content types, we needed to get rid of the base class/ content type implementation. This checkin takes and moves the nsDocShellBase to be nsDocShell. It now holds the nsIHTMLDocShell stuff. This will be going away. nsCDocShell was created to replace the previous nsCHTMLDocShell.
This commit lands on November 12th (almost a month from the first landing), and is the point where the DocShell-implementation-per-document-type plan breaks down. nsDocShellBase gets renamed to nsDocShell, and the nsIHTMLDocShell interface gets moved into nsIDocShell.idl, where a comment above it indicates that the interface will soon go away.
We have nsCDocShell.idl, but this interface will eventually disappear as well.
So, this commit message on November 13th caught my eye:
pork jockey paint fixes. bug=18140, r=kmcclusk,pavlov
What the hell is a “pork jockey”? A quick search around, and I see yet another reference to it in Bugzilla on bug 14928. It seems to be some kind of project… or code name…
I eventually found this ancient wiki page that documents some of the language used in bugs on Bugzilla, and it has an entry for “pork jockey”: a pork jockey bug is a “bug for work needed on infrastructure/architecture”.
I mentioned this in #developers, and dmose (who was hacking on Mozilla code at the time), explained:
16:52 (dmose) mconley: so, porkjockeys
16:52 (mconley) let’s hear it
16:52 (dmose) mconley: at some point long ago, there was some infrastrcture work that needed to happen
16:52 mconley flips on tape recorder
16:52 (dmose) and when people we’re talking about it, it seemed very hard to carry off
16:52 (dmose) somebody said that that would happen on the same day he saw pigs fly
16:53 (mconley) ah hah
16:53 (dmose) so ultimately the group of people in charge of trying to make that happen were…
16:53 (dmose) the porkjockeys
16:53 (dmose) which was the name of the mailing list too
Here’s the e-mail that Brendan Eich sent out to get the Porkjockey’s flying.
On November 17th, the nsIGenericWindow interface was removed because it was being implemented in widget/base/nsIBaseWindow.idl.
On November 27th, nsWebShell started to implement nsIBaseWindow, which helped pull a bunch of methods out of the WebShell implementations.
On November 29th, nsWebShell now implements nsIDocShell – so this seems to be the first point where the DocShell work gets brought into code paths that might be hit. This is particularly interesting, because he makes this change to both the WebShell implementation that he has under the docshell/ folder, as well as the WebShell implementation under the webshell/ folder. This means that some of the DocShell code is now actually being used.
On November 30th, Travis lands a patch to remove some old commented out code. The commit message mentions that the nsIDocShellEdit and nsIDocShellFile interfaces introduced in the first landing are now defunct. It doesn’t look like anything is diving in to replace these interfaces straight away, so it looks like he’s just not worrying about it just yet. The defunct interfaces are removed in this commit one day later.
One day later, nsIDocShellTreeNode interface is added to replace nsIDocShellContainer. The interface is almost identical to nsIDocShellContainer, except that it allows the caller to access child DocShells at particular indices as opposed to just returning an enumerator.
December 3rd was a very big day! Highlights include:
Noticing something? A lot of these changes are getting dumped straight into the live version of WebShell (under the webshell/ directory). That’s not really what the Plan of Attack had spelled out, but that’s what appears to be happening. Perhaps all of this stuff was trivial enough that it didn’t warrant waiting for the WebShell fork to switch over.
On December 12th, nsIDocShellTreeOwner is introduced.
On December 15th, buster re-lands the nsIDocShellEdit and nsIDocShellFile interfaces that were removed on November 30th, but they’re called nsIContentViewerEdit and nsIContentViewerFile, respectively. Otherwise, they’re identical.
On December 17th, WebShell becomes a subclass of DocShell. This means that a bunch of things can get removed from WebShell, since they’re being taken care of by the parent DocShell class. This is a pretty significant move in the whole “replacing WebShell” strategy.
Similar work occurs on December 20th, where even more methods inside WebShell start to forward to the base DocShell class.
That’s the last bit of notable work during 1999. These next bits show up in the new year, and provides further proof that we didn’t all blow up during Y2K.
On Feburary 2nd, 2000, a new interface called nsIWebNavigation shows up. This interface is still used to this day to navigate a browser, and to get information about whether it can go “forwards” or “backwards”.
On February 8th, a patch lands that makes nsGlobalWindow deal entirely in DocShells instead of WebShells. nsIScriptGlobalObject also now deals entirely with DocShells. This is a pretty big move, and the patch is sizeable.
On February 11th, more methods are removed from WebShell, since the refactorings and rearchitecture have made them obsolete.
On February 14th, for Valentine’s day, Travis lands a patch to have DocShell implement the nsIWebNavigation interface. Later on, he lands a patch that relinquishes further control from WebShell, and puts the DocShell in control of providing the script environment and providing the nsIScriptGlobalObjectOwner interface. Not much later, he lands a patch that implements the Stop method from the nsIWebNavigation interface for DocShell. It’s not being used yet, but it won’t be long now. Valentine’s day was busy!
On February 24th, more stuff (like the old Stop implementation) gets gutted from WebShell. Some, if not all, of those methods get forwarded to the underlying DocShell, unsurprisingly.
Similar story on February 29th, where a bunch of the scroll methods are gutted from WebShell, and redirected to the underlying DocShell. This one actually has a bug and some reviewers!9 Travis also landed a patch that gets DocShell set up to be able to create its own content viewers for various documents.
March 10th saw Travis gut plenty of methods from WebShell and redirect to DocShell instead. These include Init, SetDocLoaderObserver, GetDocLoaderObserver, SetParent, GetParent, GetChildCount, AddChild, RemoveChild, ChildAt, GetName, SetName, FindChildWithName, SetChromeEventHandler, GetContentViewer, IsBusy, SetDocument, StopBeforeRequestingURL, StopAfterURLAvailable, GetMarginWidth, SetMarginWidth, GetMarginHeight, SetMarginHeight, SetZoom, GetZoom. A few follow-up patches did something similar. That must have been super satisfying.
March 11th, Travis removes the Back, Forward, CanBack and CanForward methods from WebShell. Consumers of those can use the nsIWebNavigation interface on the DocShell instead.
March 30th sees the nsIDocShellLoadInfo interface show up. This interface is for “specifying information used in a nsIDocShell::loadURI call”. I guess this is certainly better than adding a huge amount of arguments to ::loadURI.
During all of this, I’m seeing references to a “new session history” being worked on. I’m not really exploring session history (at this point), so I’m not highlighting those commits, but I do want to point out that a replacement for the old Netscape session history stuff was underway during all of this DocShell business, and the work intersected quite a bit.
On April 16th, Travis lands a commit that takes yet another big chunk out of WebShell in terms of loading documents and navigation. The new session history is now being used instead of the old.
We’re approaching what appears to be the end of the DocShell work. According to his LinkedIn profile, Travis left AOL in May 2000. His last commit to the repository before he left was on April 24th. Big props to Travis for all of the work he put in on this project – by the time he left, WebShell was quite a bit simpler than when he started. I somehow don’t think he reached the end state that he had envisioned when he’d written the original redesign document – the work doesn’t appear to be done. WebShell is still around (in fact, parts of it around were around until only recently!10 ). Still, it was a hell of chunk of work he put in.
And if I’m interpreting the rest of the commits after this correctly, there is a slow but steady drop off in large architectural changes, and a more concerted effort to stabilize DocShell, nsWebBrowser and nsWebShell. I suspect this is because everybody was buckling down trying to ship the first version of the Mozilla Suite (which finally occurred June 5th, 2002 – still more than 2 years down the road).
There are still some notable commits though. I’ll keep listing them off.
On June 22nd, a developer called “rpotts” lands a patch to remove the SetDocument method from DocShell, and to give the implementation / responsibility of setting the document on implementations of nsIContentViewer.
July 5th sees rpotts move the new session history methods from nsIWebNavigation to a new interface called nsIDocShellHistory. It’s starting to feel like the new session history is really heating up.
On July 18th, a developer named Judson Valeski lands a large patch with the commit message “webshell-docshell consolodation changes”. Paraphrasing from the bug, the point of this patch is to move WebShell into the DocShell lib to reduce the memory footprint. This also appears to be a lot of cleanup of the DocShell code. Declarations are moved into header files. The nsDocShellModule is greatly simplified with some macros. It looks like some dead code is removed as well.
On November 9th, a developer named “disttsc” moves the nsIContentViewer interface from the webshell folder to the docshell folder, and converts it from a manually created .h to an .idl. The commit message states that this work is necessary to fix bug 46200, which was filed to remove nsIBrowserInstance (according to that bug, nsIBrowserInstance must die).
That’s probably the last big, notable change to DocShell during the 2000's.
On March 8th, a developer named “Dan M” moves the GetPersistence and SetPersistence methods from nsIWebBrowserChrome to nsIDocShellTreeOwner. He sounds like he didn’t really want to do it, or didn’t want to be pegged with the responsibility of the decision – the commit message states “embedding API review meeting made me do it.” This work was tracked in bug 69918.
On April 16th, Judson Valeski makes it so that the mimetypes that a DocShell can handle are not hardcoded into the implementation. Instead, handlers can be registered via the CategoryManager. This work was tracked in bug 40772.
On April 26th, a developer named Simon Fraser adds an implementation of nsISimpleEnumerator for DocShells. This implementation is called, unsurprisingly, nsDocShellEnumerator. This was for bug 76758. A method for retrieving an enumerator is added one day later in a patch that fixes a number of bugs, all related to the page find feature.
April 27th saw the first of the NSPR logging for DocShell get added to the code by a developer named Chris Waterson. Work for that was tracked in bug 76898.
On May 16th, for bug 79608, Brian Stell landed a getter and setter for the character set for a particular DocShell.
There’s a big gap here, where the majority of the landings are relatively minor bug fixes, cleanup, or only slightly related to DocShell’s purpose, and not worth mentioning.11
On January 8th, 2002, for bug 113970, Stephen Walker lands a patch that takes yet another big chunk out of WebShell, and added this to the nsIWebShell.h header:
/** * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING !!!! * * THIS INTERFACE IS DEPRECATED. DO NOT ADD STUFF OR CODE TO IT!!!! */
I’m actually surprised it too so long for something like this to get added to the nsIWebShell interface – though perhaps there was a shared understanding that nsIWebShell was shrinking, and such a notice wasn’t really needed.
On January 9th, 2003 (yes, a whole year later – I didn’t find much worth mentioning in the intervening time), I see the first reference to “deCOMtamination”, which is an effort to reduce the amount of XPCOM-style code being used. You can read up more on deCOMtamination here.
On January 13th, 2003, Nisheeth Ranjan lands a patch to use “machine learning” in order to order results in the urlbar autocomplete list. I guess this was the precursor to the frencency algorithm that the AwesomeBar uses today? Interestingly, this code was backed out again on February 21st, 2003 for reasons that aren’t immediately clear – but it looks like, according to this comment, the code was meant to be temporary in order to gather “weights” from participants in the Mozilla 1.3 beta, which could then be hard-coded into the product. The machine-learning bug got closed on June 25th, 2009 due to AwesomeBar and frecency.
On Februrary 11th, 2004, the onbeforeunload event is introduced.
On April 17, 2004, gerv lands the first of several patches to switch the licensing of the code over to the MPL/LGPL/GPL tri-license. That’d be MPL 1.1.
On November 23rd, 2004, the parent and treeOwner attributes for nsIDocShellTreeItem are made scriptable. They are read-only for script.
And that’s probably the last notable patch related to DocShell in 2004.
Reading through all of these commits in the docshell/ and webshell/ folders is a bit like taking a core sample of a very mature tree, and reading its rings. I can see some really important events occurring as I flip through these commits – from the very birth of Mozilla, to the birth of XPCOM and XUL, to porkjockeys, and the start of the embedding efforts… all the way to the splitting out of Thunderbird, deCOMtamination and introduction of the MPL. I really got a sense of the history of the Mozilla project reading through these commits.
I feel like I’m getting a better and better sense of where DocShell came from, and why it does what it does. I hope if you’re reading this, you’re getting that same sense.
Stay tuned for the next bit, where I look at years 2005 to 2010.
Messages like: ERROR: A CVS repository cannot contain both cvsroot/mozilla/browser/base/content/metadata.js,v and cvsroot/mozilla/browser/base/content/Attic/metadata.js,v, for example
http://mikeconley.ca/blog/2014/08/10/docshell-in-a-nutshell-part-2-the-wonder-years-1999-2004/
|
Peter Bengtsson: Gzip rules the world of optimization, often |
So I have a massive chunk of JSON that a Django view is sending to a piece of Angular that displays it nicely on the page. It's big. 674Kb actually. And it's likely going to be bigger in the near future. It's basically a list of dicts. It looks something like this:
>>> pprint(d['events'][0]) {u'archive_time': None, u'archive_url': u'/manage/events/archive/1113/', u'channels': [u'Main'], u'duplicate_url': u'/manage/events/duplicate/1113/', u'id': 1113, u'is_upcoming': True, u'location': u'Cyberspace - Pacific Time', u'modified': u'2014-08-06T22:04:11.727733+00:00', u'privacy': u'public', u'privacy_display': u'Public', u'slug': u'bugzilla-development-meeting-20141115', u'start_time': u'15 Nov 2014 02:00PM', u'start_time_iso': u'2014-11-15T14:00:00-08:00', u'status': u'scheduled', u'status_display': u'Scheduled', u'thumbnail': {u'height': 32, u'url': u'/media/cache/e7/1a/e71a58099a0b4cf1621ef3a9fe5ba121.png', u'width': 32}, u'title': u'Bugzilla Development Meeting'}
So I thought one hackish simplification would be to convert each of these dicts into an list with a known sort order. Something like this:
>>> event = d['events'][0] >>> pprint([event[k] for k in sorted(event)]) [None, u'/manage/events/archive/1113/', [u'Main'], u'/manage/events/duplicate/1113/', 1113, True, u'Cyberspace - Pacific Time', u'2014-08-06T22:04:11.727733+00:00', u'public', u'Public', u'bugzilla-development-meeting-20141115', u'15 Nov 2014 02:00PM', u'2014-11-15T14:00:00-08:00', u'scheduled', u'Scheduled', {u'height': 32, u'url': u'/media/cache/e7/1a/e71a58099a0b4cf1621ef3a9fe5ba121.png', u'width': 32}, u'Bugzilla Development Meeting']
So I converted my sample events.json
file like that:
$ l -h events* -rw-r--r-- 1 peterbe wheel 674K Aug 8 14:08 events.json -rw-r--r-- 1 peterbe wheel 423K Aug 8 15:06 events.optimized.json
Excitingly the file is now 250Kb smaller because it no longer contains all those keys.
Now, I'd also send the order of the keys so I could do something like this in the AngularJS code:
.success(function(response) { events = [] response.events.forEach(function(event) { var new_event = {} response.keys.forEach(function(key, i) { new_event[k] = event[i] }) }) })
Yuck! Nested loops! It was just getting more and more complicated.
Also, if there are keys that are not present in every element, it means I'd have to replace them with None
.
At this point I stopped and I could smell the hackish stink of sulfur of the hole I was digging myself into.
Then it occurred to me, gzip is really good at compressing repeated things which is something we have plenty of in a document store type data structure that a list of dicts is.
So I packed them manually to see what we could get:
$ apack events.json.gz events.json $ apack events.optimized.json.gz events.optimized.json
And without further ado...
$ l -h events* -rw-r--r-- 1 peterbe wheel 674K Aug 8 14:08 events.json -rw-r--r-- 1 peterbe wheel 90K Aug 8 14:20 events.json.gz -rw-r--r-- 1 peterbe wheel 423K Aug 8 15:06 events.optimized.json -rw-r--r-- 1 peterbe wheel 81K Aug 8 15:07 events.optimized.json.gz
Basically, all that complicated and slow hoopla for saving 10Kb. No thank you.
Thank you gzip for existing!
http://www.peterbe.com/plog/gzip-rules-the-world-of-optimization
|
Mozilla Release Management Team: Firefox 32 beta4 to beta5 |
Extension | Occurrences |
cpp | 19 |
h | 16 |
js | 3 |
ini | 3 |
html | 3 |
xml | 2 |
xhtml | 2 |
java | 2 |
in | 2 |
txt | 1 |
py | 1 |
jsm | 1 |
dep | 1 |
c | 1 |
build | 1 |
asm | 1 |
Module | Occurrences |
content | 14 |
dom | 12 |
security | 9 |
mobile | 5 |
netwerk | 4 |
js | 4 |
toolkit | 3 |
docshell | 3 |
media | 2 |
browser | 2 |
memory | 1 |
List of changesets:
Brian Hackett | Bug 1037666. r=billm, a=abillings - 784c7fb4c431 |
Byron Campen [:bwc] | Bug 963524 - Avoid setting SO_REUSEADDR when binding a UDP socket to port 0, since the linux kernel might select an already open port. r=mcmanus, a=sledru - 92364eef664a |
Mike Hommey | Bug 1047791 - Use integers for audio when on Android, or when using ARM on other OSes, and disable webm encoding. r=padenot, a=NPOTB - 333e7f930c63 |
Boris Zbarsky | Bug 1045096 - Make sure initial about:blank in iframes have a nsDOMNavigationTiming object, so we don't end up with window.performance throwing when accessed on their window. r=smaug, a=sledru - 70277dbb9071 |
Bobby Holley | Bug 1048330 - Null-check the XBL scope in more places. r=smaug, a=sledru - f5df74fab22f |
Brian Nicholson | Bug 987864 - Move API 13 styles to values-v13 folder. r=wesj, a=sledru - 68181edc64c1 |
Blair McBride | Bug 1024073 - Whitelist plugin: Roblox Plugin launcher. r=gfritzsche, a=sledru - cda6534d9780 |
Blair McBride | Bug 1029654 - Whitelist plugin: Box Edit. r=gfritzsche, a=sledru - 4d812a850eb1 |
Blair McBride | Bug 1024965 - Whitelist plugin: Nexus Personal. r=gfritzsche, a=sledru - c2fc1e357ca0 |
Martin Thomson | Bug 1048261 - Safe dispatch from DTLS connect to PeerConnectionImpl. r=jesup, r=bwc, a=abillings - adb28e85421f |
Kai Engert | Bug, 1048876, Update Mozilla 32 to use NSS 3.16.4, a=lmandel - 22589028e561 |
Cameron McCormack | Bug 1018524 - Make copies of more SVGLength objects when manipulating SVGLengthLists. r=longsonr, a=lmandel - 3315c53c4bb7 |
Cameron McCormack | Bug 1040575 - Make a copy of SVGSVGElement.currentTranslate if it is inserted into an SVGPointList. r=longsonr, a=lmandel - 4da65dc7d057 |
Valentin Gosu | Bug 1035007 - Make sure hostname is inserted in the right place. r=mcmanus, a=sledru - e6cee3b7907e |
Ben Kelly | Bug 995688 - Always show scrollbars in test to avoid fade effect evicting document from BF cache. r=smaug, a=test-only - 8f34703f5065 |
Richard Newman | Bug 1049217 - Fix CharacterValidator for API levels below 12. r=margaret, a=sledru - fc7ce6481ea9 |
Randell Jesup | Bug 1037000 - Include "default communications device" in the audio input enumeration for gUM. r=padenot, a=sledru - ee74d30a8968 |
Gregory Szorc | Bug 1045421 - Remove date time bomb from test_crash_manager.js, add logging. r=gfritzsche, a=test-only - ac0afa7b1b25 |
Jason Orendorff | Bug 1043690 - Part 1: Provide helper function for HTMLDocument and HTMLFormElement proxies to use from [[Set]]. r=efaust, a=lmandel - 8375886783f2 |
Boris Zbarsky | Bug 1043690 - Part 2: Change the codegen for DOM proxies to ignore named props when looking up property descriptors on [[Set]]. r=efaust, a=lmandel - 06542873b0dc |
Jan de Mooij | Bug 1041148 - Move HoldJSObjects call to XMLHttpRequest constructor to simplify the code. r=bz, a=lmandel - 7b29fabbf26a |
Ryan VanderMeulen | Bug 1043690 - Remove extraneous const usage. r=jorendorff, a=bustage - c755d28a5266 |
Michael Comella | Bug 1047264 - Dynamically retrieve Views for Display Mode on tablet. r=lucasr, a=sledru - e8fbf14de311 |
Richard Newman | Bug 1047549 - Copy libraries out of the APK when they're missing. r=blassey, a=lmandel - 9d8f79b400bf |
Andrew McCreight | Bug 1038243 - Avoid static casting from nsIDOMAttr to Attr. r=smaug, a=lmandel - 551f71d3138f |
Michael Wu | Bug 1044193 - Always cleanup on heap allocation path. r=glandium, a=lmandel - e51295fe2c54 |
Jonas Jenwald | Bug 1028735 - Revert one aspect of CIDFontType2 font parsing to the state prior to CMAP landing. r=yury, a=lmandel - 599c7756380c |
http://release.mozilla.org//statistics/32/2014/08/09/fx-32-b4-to-b5.html
|
Sean Bolton: Community Lessons from LEGO (and other thoughts on community) |
Communities form when you find a group of people that you feel you can be yourself around. In this environment, you don’t have to self-edit as much to fit in. You get the feeling that these people share a similar view of the world in some way. Communities form when the answer to, “are they like me?” is “yes.”
It’s not very surprising then that communities can form around brands as brands often represent a certain view of the world. Smart companies notice this and they engage these people in a win-win partnership to give their community value and to create value for the organization. That is no easy task. Here is a bit about how LEGO does it…
LEGO cares deeply about their community. They know that these people drive their brand, provide the best form of marketing and can help fuel new product development. And the community members get a powerful sense of fulfillment in meeting similar people and getting to be more of a creator than a consumer – they get to make LEGO their own. When working with community LEGO follows these principles (a non-exhaustive list):
LEGO has high quality standards and the way their community team works is no exception. They have a communication structure that empowers people to help and learn from each other so that not every person needs to communicate with LEGO directly. There are designated ‘ambassadors’ that communicate directly with LEGO – they help distill and clarify communication, taking a sort of leadership role in the community. This helps LEGO better focus resources and helps build a stronger sense of community among members (win-win).
There is a massive community surrounding LEGO, over 300K. To reference, we currently have about 8K at Mozilla. While our communities do different things, we are all fundamentally driven to be part of that group that makes us feel like we can be more of ourselves. It gives people a sense of belonging and fulfillment – something we all want in life. That is why community management matters. Without it, these large groups of people can’t exist and that sense of belonging can be easily lost.
[Post featured on Mozilla's Community blog.]
http://seanbolton.me/2014/08/08/community-lessons-from-lego-and-other-thoughts-on-community/
|
Kim Moir: Mozilla pushes - July 2014 |
http://relengofthenerds.blogspot.com/2014/08/mozilla-pushes-july-2014.html
|
Eric Shepherd: The Sheppy Report: August 8, 2014 |
It’s been another good week of Making Things Happen. I’m pleased with the productivity this week: not just mine, but the entire writing community’s.
As usual, what I did this week doesn’t entirely line up with what I’d expected, but it was still productive, which is the important thing, right?
Work continued on finishing up the doc project planning page migration work, and better integration with other pages on MDN and elsewhere. I also put together the first draft of the WebGL doc plan.
I’m working on trying to reshuffle my many personal appointments that happen regularly to less often interfere with meetings, but unfortunately there’s only so much I can do.
dev-doc-needed
keyword to man WebGL 2.0 related bugs./docs/
hierarchy.ContentFromWikimo
, which imports the content of a specified block (by ID) from a page on wikimo and inserts it into the MDN page.ContentFromWikimo
macro to embed module owner information about WebRTC, WebGL, Web Workers, and XPCOM to their doc plans.So, whew! Lots done! I’m particularly proud of the ContentFromWikimo
macro work. It was also a lot of fun to do. I think it’ll be useful, too, at least sometimes.
I have a good feeling about next week. I think it’ll be even more productive!
http://www.bitstampede.com/2014/08/08/the-sheppy-report-august-8-2014/
|