IE7 Tabbed Browsing Implementation

The information published in this post is now out-of-date and one or more links are invalid.

—IEBlog Editor, 21 August 2012

Hey, I’m Tony Schreiner, a developer on the IE team. I’ve been working on IE for a little over a year, and at Microsoft for over six years. My personal blog is over here, but I'm posting on the official IE blog to help consolidate useful information about IE7.

My role has been to re-architect IE to support tabbed browsing. This work began last year and includes building a new frame (top-level window and chrome), sorting out how to host and switch between multiple instances of the browser, and managing communication between the various internal components.

There have been a lot of questions and speculation about IE7's tabbed browsing feature, so I wanted to give an overview of some of the work we've done that you can look forward to seeing in Beta 1.

Keeping the User in Control

Our philosophy for tabbed browsing is to keep the user in control of the experience. Tabs are on by default in IE7 Beta 1, but for those that do not want to use them they shouldn't be intrusive and there's a setting to turn them off and reclaim the screen real estate if desired.

Regarding script, there is no "target='_tab'" feature or any direct access to tabs from script beyond what is available with multiple windows today. We are working on balancing the default behavior for whether a window opened from script opens as in a new frame or a tab. Currently, windows that have been customized, such as hiding a toolbar or making the window non-resizable, will default to opening in their own standalone frame, whereas ordinary pop-up windows will open in a new foreground tab. CTRL-clicking and middle-clicking links will open those links in a background tab. The rationale for opening only customized windows in a new frame is that this seems to correlate with scenarios where showing a window on top of the current window is desirable, such as replying to posts on internet message boards and getting a close-up view of items on shopping sites. Naturally we will continue to refine the default behavior and provide settings to customize the behavior.

In addition there is ongoing work to tweak the DOM so that window operations behave in a compatible but non-intrusive way. For example, window.move() will continue to allow a web site or applications that automate IE (more on this later) to move the frame, when there is a single tab open, but when multiple tabs are opened this will have no effect. These tweaks will allow IE to behave as expected for compatibility, but should help prevent sites from tampering with the browser when you have a set of tabs open.

IE7 Beta 1 has most of the core features you expect from a tabbed browser. You are able to open links in a new tab by middle-clicking or Ctrl-clicking links. You can switch between tabs quickly and easily using both the keyboard and mouse. You can control whether tabs open in the background or foreground, or open them in a new window as you always have. This core functionality is largely catch-up to other browsers which support tabs, but a necessary foundation for future work.

Adding Tabs to IE

The biggest challenge of implementing tabbed browsing is that IE was originally written as a single-window browser, and many of its features were designed around this assumption. It’s a bit ironic that the IE platform is made up of easily reusable components that make it possible for anyone to build a simple browser in a weekend using the Web Browser Control (WebOC), yet internally IE was factored in such a way that makes tabbed browsing difficult to implement.

One of the reasons IE is architected differently than a 3rd party browser that hosts the WebOC is that the IE frame and WebOC were written by the essentially same team and evolved in lockstep. While care was taken to keep components reasonably abstracted from one another using COM interfaces, the internal separation between these components is not as clear as a 3rd party browser built on top of the final public interfaces. Within IE6 the frame and WebOC are more like peers, and if you look at the MSDN documentation for IWebBrowser2 you can see the effects of this: some methods on that interface are only available when you’re building an application that invokes IE using automation (CLSID_InternetExplorer), while others are also available when your application hosts the WebOC (CLSID_WebBrowser). This means that internally, components such as menus and toolbars were tightly integrated with the browser.

Another example of what makes this challenging is that IE and Explorer windows share the same code for the frame and chrome (toolbars, menus, etc.), which means there are more code paths and different types of interactions with the hosted view (in this case, a ShellView) that were required to continue working after adding tabbed browsing to IE.

Finally, preserving compatibility with 3rd party add-ons and applications that host or leverage IE is an ongoing challenge. More on this later.

Implementing Tabs

We considered a variety of approaches and built a couple prototypes, and the solution we settled on was to essentially push a large part of what you see in IE6 into a tab. We built a new frame to host the browsers and wrote a bunch of internal plumbing to manage them and cache state. This is a bit of a simplification; the address bar and so on won’t be part of the tab of course, but 3rd party toolbars and Browser Helper Objects (BHOs) are because they are tied to a single browser and sometimes make deep assumptions about how they are hosted.

The address bar, back and forward buttons, and similar controls are still part of the frame. This required significant changes to the way these components interact with the browser. The old model was that they were directly connected to a single browser, frequently probing (sometimes deeply) through the object model to find out what type of content was being hosted and what capabilities were supported. They communicated directly to these objects and interfaces within the browser and cached pointers for performance and convenience. We untangled the communication so that the controls could flexibly target any tab and eliminated assumptions that were no longer valid. Similarly, we hooked them up to use the cached state for each tab because they can no longer sink the browser’s events directly.

One design decision worth calling out is that our current implementation is fully multithreaded. Each tab is on a separate thread, and the frame is also on its own thread. This has some impact on the overall footprint of IE, but we believe this will allow IE7 to feel faster and provide an overall better user experience. Internally this creates some additional complexity as we have to deal with a lot of cross-thread communication, but it also gives us a way to do things we wouldn’t otherwise be able to do with a single-threaded approach.

Compatibility

As I mentioned above, one of the deciding factors for our design was to preserve compatibility with 3rd party applications: both add-ons and hosts. Web sites are a concern too, especially with the DOM tweaks, but this feature is relatively benign in that regard.

As a caveat, I should add that compatibility is an ongoing challenge, and in addition to tabbed browsing there are many other changes across Longhorn that we’ve needed to be careful about. As a general rule, ActiveX controls and add-ons such as toolbars that interact with the browser and "lower" components through published interfaces should not have much trouble, whereas add-ons that walk up and down the window hierarchy using Win32 APIs such as GetParent(), subclass windows, or do other things that depend on internal implementation details will have more trouble. In general, applications that host the WebOC should not be impacted.

I’ll elaborate on this more and give some examples of some of the problems we’ve seen in a future post.

- Tony