In this episode, I kept my camera off, since I was having some audio-sync issues1.
I was also under some time-pressure, because I had a meeting scheduled for 2:30 ET2, giving me exactly 1.5 hours to do what I needed to do.
And what did I need to do?
I needed to figure out why an nsISHEntry, when passed to nsIWebPageDescriptor’s loadPage, was not enough to get the document out from the HTTP cache in some cases. 1.5 hours to figure it out – the pressure was on!
I don’t recall writing a single line of code. Instead, I spent most of my time inside XCode, walking through various scenarios in the debugger, trying to figure out what was going on. And I eventually figured it out! Read this footnote for the TL;DR:3
I should have those resolved for Episode 11! ↩
And when the stream finished, I found out the meeting had been postponed to next week, meaning that next week will also be a short episode. :( ↩
Basically, the nsIChannel used to retrieve data over the network is implemented by HttpChannelChild in the content process. HttpChannelChild is really just a proxy to a proper nsIChannel on the parent-side. On the child side, HttpChannelChild does not implement nsICachingChannel, which means we cannot get a cache key from it when creating a session history entry. With no cache key, comes no ability to retrieve the document from the network cache via nsIWebDescriptor’s loadPage. ↩
For example, here is where we synthesize native mouse events for OS X. I think this is mostly used for testing when we want to simulate mouse activity.
Note that if you attempt to replay a queue of synthesized (or cached) native Cocoa events to trackSwipeEventWithOptions, those events might get coalesced and not behave the way you want. mstange and I ran into this while working on this bug to get some basic gesture support working with Nightly+e10s (Specifically, the history swiping gesture on OS X).
We were able to determine that OS X was coalescing the events because we grabbed the section of code that implements trackSwipeEventWithOptions, and used the Hopper Disassembler to decompile the assembly into some pseudocode. After reading it through, we found some logging messages in there referring to coalescing. We noticed that those log messages were only sent when NSDebugSwipeTrackingLogic was set to true, we executed this:defaults write org.mozilla.nightlydebug NSDebugSwipeTrackingLogic -bool YES
In the console, and then re-ran our swiping test in a debug build of Nightly to see what messages came out. Sure enough, this is what we saw:2015-04-09 15:11:55.395 firefox[5203:707] ___trackSwipeWithScrollEvent_block_invoke_0 coalescing scrollevents 2015-04-09 15:11:55.395 firefox[5203:707] ___trackSwipeWithScrollEvent_block_invoke_0 cumulativeDelta:-2.000 progress:-0.002 2015-04-09 15:11:55.395 firefox[5203:707] ___trackSwipeWithScrollEvent_block_invoke_0 cumulativeDelta:-2.000 progress:-0.002 adjusted:-0.002 2015-04-09 15:11:55.396 firefox[5203:707] ___trackSwipeWithScrollEvent_block_invoke_0 call trackingHandler(NSEventPhaseChanged, gestureAmount:-0.002)
This coalescing means that trackSwipeEventWithOptions is only getting a subset of the events that we’re sending, which is not what we had intended. It’s still not clear what triggers the coalescing – I suspect it might have to do with how rapidly we flush our native event queue, but mstange suspects it might be more sophisticated than that. Unfortunately, the pseudocode doesn’t make it too clear.String templates and toSource might run the risk of higher memory use?
I’m not sure I “learned” this so much, but I saw it in passing this week in this bug. Apparently, there was some section of the Marionette testing framework that was doing request / response logging with toSource and some string templates, and this caused a 20MB regression on AWSY. Doing away with those in favour of old-school string concatenation and JSON.stringify seems to have addressed the issue.When you change the remote attribute on a <xul:browser> you need to re-add the <xul:browser> to the DOM tree
I think I knew this a while back, but I’d forgotten it. I actually re-figured it out during the last episode of The Joy of Coding. When you change the remoteness of a <xul:browser>, you can’t just flip the remote attribute and call it a day. You actually have to remove it from the DOM and re-add it in order for the change to manifest properly.
You also have to re-add any frame scripts you had specially loaded into the previous incarnation of the browser before you flipped the remoteness attribute.1Using Mercurial, and want to re-land a patch that got backed out? hg graft is your friend!
Suppose you got backed out, and want to reland your patch(es) with some small changes. Try this:hg update -r tip hg graft --force BASEREV:ENDREV
This will re-land your changes on top of tip. Note that you need –force, otherwise Mercurial will skip over changes it notices have already landed in the commit ancestry.
Here’s the documentation for hg graft.
In this episode1, I continued the work we had started in Episode 8, by trying to make it so that we don’t hit the network when viewing the source of a page in multi-process Firefox.
It was a little bit of a slog – after some thinking, I decided to undo some of the work we had done in the previous episode, and then I set up the messaging infrastructure for talking to the remote browser in the view source window.
I also rebased and landed a patch that we had written in the previous episode, after fixing up some nits2.
Then, I (re)-learned that flipping the “remote” attribute of a browser is not enough in order for it to run out-of-process; I have to remove it from the DOM, and then re-add it. And once it’s been re-added, I have to reload any frame scripts that I had loaded in the previous incarnation of the browser.
Anyhow, by the end of the episode, we were able to view the source from a remote browser inside a remote view source browser!3 That’s a pretty big deal!
A note that I also tried an experiment where I keep my camera running during the entire session, and place the feed into the bottom right-hand corner of the recording. It looks like there were some synchronization issues between audio and video, which are a bit irritating. Sorry about that! I’ll see what I can do about that. ↩
and dropping a nit having conversed with :gabor about it ↩
We were still loading it off the network though, so I need to figure out what’s going on there in the next episode. ↩
This is my second post in a weekly series, where I attempt to distill my week down into some lessons or facts that I’ve picked up. Let’s get to it!ES6 – what’s safe to use in browser development?
As of March 27, 2015, ES6 classes are still not yet safe for use in production browser code. There’s code to support them in Firefox, but they’re Nightly-only behind a build-time pref.
However, any of the rest of the ES6 Harmony work currently implemented by Nightly is fair-game for use, according to jorendorff. The JS team is also working on a Wiki page to tell us Firefox developers what ES6 stuff is safe for use and what is not.Getting a profile from a hung process
According to mstange, it is possible to get profiles from hung Firefox processes using lldb1.
- After the process has hung, attach lldb.
- Type in2, : p (void)mozilla_sampler_save_profile_to_file("somepath/profile.txt")
- Clone mstange’s handy profile analysis repository.
python symbolicate_profile.py somepath/profile.txt
To graft symbols into the profile. mstange’s scripts do some fairly clever things to get those symbols – if your Firefox was built by Mozilla, then it will retrieve the symbols from the Mozilla symbol server. If you built Firefox yourself, it will attempt to use some cleverness3 to grab the symbols from your binary.
Your profile will now, hopefully, be updated with symbols.
Then, load up Cleopatra, and upload the profile.
I haven’t yet had the opportunity to try this, but I hope to next week. I’d be eager to hear people’s experience giving this a go – it might be a great tool in determining what’s going on in Firefox when it’s hung4!
I noticed that when I talked about “things that I passed to functions5”, I would use “arguments” and “parameters” interchangeably. I recently learned that there is more to those terms than I had originally thought.
According to this MSDN article, an argument is what is passed in to a function by a caller. To the function, it has received parameters. It’s like two sides of a coin. Or, as the article puts it, like cars and parking spaces:
You can think of the parameter as a parking space and the argument as an automobile. Just as different automobiles can park in a parking space at different times, the calling code can pass a different argument to the same parameter every time that it calls the procedure.6
Not that it really makes much difference, but I like knowing the details.
Unfortunately, this technique will not work for Windows. ↩
A binary called dump_syms_mac in mstange’s toolkit, and nm on Linux ↩
Or methods. ↩