More fixes and performance improvements to Safari event handling and dispatching

This commit is contained in:
Chris 2015-01-20 00:11:26 -07:00
parent 72f0f8a67d
commit 03668551c2
2 changed files with 60 additions and 106 deletions

View file

@ -188,13 +188,11 @@ vAPI.tabs = {
/******************************************************************************/
vAPI.tabs.registerListeners = function() {
var onNavigation = this.onNavigation;
safari.application.addEventListener('beforeNavigate', function(e) {
if ( !e.target || !e.target.url || e.target.url === 'about:blank' ) {
if ( !e.target || e.url === 'about:blank' ) {
return;
}
var url = e.target.url, tabId = vAPI.tabs.getTabId(e.target);
var url = e.url, tabId = vAPI.tabs.getTabId(e.target);
if ( vAPI.tabs.popupCandidate ) {
var details = {
url: url,
@ -210,11 +208,6 @@ vAPI.tabs.registerListeners = function() {
return;
}
}
onNavigation({
url: url,
frameId: 0,
tabId: tabId
});
}, true);
// onClosed handled in the main tab-close event
@ -586,9 +579,6 @@ vAPI.messaging.broadcast = function(message) {
}
};
/******************************************************************************/
/******************************************************************************/
vAPI.net = {};
@ -649,6 +639,14 @@ vAPI.net.registerListeners = function() {
return;
}
if ( e.message.navigatedToNew ) {
vAPI.tabs.onNavigation({
url: e.message.url,
frameId: 0,
tabId: vAPI.tabs.getTabId(e.target)
});
return;
}
block = vAPI.net.onBeforeRequest;

View file

@ -191,95 +191,63 @@ if ( location.protocol === 'safari-extension:' ) {
/******************************************************************************/
var beforeLoadEvent = document.createEvent('Event');
beforeLoadEvent.initEvent('beforeload');
/******************************************************************************/
var frameId = window === window.top ? 0 : Date.now() % 1E5;
var parentFrameId = frameId ? 0 : -1;
var beforeLoadEvent = new Event('beforeload'); // Helper event to message background
// Inform that we've navigated
if(frameId === 0) {
safari.self.tab.canLoad(beforeLoadEvent, {
url: location.href,
type: 'main_frame',
navigatedToNew: true
});
}
var linkHelper = document.createElement('a');
var onBeforeLoad = function(e, details) {
if ( e.url && e.url.lastIndexOf('data:', 0) === 0 ) {
return;
}
linkHelper.href = details ? details.url : e.url;
var url = linkHelper.href;
if ( url.lastIndexOf('http:', 0) === -1 && url.lastIndexOf('https:', 0) === -1) {
return;
}
if ( details ) {
details.url = url;
} else {
details = {
url: url
};
switch ( e.target.nodeName.toLowerCase() ) {
case 'frame':
case 'iframe':
details.type = 'sub_frame';
break;
case 'script':
details.type = 'script';
break;
case 'img':
case 'input': // type=image
details.type = 'image';
break;
case 'object':
case 'embed':
details.type = 'object';
break;
case 'link':
var rel = e.target.rel.trim().toLowerCase();
if ( rel.indexOf('icon') !== -1 ) {
details.type = 'image';
break;
} else if ( rel === 'stylesheet' ) {
details.type = 'stylesheet';
break;
}
default:
details.type = 'other';
}
}
// This can run even before the first DOMSubtreeModified event fired
if ( firstMutation ) {
firstMutation();
}
// tabId is determined in the background script
// details.tabId = null;
var nodeTypes = {
'frame': 'sub_frame',
'iframe': 'sub_frame',
'script': 'script',
'img': 'image',
'input': 'image',
'object': 'object',
'embed': 'object',
'link': 'stylesheet'
};
var shouldBlockDetailedRequest = function(details) {
linkHelper.href = details.url;
details.url = linkHelper.href;
details.frameId = frameId;
details.parentFrameId = parentFrameId;
details.timeStamp = Date.now();
var response = safari.self.tab.canLoad(e, details);
if ( !response ) {
if ( details.type === 'main_frame' ) {
window.stop();
} else {
e.preventDefault();
}
return false;
}
// Local mirroring, response should be a data: URL here
if ( typeof response !== 'string' ) {
return !(safari.self.tab.canLoad(beforeLoadEvent, details));
}
var onBeforeLoad = function(e) {
if(e.url.lastIndexOf('data:', 0) === 0) {
return;
}
linkHelper.href = e.url;
var url = linkHelper.href;
var details = {
url: url,
type: nodeTypes[e.target.nodeName.toLowerCase()] || 'other',
// tabId is determined in the background script
frameId: frameId,
parentFrameId: parentFrameId,
timeStamp: Date.now()
};
var response = safari.self.tab.canLoad(e, details);
if(!response) {
e.preventDefault();
return false;
}
// Local mirroring, response should be a data: URL here
if(typeof response !== 'string') {
return;
}
// Okay, we're mirroring...
e.preventDefault();
// Content Security Policy with disallowed inline scripts may break things
details = document.createElement('script');
details.textContent = atob(response.slice(response.indexOf(',', 20) + 1));
@ -308,11 +276,9 @@ var firstMutation = function() {
var randEventName = uniqueId();
window.addEventListener(randEventName, function(e) {
var result = onBeforeLoad(beforeLoadEvent, e.detail);
if ( result === false ) {
if(shouldBlockDetailedRequest(e.detail)) {
e.detail.url = false;
}
};
}, true);
// the extension context is unable to reach the page context,
@ -409,18 +375,8 @@ var onContextMenu = function(e) {
self.addEventListener('contextmenu', onContextMenu, true);
/******************************************************************************/
// 'main_frame' simulation
if ( frameId === 0 ) {
onBeforeLoad(beforeLoadEvent, {
url: location.href,
type: 'main_frame'
});
}
/******************************************************************************/
})();
/******************************************************************************/