Index: safari/ext/background.js
===================================================================
--- a/safari/ext/background.js
+++ b/safari/ext/background.js
@@ -22,12 +22,11 @@
   var pages = {__proto__: null};
   var pageCounter = 0;
 
-  var Page = function(id, tab, url, prerendered)
+  var Page = function(id, tab, url)
   {
     this._id = id;
     this._tab = tab;
     this._frames = [{url: url, parent: null}];
-    this._prerendered = prerendered;
 
     if (tab.page)
       this._messageProxy = new ext._MessageProxy(tab.page);
@@ -64,20 +63,25 @@
 
   var isPageActive = function(page)
   {
-    return page._tab == page._tab.browserWindow.activeTab && !page._prerendered;
+    var tab = page._tab;
+    return tab == tab.browserWindow.activeTab && page == tab._visiblePage;
   };
 
   var forgetPage = function(id)
   {
     ext._removeFromAllPageMaps(id);
+
+    delete pages[id]._tab._pages[id];
     delete pages[id];
   };
 
   var replacePage = function(page)
   {
-    for (var id in pages)
+    page._tab._visiblePage = page;
+
+    for (var id in page._tab._pages)
     {
-      if (id != page._id && pages[id]._tab == page._tab)
+      if (id != page._id)
         forgetPage(id);
     }
 
@@ -139,11 +143,8 @@
     // tab. Note that it wouldn't be sufficient do that when the old page
     // is unloading, because Safari dispatches window.onunload only when
     // reloading the page or following links, but not when closing the tab.
-    for (var id in pages)
-    {
-      if (pages[id]._tab == event.target)
-        forgetPage(id);
-    }
+    for (var id in event.target._pages)
+      forgetPage(id);
   }, true);
 
 
@@ -227,18 +228,7 @@
     // became active. If we can't find that page (e.g. when a page was
     // opened in a new tab, and our content script didn't run yet), the
     // toolbar item of the window, is reset to its intial configuration.
-    var activePage = null;
-    for (var id in pages)
-    {
-      var page = pages[id];
-      if (page._tab == event.target && !page._prerendered)
-      {
-        activePage = page;
-        break;
-      }
-    }
-
-    updateToolbarItemForPage(activePage, event.target.browserWindow);
+    updateToolbarItemForPage(event.target._visiblePage, event.target.browserWindow);
   }, true);
 
 
@@ -540,11 +530,9 @@
     // by matching its referrer with the URL of frames previously
     // loaded in the same tab. If there is more than one match,
     // the most recent loaded page and frame is preferred.
-    for (var curPageId in pages)
+    for (var curPageId in (tab ? tab._pages : pages))
     {
       var curPage = pages[curPageId];
-      if (tab && curPage._tab != tab)
-        continue;
 
       for (var i = 0; i < curPage._frames.length; i++)
       {
@@ -580,36 +568,33 @@
         switch (event.message.category)
         {
           case "loading":
+            var tab = event.target;
+            var message = event.message;
+
             var pageId;
             var frameId;
 
-            if (event.message.isTopLevel)
+            if (message.isTopLevel)
             {
               pageId = ++pageCounter;
               frameId = 0;
 
-              var isPrerendered = event.message.isPrerendered;
-              var page = new Page(
-                pageId,
-                event.target,
-                event.message.url,
-                isPrerendered
-              );
+              var page = new Page(pageId, tab, message.url);
 
-              if (event.message.isPopup && !event.target._popupLoaded)
+              if (message.isPopup && !tab._popupLoaded)
               {
-                if (!("_opener" in event.target))
-                  event.target._opener = findPageAndFrame(null, event.message.referrer);
+                if (!("_opener" in tab))
+                  tab._opener = findPageAndFrame(null, message.referrer);
 
                 if (page.url != "about:blank")
-                  event.target._popupLoaded = true;
+                  tab._popupLoaded = true;
 
-                ext.pages.onPopup._dispatch(page, event.target._opener);
+                ext.pages.onPopup._dispatch(page, tab._opener);
               }
 
-              if (event.target.browserWindow)
+              if (tab.browserWindow)
               {
-                pages[pageId] = page;
+                pages[pageId] = (tab._pages || (tab._pages = {__proto__: null}))[pageId] = page;
 
                 // when a new page is shown, forget the previous page associated
                 // with its tab, and reset the toolbar item if necessary.
@@ -617,7 +602,7 @@
                 // page is unloading, because Safari dispatches window.onunload
                 // only when reloading the page or following links, but not when
                 // you enter a new URL in the address bar.
-                if (!isPrerendered)
+                if (!message.isPrerendered)
                   replacePage(page);
 
                 ext.pages.onLoading._dispatch(page);
@@ -625,15 +610,12 @@
             }
             else
             {
-              var parent = findPageAndFrame(event.target, event.message.referrer);
+              var parent = findPageAndFrame(tab, message.referrer);
 
               pageId  = parent.page._id;
               frameId = parent.page._frames.length;
 
-              parent.page._frames.push({
-                url: event.message.url,
-                parent: parent.frame
-              });
+              parent.page._frames.push({url: message.url, parent: parent.frame});
             }
 
             event.message = {pageId: pageId, frameId: frameId};
@@ -662,16 +644,13 @@
         pages[event.message.pageId]._messageProxy.handleResponse(event.message);
         break;
       case "replaced":
-        var page = pages[event.message.pageId];
-        page._prerendered = false;
-
         // when a prerendered page is shown, forget the previous page
         // associated with its tab, and reset the toolbar item if necessary.
         // Note that it wouldn't be sufficient to do that when the old
         // page is unloading, because Safari dispatches window.onunload
         // only when reloading the page or following links, but not when
         // the current page is replaced with a prerendered page.
-        replacePage(page);
+        replacePage(pages[event.message.pageId]);
         break;
     }
   });
