| Index: safari/ext/background.js |
| =================================================================== |
| --- a/safari/ext/background.js |
| +++ b/safari/ext/background.js |
| @@ -52,6 +52,10 @@ |
| { |
| this._tab.activate(); |
| }, |
| + close: function() |
| + { |
| + this._tab.close(); |
| + }, |
| sendMessage: function(message, responseCallback) |
| { |
| this._messageProxy.sendMessage(message, responseCallback, {pageId: this._id}); |
| @@ -119,7 +123,8 @@ |
| callback(matchedPages); |
| }, |
| - onLoading: new ext._EventTarget() |
| + onLoading: new ext._EventTarget(), |
| + onPopup: new ext._EventTarget() |
| }; |
| safari.application.addEventListener("close", function(event) |
| @@ -523,6 +528,50 @@ |
| /* Message processing */ |
| + var findPageAndFrame = function(tab, url) |
| + { |
| + var page = null; |
| + var frame = null; |
| + |
| + var lastPage; |
| + var lastPageTopLevelFrame; |
| + |
| + // find the parent frame and its page for this sub frame, |
| + // 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) |
| + { |
| + var curPage = pages[curPageId]; |
| + if (tab && curPage._tab != tab) |
| + continue; |
| + |
| + for (var i = 0; i < curPage._frames.length; i++) |
| + { |
| + var curFrame = curPage._frames[i]; |
| + |
| + if (curFrame.url == url) |
| + { |
| + page = curPage; |
| + frame = curFrame; |
| + } |
| + |
| + if (i == 0) |
| + { |
| + lastPage = curPage; |
| + lastPageTopLevelFrame = curFrame; |
| + } |
| + } |
| + } |
| + |
| + // if we can't find the parent frame and its page, fall back to |
| + // the page most recently loaded in the tab and its top level frame |
| + return { |
| + page: page || lastPage, |
| + frame: frame || lastPageTopLevelFrame |
| + }; |
| + }; |
| + |
| safari.application.addEventListener("message", function(event) |
| { |
| switch (event.name) |
| @@ -540,76 +589,50 @@ |
| frameId = 0; |
| var isPrerendered = event.message.isPrerendered; |
| - var page = pages[pageId] = new Page( |
| + var page = new Page( |
| pageId, |
| event.target, |
| event.message.url, |
| isPrerendered |
| ); |
| - // when a new 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 |
| - // you enter a new URL in the address bar. |
| - if (!isPrerendered) |
| - replacePage(page); |
| + if (event.message.isPopup && !event.target._popupLoaded) |
| + { |
| + if (!("_opener" in event.target)) |
| + event.target._opener = findPageAndFrame(null, event.message.referrer); |
| - ext.pages.onLoading._dispatch(page); |
| + if (page.url != "about:blank") |
| + event.target._popupLoaded = true; |
| + |
| + ext.pages.onPopup._dispatch(page, event.target._opener); |
| + } |
| + |
| + if (event.target.browserWindow) |
| + { |
| + pages[pageId] = page; |
| + |
| + // when a new 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 |
| + // you enter a new URL in the address bar. |
| + if (!isPrerendered) |
| + replacePage(page); |
| + |
| + ext.pages.onLoading._dispatch(page); |
| + } |
| } |
| else |
| { |
| - var page; |
| - var parentFrame; |
| + var parent = findPageAndFrame(event.target, event.message.referrer); |
| - var lastPageId; |
| - var lastPage; |
| - var lastPageTopLevelFrame; |
| + pageId = parent.page._id; |
| + frameId = parent.page._frames.length; |
| - // find the parent frame and its page for this sub frame, |
| - // 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) |
| - { |
| - var curPage = pages[curPageId]; |
| - if (curPage._tab != event.target) |
| - continue; |
| - |
| - for (var i = 0; i < curPage._frames.length; i++) |
| - { |
| - var curFrame = curPage._frames[i]; |
| - |
| - if (curFrame.url == event.message.referrer) |
| - { |
| - pageId = curPageId; |
| - page = curPage; |
| - parentFrame = curFrame; |
| - } |
| - |
| - if (i == 0) |
| - { |
| - lastPageId = curPageId; |
| - lastPage = curPage; |
| - lastPageTopLevelFrame = curFrame; |
| - } |
| - } |
| - } |
| - |
| - // if we can't find the parent frame and its page, fall back to |
| - // the page most recently loaded in the tab and its top level frame |
| - if (!page) |
| - { |
| - pageId = lastPageId; |
| - page = lastPage; |
| - parentFrame = lastPageTopLevelFrame; |
| - } |
| - |
| - frameId = page._frames.length; |
| - page._frames.push({ |
| + parent.page._frames.push({ |
| url: event.message.url, |
| - parent: parentFrame |
| + parent: parent.frame |
| }); |
| } |