ZoomBySite and Safari 7 – More Details

I wrote about ZoomBySite not working well with Safari 7 in ZoomBySite and Safari 7:

When a page loads, the ZoomBySite extension checks to see whether a zoom level has been saved for the page’s domain. To do this, a little bit of Javascript on the page sends a message over to the extension, which checks its database of zoom levels, and if one is found, sends a message back to the page with the desired zoom level. The problem with Safari 7 is that when the extension tries to send the message back to the page, it fails. I tried several different workarounds with no success.

As it turned out, the problem was actually with the extension trying to look at the URL of the page, which was always empty when loading in an empty tab or contained the “wrong” URL when loaded in an existing tab (instead of containing the actual URL of page as had been the case in prior versions of Safari). The extension looks at the URL of the page in order to make sure that it’s sending the zoom level to the correct page.

This change in behavior was due to a performance enhancement in Safari related to the preloading of pages. This is documented in the Safari Extension Guide in the Messages and Proxies section (under the ‘Tabs in Safari 6.1 and Later’ heading). This section explains that in some situations, “Safari 6.1 and later may preload webpages in the background to improve the user experience.” It goes on to explain that when you send a message from an extension to a tab, it goes to the live page (as expected) and also to any pages that are being preloaded. There are ways to tell whether the page receiving the message is live (for example, checking document.hidden). There’s also a visibility change Javascript event that can be used to detect the status of the page changing.

As far as I can tell, the change that broke ZoomBySite was that this preloading is now also done when typing in a URL in the address bar. In this case, the page started loading before you finished typing the URL and hitting enter. When ZoomBySite checked the URL of the page, it was either the URL of the previous page (in which case unless the domain was the same, the zoom level wouldn’t change) or if the URL was being typed into an empty tab, it was missing (also causing the zoom level not to change).

There is a preference for turning off this preloading behavior for the address bar in Safari Preferences (Privacy tab -> Do not preload Top Hit in the background). I didn’t try turning this on to see if it fixed ZoomBySite, but it should have. With a well-behaved extension, it’s definitely better to leave this enabled as it improves performance.

The fix for this was to move the check the domain from the extension to the page. In this case, the page knows its domain and can ignore zoom messages that are targeted to a different domain.

Again, thanks to Apple for pointing out the problem with ZoomBySite and also for providing a suggested fix!