Merge pull request #548 from chrisaljoudi/master

More fixes and performance improvements to Safari event handling and dispatching
This commit is contained in:
Raymond Hill 2015-01-20 09:40:37 -05:00
commit 965f3cfc29
2 changed files with 70 additions and 119 deletions

View file

@ -188,33 +188,23 @@ vAPI.tabs = {
/******************************************************************************/ /******************************************************************************/
vAPI.tabs.registerListeners = function() { vAPI.tabs.registerListeners = function() {
var onNavigation = this.onNavigation;
safari.application.addEventListener('beforeNavigate', function(e) { safari.application.addEventListener('beforeNavigate', function(e) {
if ( !e.target || !e.target.url || e.target.url === 'about:blank' ) { if ( !vAPI.tabs.popupCandidate || !e.target || e.url === 'about:blank' ) {
return; 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 = {
var details = { url: url,
url: url, tabId: tabId,
tabId: tabId, sourceTabId: vAPI.tabs.popupCandidate
sourceTabId: vAPI.tabs.popupCandidate };
}; vAPI.tabs.popupCandidate = false;
vAPI.tabs.popupCandidate = false; if ( vAPI.tabs.onPopup(details) ) {
if ( vAPI.tabs.onPopup(details) ) { e.preventDefault();
e.preventDefault(); if ( vAPI.tabs.stack[details.sourceTabId] ) {
if ( vAPI.tabs.stack[details.sourceTabId] ) { vAPI.tabs.stack[details.sourceTabId].activate();
vAPI.tabs.stack[details.sourceTabId].activate();
}
return;
} }
} }
onNavigation({
url: url,
frameId: 0,
tabId: tabId
});
}, true); }, true);
// onClosed handled in the main tab-close event // onClosed handled in the main tab-close event
@ -586,9 +576,6 @@ vAPI.messaging.broadcast = function(message) {
} }
}; };
/******************************************************************************/
/******************************************************************************/ /******************************************************************************/
vAPI.net = {}; vAPI.net = {};
@ -649,6 +636,14 @@ vAPI.net.registerListeners = function() {
return; 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; 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 frameId = window === window.top ? 0 : Date.now() % 1E5;
var parentFrameId = frameId ? 0 : -1; 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 linkHelper = document.createElement('a');
var onBeforeLoad = function(e, details) { var nodeTypes = {
if ( e.url && e.url.lastIndexOf('data:', 0) === 0 ) { 'frame': 'sub_frame',
return; 'iframe': 'sub_frame',
} 'script': 'script',
'img': 'image',
linkHelper.href = details ? details.url : e.url; 'input': 'image',
var url = linkHelper.href; 'object': 'object',
'embed': 'object',
if ( url.lastIndexOf('http:', 0) === -1 && url.lastIndexOf('https:', 0) === -1) { 'link': 'stylesheet'
return; };
} var shouldBlockDetailedRequest = function(details) {
linkHelper.href = details.url;
if ( details ) { details.url = linkHelper.href;
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;
details.frameId = frameId; details.frameId = frameId;
details.parentFrameId = parentFrameId; details.parentFrameId = parentFrameId;
details.timeStamp = Date.now(); details.timeStamp = Date.now();
return !(safari.self.tab.canLoad(beforeLoadEvent, details));
var response = safari.self.tab.canLoad(e, details); }
var onBeforeLoad = function(e) {
if ( !response ) { if(e.url.lastIndexOf('data:', 0) === 0) {
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; 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(); e.preventDefault();
// Content Security Policy with disallowed inline scripts may break things // Content Security Policy with disallowed inline scripts may break things
details = document.createElement('script'); details = document.createElement('script');
details.textContent = atob(response.slice(response.indexOf(',', 20) + 1)); details.textContent = atob(response.slice(response.indexOf(',', 20) + 1));
@ -308,11 +276,9 @@ var firstMutation = function() {
var randEventName = uniqueId(); var randEventName = uniqueId();
window.addEventListener(randEventName, function(e) { window.addEventListener(randEventName, function(e) {
var result = onBeforeLoad(beforeLoadEvent, e.detail); if(shouldBlockDetailedRequest(e.detail)) {
if ( result === false ) {
e.detail.url = false; e.detail.url = false;
} };
}, true); }, true);
// the extension context is unable to reach the page context, // the extension context is unable to reach the page context,
@ -409,18 +375,8 @@ var onContextMenu = function(e) {
self.addEventListener('contextmenu', onContextMenu, true); self.addEventListener('contextmenu', onContextMenu, true);
/******************************************************************************/
// 'main_frame' simulation
if ( frameId === 0 ) {
onBeforeLoad(beforeLoadEvent, {
url: location.href,
type: 'main_frame'
});
}
/******************************************************************************/ /******************************************************************************/
})(); })();
/******************************************************************************/ /******************************************************************************/