| Index: safari/ext/background.js |
| =================================================================== |
| --- a/safari/ext/background.js |
| +++ b/safari/ext/background.js |
| @@ -17,6 +17,13 @@ |
| (function() |
| { |
| + var isPreloadedPage = function(message, tab) |
| + { |
| + // the message was sent by a preloaded page if document.hidden was set, despite the tab is visible |
| + return message.isDocumentHidden && tab.browserWindow.visible && tab.browserWindow.activeTab == tab |
| + }; |
| + |
| + |
| /* Events */ |
| var TabEventTarget = function() |
| @@ -38,6 +45,7 @@ |
| var LoadingTabEventTarget = function(target) |
| { |
| WrappedEventTarget.call(this, target, "message", false); |
| + this._preloadedTabs = new TabMap(); |
| }; |
| LoadingTabEventTarget.prototype = { |
| __proto__: WrappedEventTarget.prototype, |
| @@ -45,9 +53,35 @@ |
| { |
| return function (event) |
| { |
| - if (event.name == "loading") |
| - listener(new Tab(event.target)); |
| - }; |
| + switch (event.name) |
| + { |
| + case "loading": |
| + var tab = new Tab(event.target); |
| + |
| + // when the "loading" message was sent form a preloaded |
|
Wladimir Palant
2014/01/24 14:11:34
form => from
|
| + // page in Safari 7.0, we have to wait until the page is |
| + // shown, before calling the listener. The high-level code |
| + // doesn't know anything about preloaded pages and expects |
| + // all events to be related to the current visible page. |
| + if (isPreloadedPage(event.message, event.target)) |
| + this._preloadedTabs.set(tab, null); |
| + else |
| + { |
| + this._preloadedTabs.delete(tab); |
| + listener(tab); |
| + } |
| + |
| + break; |
| + case "show": |
| + var tab = new Tab(event.target); |
| + |
| + if (this._preloadedTabs.has(tab)) |
| + { |
| + this._preloadedTabs.delete(tab); |
|
Wladimir Palant
2014/01/24 14:11:34
What if a preloaded page is simply discarded? Won'
Sebastian Noack
2014/01/24 14:17:49
Just temporarily until another page is loaded in t
|
| + listener(tab); |
| + } |
| + } |
| + }.bind(this); |
| } |
| }; |
| @@ -71,6 +105,23 @@ |
| event.target |
| ) |
| }; |
| + }, |
| + _ignoreIf: function(event) |
| + { |
| + // when receiving a message from a preloaded page in Safari 7.0, we |
| + // have to defer procesing of that message, until the page is shown. |
| + // The high-level code doesn't know anything about preloaded pages |
| + // and expects all message to be sent from the current visible page. |
| + if (isPreloadedPage(event.message, event.target)) |
| + { |
| + event.target.page.dispatchMessage("response", { |
| + requestId: event.message.requestId, |
| + deferred: true |
| + }); |
| + return true; |
| + } |
| + |
| + return false; |
| } |
| }; |
| @@ -104,8 +155,19 @@ |
| sendMessage: function(message, responseCallback) |
| { |
| _sendMessage( |
| - message, responseCallback, |
| - this._tab.page, this._tab |
| + // message payload |
| + message, |
| + // response callback |
| + responseCallback && function(response) { responseCallback(response.payload); }, |
| + // message dispatcher |
| + this._tab.page, |
| + // response event target |
| + this._tab, |
| + // extra data |
| + { |
| + isTabVisible: this._tab.browserWindow.visible && |
| + this._tab.browserWindow.activeTab == this._tab |
| + } |
| ); |
| } |
| }; |
| @@ -574,16 +636,23 @@ |
| _handleMessage: function(message, rawTab) |
| { |
| + // we have to defer loading of resources on preloaded pages |
| + // in Safari 7.0, until the page is shown. The high-level code |
| + // doesn't know anything about preloaded pages and expects all |
| + // web requests to be related to the current visible page. |
| + if (isPreloadedPage(message, rawTab)) |
| + return "deferred"; |
| + |
| var tab = new Tab(rawTab); |
| var frame = new Frame(message.documentUrl, message.isTopLevel, rawTab); |
| for (var i = 0; i < this._listeners.length; i++) |
| { |
| if (this._listeners[i](message.url, message.type, tab, frame) === false) |
| - return false; |
| + return "blocked"; |
| } |
| - return true; |
| + return "ok"; |
| }, |
| addListener: function(listener) |
| { |