The Privacy Impact of Add-ons: New APIs for IE8

By default, when starting a new session using IE8's InPrivate Browsing feature, toolbars and Browser Helper Objects are disabled. This is done to help protect the user's privacy: many toolbars and extensions maintain their own navigation/search/etc history lists, and such lists could violate the user's expectation of privacy while InPrivate Browsing is enabled. In contrast, ActiveX controls remain enabled while browsing InPrivate because many sites rely on such controls, and they are somewhat less likely to track users' state in a way that impacts privacy.

To enable all browser extensions (ActiveX, BHOs, and toolbars) to be more privacy-conscious, IE8 includes a new API to allow add-ons to detect when they are running inside a private browsing session. The IEIsInPrivateBrowsing() function returns a boolean value indicating whether the current browser instance is running InPrivate. Your extension only needs to check this API once per session, because entering and exiting InPrivate Browsing results in the creation/teardown of the browser instance (and hence your add-on). Stated another way, you need not worry that the return value of this API will change during the lifetime of the process.

When IEIsInPrivateBrowsing() returns TRUE, your extension should do the following things:

  • Do not allow script/network access to any persistent state information generated from a previous session (e.g. start with an empty cookie jar, DOMStorage, etc). 
  • Downgrade any attempts to alter persistent state (e.g. cookies, DOMStorage, or equivalents) to session-based state that is cleared on exit.
  • Avoid making any changes to data stores (e.g. disk caches, registry, etc) unless those changes are reverted on exit. 

By supporting the IEIsInPrivateBrowsing API, you can ensure that your add-on is respectful of the user's privacy choices. Even if you're implementing a BHO or toolbar, you should consider supporting this API because end-users may choose to enable toolbars and BHOs while InPrivate by unchecking the Disable toolbars and extension when InPrivate Browsing starts option on the Privacy tab of the Internet Options dialog.

In addition to the IEIsInPrivateBrowsing API, we've added a new API that allows extensions to be notified when users delete their browsing history. This notification enables extensions to clean up their own state according to the user's preferences. To receive the notification, register your COM object in the COM Component Category CATID_DeleteBrowsingHistory.  When a cleanup takes place, Internet Explorer will load your object and call your implementation of DeleteBrowsingHistory(), passing flags which indicate which types of state should be cleared. In some cases, you will need to make logical assumptions about the user's intent: for instance, if the DELETE_BROWSING_HISTORY_COOKIES flag is passed, you should clear any state that would be considered equivalent to a cookie (e.g. DOMStorage elements), and so forth. 

Unfortunately, supporting the DELETE_BROWSING_HISTORY_PRESERVEFAVORITES flag is a non-trivial exercise, as IE8 does not include a IsHostNameAFavoriteOrHomePage(strHost) API. Therefore, an extension wishing to respect this flag must itself determine whether each stored item originates from a site within the user's Favorites or Homepages list. This requires mining the user's Favorites and Homepages to gather of a list of exempt domains or hostnames, then determining if each storage item is exempt based on that list. 

To build the exempt-hostname list from the user's Favorites, you'll need to iterate the Internet Shortcut files in the special folder CSIDL_FAVORITES. For each file, you'll need to CoCreateInstance CLSID_InternetShortcut, call IPersistFile Load to load the favorite, then call the GetURL method on the IUniformResourceLocatorW interface. Be sure to test with RSS Feed items and WebSlices too!

Next, add in the list of hostnames gleaned from the user's homepages.

After you have the URLs, use IURI to parse each. If the Uri_PROPERTY_DOMAIN is null (because the URL contains a plainhostname) then extract Uri_PROPERTY_HOST instead. Add each Domain or Host to the exempt list.

Finally, when deleting stored items, use this exemption list to preserve the data from the exempt domains/hostnames list.

Thanks for your help in allowing users to maintain control of their privacy!