Aero Snap for Chrome
One hurdle that has always stopped me from adopting Chrome is something that I could easily fix in Firefox. That being, adding a little bit of padding above the tab bar, while maximized, so that you can instantly move your mouse upwards and drag downwards to restore the window. This is Aero Snap, a feature of Windows 7, and it’s great for moving browsers from monitor to monitor. The problem without this padding is explained in my Firefox article, here: http://digitaldj.net/2011/01/26/a-little-firefox-4-tweak-extra-padding-when-maximized/
The TLDR version: without the padding, when you have a full tab bar, you have to search for gaps in the tabs to pull down the window, otherwise you’ll end up dragging a tab off the bar. This makes it impossible to perform a reflex action, pushing the mouse to the top of the screen and pulling the window. After all, the time taken to acquire a target if it’s tiny is far longer than if it’s huge (Fitts’s Law).
In Firefox, the solution was simple. Since the UI is basically CSS, you can add an extension to dynamically tweak it. In Chrome, this is a little more complex since the skinning engine in Chrome only allows you to change images and not the actual look and feel of the UI. It’s all hard coded. Thankfully, Chrome is Open Source.
I figured it’d be pretty easy to grab the Chrome source, poke around and add a little tweak. However, I soon realized this is going to be rather tedious. Since the Chrome team pushes releases extremely often, compiling a new version with the tweak each time would be time consuming. An initial compile takes up to an hour on a fast machine, with subsequent compiles taking 5-10 minutes. This wasn’t really an option, so instead I thought maybe I could binary patch the file. This is that journey.
Setting up the initial development environment is fairly easy. The Chromium page has a fantastic How-To for the build instructions (http://www.chromium.org/developers/how-tos/build-instructions-windows). After I was up and running in Visual Studio, the initial compile took at least an hour. A long the lines I stumbled into an error with pyautolib. A fix outlined in Chromium Issue 83936 (http://code.google.com/p/chromium/issues/detail?id=83936) got me back on the right track and with a successful compile. Hooray!
Now it was time to find the code that dealt with building the UI. After doing some keyword searches (particularly “aero”), I found the file “glass_browser_frame_view.cc” which contained a set of constants outlined below:

The comment for ‘kTabstripTopShadowThickness’ was spot on for what I wanted: “… in maximized mode we push this off the top of the screen so the tabs appear flush against the screen edge.” After doing a quick search for references to the variable I found the method “NonClientTopBorderHeight”:

The method basically determines the top border of thickness for the browser window. When it’s restored, there’s 11px of thickness (“kNonClientRestoredExtraThickness”). However, when maximized, there is no thickness and the tab’s shadow is removed, pushing it against the top edge of the screen. If we instead set this to 0, the tab’s shadow would be visible but would still result in the same dragging tab off bar problem. However, if we set it to 1, we have 1px of frame thickness, just enough for a mouse flick and drag. I gave this a shot, and after a short-ish compile, success!

Now for the more interesting bit: how on earth was I going to convert this into a generic binary patch without a lot of trial and error? Symbols, of course! Google publish the symbols for release versions of Chrome for debugging at http://chromium-browser-symsrv.commondatastorage.googleapis.com. I figured I could use WinDbg to load up a Release version of Chrome (15.0.874.120 in this case), add the symbols, search for the method then determine the file offset for better analysis in IDA.
So, I opened up WinDbg, attached to chrome.exe and searched for the offset of “NonClientTopBorderHeight” using command “x chrome*!*NonClientTopBorderHeight”. This gives back 4 different methods, all for different UI types. In this case, we want the GlassBrowserFrameView which is used for Aero. I presume OpaqueBrowserFrameView is used when Aero is disabled or for legacy Windows (i.e. XP).

Now that I had the offset and what the hex of the method looked like, I could use IDA to set things out a little more neatly in a flow chart:

What we see here is a flow chart of just the return statement of the method shown earlier. As numbered:
1: Check the “restored” variable. If false, jump to 2, else jump to 3.
2: Check IsMaximized(). If true, jump to 4, else jump to 3.
3: Box 3 is the result of being in a restored state. This is where it pushes the value 0x0B, which is 11 in decimal (the value of kNonClientRestoredExtraThickness). This gives the extra frame border.
4: Box 4 is the result of being in a maximized state. This is the negative of “kTabstripTopShadowThickness”
5: Add the thickness to the GetSystemMetricsCall (not important)
Fortunately, both “or esi, 0FFFFFFFFh” and “push 0Bh, pop esi” commands are exactly 3 bytes (0x83ceff vs 0x6a0b5e). Therefore, we can replace “or esi, 0FFFFFFFFh” (0x83ceff) with “push 01h, pop esi” (0x6a015e) without doing anything too fancy to the executable, just a simple binary replace. This would give us 1 pixel of frame border when maximized.
Huzzah, a binary patch! I haven’t yet created an automatic patcher, but all you need to do is open up chrome.dll in your favorite hex editor. This is located in “%LOCALAPPDATA%\Google\Chrome\Application\
From here, I can either create a generic patcher or maybe something that launches Chrome and patches it in memory. At least the memory patching way wouldn’t require a patch each time Chrome is updated. More on that in the near future. I also want to change the default CTRL+T shortcut to duplicate a tab. Hopefully I can create a simple binary patch for that too.




