Massive overhaul/fixes to core Safari event capturing

This commit is contained in:
Chris 2015-01-19 01:50:10 -07:00
parent 5ee417e110
commit 11bb0e9638
2 changed files with 33 additions and 61 deletions

View File

@ -190,21 +190,32 @@ vAPI.tabs = {
vAPI.tabs.registerListeners = function() {
var onNavigation = this.onNavigation;
this.onNavigation = function(e) {
// e.url is not present for local files or data URIs,
// or probably for those URLs which we don't have access to
if ( !e.target || !e.target.url ) {
safari.application.addEventListener('beforeNavigate', function(e) {
if ( !e.target || !e.target.url || e.target.url === 'about:blank' ) {
return;
}
onNavigation({
frameId: 0,
tabId: vAPI.tabs.getTabId(e.target),
url: e.target.url
});
var url = e.target.url, tabId = vAPI.tabs.getTabId(e.target);
if ( vAPI.tabs.popupCandidate ) {
var details = {
url: url,
tabId: tabId,
sourceTabId: vAPI.tabs.popupCandidate
};
safari.application.addEventListener('navigate', this.onNavigation, true);
vAPI.tabs.popupCandidate = false;
if ( vAPI.tabs.onPopup(details) ) {
e.preventDefault();
if ( vAPI.tabs.stack[details.sourceTabId] ) {
vAPI.tabs.stack[details.sourceTabId].activate();
}
return;
}
}
onNavigation({
url: url,
frameId: 0,
tabId: tabId
});
}, true);
// onClosed handled in the main tab-close event
// onUpdated handled via monitoring the history.pushState on web-pages
@ -577,27 +588,6 @@ vAPI.messaging.broadcast = function(message) {
/******************************************************************************/
safari.application.addEventListener('beforeNavigate', function(e) {
if ( !vAPI.tabs.popupCandidate || e.url === 'about:blank' ) {
return;
}
var details = {
url: e.url,
tabId: vAPI.tabs.getTabId(e.target),
sourceTabId: vAPI.tabs.popupCandidate
};
vAPI.tabs.popupCandidate = null;
if ( vAPI.tabs.onPopup(details) ) {
e.preventDefault();
if ( vAPI.tabs.stack[details.sourceTabId] ) {
vAPI.tabs.stack[details.sourceTabId].activate();
}
}
}, true);
/******************************************************************************/

View File

@ -191,47 +191,31 @@ if ( location.protocol === 'safari-extension:' ) {
/******************************************************************************/
window.MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
if ( !window.MutationObserver ) {
// Dummy, minimalistic shim for older versions (<6)
// only supports node insertions, but currently we don't use it for anything else
window.MutationObserver = function(handler) {
this.observe = function(target) {
target.addEventListener('DOMNodeInserted', function(e) {
handler([{ addedNodes: [e.target] }]);
}, true);
};
};
}
/******************************************************************************/
var beforeLoadEvent = document.createEvent('Event');
beforeLoadEvent.initEvent('beforeload');
/******************************************************************************/
var frameId = window === window.top ? 0 : Date.now() % 1E5;
var parentFrameId = frameId ? 0 : -1;
var linkHelper = document.createElement('a');
var onBeforeLoad = function(e, details) {
if ( e.url && e.url.slice(0, 5) === 'data:' ) {
if ( e.url && e.url.lastIndexOf('data:', 0) == 0 ) {
return;
}
linkHelper.href = details ? details.url : e.url;
var url = linkHelper.href;
if ( linkHelper.protocol !== 'http:' && linkHelper.protocol !== 'https:' ) {
if ( !(details && details.type === 'popup') ) {
if ( url.lastIndexOf('http:', 0) === -1 && url.lastIndexOf('https:', 0) === -1) {
return;
}
}
if ( details ) {
details.url = linkHelper.href;
details.url = url;
} else {
details = {
url: linkHelper.href
url: url
};
switch ( e.target.nodeName.toLowerCase() ) {
@ -274,7 +258,7 @@ var onBeforeLoad = function(e, details) {
// tabId is determined in the background script
// details.tabId = null;
details.frameId = frameId;
details.parentFrameId = frameId ? 0 : -1;
details.parentFrameId = parentFrameId;
details.timeStamp = Date.now();
var response = safari.self.tab.canLoad(e, details);
@ -316,11 +300,10 @@ var onBeforeLoad = function(e, details) {
document.addEventListener('beforeload', onBeforeLoad, true);
/******************************************************************************/
// block pop-ups, intercept xhr requests, and apply site patches
var firstMutation = function() {
document.removeEventListener('DOMSubtreeModified', firstMutation, true);
firstMutation = null;
firstMutation = false;
var randEventName = uniqueId();
@ -337,11 +320,10 @@ var firstMutation = function() {
var tmpJS = document.createElement('script');
var tmpScript = ['(function() {',
'var block = function(u, t) {',
'var e = document.createEvent("CustomEvent"),',
'd = {url: u, type: t};',
'e.initCustomEvent("' + randEventName + '", false, false, d);',
'var e = new CustomEvent("' + randEventName +'",',
'{detail: {url: u, type: t}, bubbles: false});',
'dispatchEvent(e);',
'return d.url === false;',
'return e.detail.url === false;',
'}, wo = open, xo = XMLHttpRequest.prototype.open;',
'open = function(u) {',
'return block(u, "popup") ? null : wo.apply(this, arguments);',