1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-11-09 12:22:33 +01:00

Merge pull request #596 from chrisaljoudi/master

Big fixes to Safari vAPI stuff
This commit is contained in:
Raymond Hill 2015-01-25 07:21:11 -05:00
commit f69b38f089
3 changed files with 98 additions and 150 deletions

View File

@ -19,9 +19,6 @@
Home: https://github.com/gorhill/uBlock Home: https://github.com/gorhill/uBlock
*/ */
/* global ytspf */
'use strict';
/******************************************************************************/ /******************************************************************************/
// Adding new URL requires to whitelist it in the background script too (addContentScriptFromURL) // Adding new URL requires to whitelist it in the background script too (addContentScriptFromURL)
@ -30,7 +27,7 @@
// from the extension scope won't be accessible in the sitePatch function. // from the extension scope won't be accessible in the sitePatch function.
self.vAPI = self.vAPI || {}; var vAPI = self.vAPI = self.vAPI || {};
if ( /^www\.youtube(-nocookie)?\.com/.test(location.host) ) { if ( /^www\.youtube(-nocookie)?\.com/.test(location.host) ) {
vAPI.sitePatch = function() { vAPI.sitePatch = function() {

View File

@ -29,8 +29,6 @@
'use strict'; 'use strict';
/******************************************************************************/
var vAPI = self.vAPI = self.vAPI || {}; var vAPI = self.vAPI = self.vAPI || {};
vAPI.safari = true; vAPI.safari = true;
@ -590,104 +588,84 @@ vAPI.net = {};
/******************************************************************************/ /******************************************************************************/
// Fast `contains`
Array.prototype.contains = function(a) {
var b = this.length;
while(b --) {
if(this[b] === a) {
return true;
}
}
return false;
};
/******************************************************************************/
vAPI.net.registerListeners = function() { vAPI.net.registerListeners = function() {
var µb = µBlock; var µb = µBlock;
// Since it's not used // Until Safari has more specific events, those are instead handled
this.onBeforeSendHeaders = null; // in the onBeforeRequestAdapter; clean them up so they're garbage-collected
this.onHeadersReceived = null; vAPI.net.onBeforeSendHeaders = null;
vAPI.net.onHeadersReceived = null;
var onBeforeRequest = this.onBeforeRequest; var onBeforeRequest = vAPI.net.onBeforeRequest,
onBeforeRequestClient = onBeforeRequest.callback,
blockableTypes = onBeforeRequest.types;
if ( !Array.isArray(onBeforeRequest.types) ) { var onBeforeRequestAdapter = function(e) {
onBeforeRequest.types = []; if(e.name !== "canLoad") {
}
onBeforeRequest = onBeforeRequest.callback;
this.onBeforeRequest.callback = function(e) {
var block;
if ( e.name !== 'canLoad' ) {
return; return;
} }
e.stopPropagation && e.stopPropagation();
// No stopPropagation if it was called from beforeNavigate event switch(e.message.type) {
if ( e.stopPropagation ) { case "isWhiteListed":
e.stopPropagation(); e.message = !µb.getNetFilteringSwitch(e.message.url);
} break;
case "navigatedToNew":
if ( e.message.isURLWhiteListed ) { vAPI.tabs.onNavigation({
// https://github.com/gorhill/uBlock/issues/595 url: e.message.url,
// Do not access µb.netWhitelist directly frameId: 0,
e.message = !µb.getNetFilteringSwitch(e.message.isURLWhiteListed); tabId: vAPI.tabs.getTabId(e.target)
return e.message; });
} break;
case "popup":
// When the URL changes, but the document doesn't if(e.message.url === 'about:blank') {
if ( e.message.type === 'popstate' ) {
vAPI.tabs.onUpdated(
vAPI.tabs.getTabId(e.target),
{url: e.message.url},
{url: e.message.url}
);
return;
} else if ( e.message.type === 'popup' ) {
// blocking unwanted pop-ups
if ( e.message.url === 'about:blank' ) {
vAPI.tabs.popupCandidate = vAPI.tabs.getTabId(e.target); vAPI.tabs.popupCandidate = vAPI.tabs.getTabId(e.target);
e.message = true; e.message = true;
} else { }
else {
e.message = !vAPI.tabs.onPopup({ e.message = !vAPI.tabs.onPopup({
url: e.message.url, url: e.message.url,
tabId: 0, tabId: 0,
sourceTabId: vAPI.tabs.getTabId(e.target) sourceTabId: vAPI.tabs.getTabId(e.target)
}); });
} }
break;
case "popstate":
vAPI.tabs.onUpdated(vAPI.tabs.getTabId(e.target),
{url: e.message.url},
{url: e.message.url});
break;
default:
if(!blockableTypes.contains(e.message.type)) {
e.message = true;
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;
if ( block.types.indexOf(e.message.type) === -1 ) {
return true;
}
e.message.hostname = µb.URI.hostnameFromURI(e.message.url); e.message.hostname = µb.URI.hostnameFromURI(e.message.url);
e.message.tabId = vAPI.tabs.getTabId(e.target); e.message.tabId = vAPI.tabs.getTabId(e.target);
block = onBeforeRequest(e.message); var blockVerdict = onBeforeRequestClient(e.message);
if(blockVerdict && blockVerdict.cancel) {
// Truthy return value will allow the request,
// except when redirectUrl is present
if ( block && typeof block === 'object' ) {
if ( block.cancel === true ) {
e.message = false; e.message = false;
} else if ( e.message.type === 'script' }
&& typeof block.redirectUrl === 'string' ) { else {
e.message = block.redirectUrl;
} else {
e.message = true; e.message = true;
} }
} else {
e.message = true;
} }
return;
return e.message;
}; };
safari.application.addEventListener("message", onBeforeRequestAdapter, true);
safari.application.addEventListener(
'message',
this.onBeforeRequest.callback,
true
);
}; };
/******************************************************************************/ /******************************************************************************/

View File

@ -27,9 +27,7 @@
'use strict'; 'use strict';
/******************************************************************************/ var vAPI = self.vAPI = self.vAPI || {};
self.vAPI = self.vAPI || {};
vAPI.safari = true; vAPI.safari = true;
/******************************************************************************/ /******************************************************************************/
@ -177,7 +175,7 @@ vAPI.messaging = {
/******************************************************************************/ /******************************************************************************/
vAPI.canExecuteContentScript = function() { vAPI.canExecuteContentScript = function() {
return /^https?:/.test(location.protocol); return (/^https?:/.test(location.protocol) && typeof safari === 'object');
}; };
/******************************************************************************/ /******************************************************************************/
@ -185,35 +183,34 @@ vAPI.canExecuteContentScript = function() {
// This file can be included into extensin pages, // This file can be included into extensin pages,
// but the following code should run only in content pages. // but the following code should run only in content pages.
if ( location.protocol === 'safari-extension:' ) { if ( location.protocol === 'safari-extension:' || typeof safari !== 'object' ) {
return; return;
} }
/******************************************************************************/ /******************************************************************************/
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 var beforeLoadEvent = new Event("beforeload"); // Helper event to message background
// Inform that we've navigated // Inform that we've navigated
if(frameId === 0) { if(frameId === 0) {
safari.self.tab.canLoad(beforeLoadEvent, { safari.self.tab.canLoad(beforeLoadEvent, {
url: location.href, url: location.href,
type: 'main_frame', type: "navigatedToNew"
navigatedToNew: true
}); });
} }
var linkHelper = document.createElement('a'); var linkHelper = document.createElement("a");
var nodeTypes = { var nodeTypes = {
'frame': 'sub_frame', "frame": "sub_frame",
'iframe': 'sub_frame', "iframe": "sub_frame",
'script': 'script', "script": "script",
'img': 'image', "img": "image",
'input': 'image', "input": "image",
'object': 'object', "object": "object",
'embed': 'object', "embed": "object",
'link': 'stylesheet' "link": "stylesheet"
}; };
var shouldBlockDetailedRequest = function(details) { var shouldBlockDetailedRequest = function(details) {
linkHelper.href = details.url; linkHelper.href = details.url;
@ -224,7 +221,7 @@ var shouldBlockDetailedRequest = function(details) {
return !(safari.self.tab.canLoad(beforeLoadEvent, details)); return !(safari.self.tab.canLoad(beforeLoadEvent, details));
} }
var onBeforeLoad = function(e) { var onBeforeLoad = function(e) {
if(e.url.lastIndexOf('data:', 0) === 0) { if(e.url.lastIndexOf("data:", 0) === 0) {
return; return;
} }
linkHelper.href = e.url; linkHelper.href = e.url;
@ -240,28 +237,6 @@ var onBeforeLoad = function(e) {
var response = safari.self.tab.canLoad(e, details); var response = safari.self.tab.canLoad(e, details);
if(!response) { if(!response) {
e.preventDefault(); 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));
if ( e.target.hasAttribute('defer') && document.readyState === 'loading' ) {
var jsOnLoad = function(ev) {
this.removeEventListener(ev.type, jsOnLoad, true);
this.body.removeChild(this.body.appendChild(details));
};
document.addEventListener('DOMContentLoaded', jsOnLoad, true);
} else {
e.target.parentNode.insertBefore(details, e.target);
details.parentNode.removeChild(details);
} }
}; };
@ -270,7 +245,7 @@ document.addEventListener('beforeload', onBeforeLoad, true);
/******************************************************************************/ /******************************************************************************/
// block pop-ups, intercept xhr requests, and apply site patches // block pop-ups, intercept xhr requests, and apply site patches
var firstMutation = function() { var firstMutation = function() {
document.removeEventListener('DOMSubtreeModified', firstMutation, true); document.removeEventListener('DOMContentLoaded', firstMutation, true);
firstMutation = false; firstMutation = false;
var randEventName = uniqueId(); var randEventName = uniqueId();
@ -302,7 +277,7 @@ var firstMutation = function() {
'};' '};'
]; ];
if ( frameId === 0 ) { if(frameId === 0) {
tmpScript.push( tmpScript.push(
'var pS = history.pushState, rS = history.replaceState,', 'var pS = history.pushState, rS = history.replaceState,',
'onpopstate = function(e) {', 'onpopstate = function(e) {',
@ -322,22 +297,20 @@ var firstMutation = function() {
); );
} }
var block = safari.self.tab.canLoad(beforeLoadEvent, { var whiteListed = safari.self.tab.canLoad(beforeLoadEvent, {
isURLWhiteListed: location.href type: "isWhiteListed",
url: location.href
}); });
if(vAPI.sitePatch && !whiteListed) {
if ( vAPI.sitePatch && !block ) {
tmpScript.push('(' + vAPI.sitePatch + ')();'); tmpScript.push('(' + vAPI.sitePatch + ')();');
} }
tmpScript.push('})();'); tmpScript.push('})();');
tmpJS.textContent = tmpScript.join(''); tmpJS.textContent = tmpScript.join('');
document.documentElement.removeChild( document.documentElement.removeChild(document.documentElement.appendChild(tmpJS));
document.documentElement.appendChild(tmpJS)
);
}; };
document.addEventListener('DOMSubtreeModified', firstMutation, true); document.addEventListener('DOMContentLoaded', firstMutation, true);
/******************************************************************************/ /******************************************************************************/