Skip to content

Loading…

Big fixes to Safari vAPI stuff #596

Merged
merged 1 commit into from

2 participants

@chrisaljoudi

Safari vAPI is now more harmonious with core. Whitelisting should work a lot better now. Also fixes #595.

@gorhill gorhill merged commit f69b38f into chrisaljoudi:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 25, 2015
This page is out of date. Refresh to see the latest.
Showing with 98 additions and 150 deletions.
  1. +1 −4 platform/safari/sitepatch-safari.js
  2. +72 −94 platform/safari/vapi-background.js
  3. +25 −52 platform/safari/vapi-client.js
View
5 platform/safari/sitepatch-safari.js
@@ -19,9 +19,6 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global ytspf */
-'use strict';
-
/******************************************************************************/
// 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.
-self.vAPI = self.vAPI || {};
+var vAPI = self.vAPI = self.vAPI || {};
if ( /^www\.youtube(-nocookie)?\.com/.test(location.host) ) {
vAPI.sitePatch = function() {
View
166 platform/safari/vapi-background.js
@@ -29,8 +29,6 @@
'use strict';
-/******************************************************************************/
-
var vAPI = self.vAPI = self.vAPI || {};
vAPI.safari = true;
@@ -590,104 +588,84 @@ vAPI.net = {};
/******************************************************************************/
-vAPI.net.registerListeners = function() {
- var µb = µBlock;
-
- // Since it's not used
- this.onBeforeSendHeaders = null;
- this.onHeadersReceived = null;
+// Fast `contains`
- var onBeforeRequest = this.onBeforeRequest;
-
- if ( !Array.isArray(onBeforeRequest.types) ) {
- onBeforeRequest.types = [];
+Array.prototype.contains = function(a) {
+ var b = this.length;
+ while(b --) {
+ if(this[b] === a) {
+ return true;
+ }
}
+ return false;
+};
- onBeforeRequest = onBeforeRequest.callback;
- this.onBeforeRequest.callback = function(e) {
- var block;
-
- if ( e.name !== 'canLoad' ) {
- return;
- }
-
- // No stopPropagation if it was called from beforeNavigate event
- if ( e.stopPropagation ) {
- e.stopPropagation();
- }
-
- if ( e.message.isURLWhiteListed ) {
- // https://github.com/gorhill/uBlock/issues/595
- // Do not access µb.netWhitelist directly
- e.message = !µb.getNetFilteringSwitch(e.message.isURLWhiteListed);
- return e.message;
- }
-
- // When the URL changes, but the document doesn't
- 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);
- e.message = true;
- } else {
- e.message = !vAPI.tabs.onPopup({
- url: e.message.url,
- tabId: 0,
- sourceTabId: vAPI.tabs.getTabId(e.target)
- });
- }
-
- 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.tabId = vAPI.tabs.getTabId(e.target);
- block = onBeforeRequest(e.message);
-
- // Truthy return value will allow the request,
- // except when redirectUrl is present
- if ( block && typeof block === 'object' ) {
- if ( block.cancel === true ) {
- e.message = false;
- } else if ( e.message.type === 'script'
- && typeof block.redirectUrl === 'string' ) {
- e.message = block.redirectUrl;
- } else {
- e.message = true;
- }
- } else {
- e.message = true;
- }
+vAPI.net.registerListeners = function() {
+ var µb = µBlock;
- return e.message;
+ // Until Safari has more specific events, those are instead handled
+ // in the onBeforeRequestAdapter; clean them up so they're garbage-collected
+ vAPI.net.onBeforeSendHeaders = null;
+ vAPI.net.onHeadersReceived = null;
+
+ var onBeforeRequest = vAPI.net.onBeforeRequest,
+ onBeforeRequestClient = onBeforeRequest.callback,
+ blockableTypes = onBeforeRequest.types;
+
+ var onBeforeRequestAdapter = function(e) {
+ if(e.name !== "canLoad") {
+ return;
+ }
+ e.stopPropagation && e.stopPropagation();
+ switch(e.message.type) {
+ case "isWhiteListed":
+ e.message = !µb.getNetFilteringSwitch(e.message.url);
+ break;
+ case "navigatedToNew":
+ vAPI.tabs.onNavigation({
+ url: e.message.url,
+ frameId: 0,
+ tabId: vAPI.tabs.getTabId(e.target)
+ });
+ break;
+ case "popup":
+ if(e.message.url === 'about:blank') {
+ vAPI.tabs.popupCandidate = vAPI.tabs.getTabId(e.target);
+ e.message = true;
+ }
+ else {
+ e.message = !vAPI.tabs.onPopup({
+ url: e.message.url,
+ tabId: 0,
+ 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;
+ }
+ e.message.hostname = µb.URI.hostnameFromURI(e.message.url);
+ e.message.tabId = vAPI.tabs.getTabId(e.target);
+ var blockVerdict = onBeforeRequestClient(e.message);
+ if(blockVerdict && blockVerdict.cancel) {
+ e.message = false;
+ }
+ else {
+ e.message = true;
+ }
+ }
+ return;
};
-
- safari.application.addEventListener(
- 'message',
- this.onBeforeRequest.callback,
- true
- );
+ safari.application.addEventListener("message", onBeforeRequestAdapter, true);
};
/******************************************************************************/
View
77 platform/safari/vapi-client.js
@@ -27,9 +27,7 @@
'use strict';
-/******************************************************************************/
-
-self.vAPI = self.vAPI || {};
+var vAPI = self.vAPI = self.vAPI || {};
vAPI.safari = true;
/******************************************************************************/
@@ -177,7 +175,7 @@ vAPI.messaging = {
/******************************************************************************/
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,
// but the following code should run only in content pages.
-if ( location.protocol === 'safari-extension:' ) {
+if ( location.protocol === 'safari-extension:' || typeof safari !== 'object' ) {
return;
}
/******************************************************************************/
var frameId = window === window.top ? 0 : Date.now() % 1E5;
-var parentFrameId = frameId ? 0 : -1;
-var beforeLoadEvent = new Event('beforeload'); // Helper event to message background
+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
+ type: "navigatedToNew"
});
}
-var linkHelper = document.createElement('a');
+var linkHelper = document.createElement("a");
var nodeTypes = {
- 'frame': 'sub_frame',
- 'iframe': 'sub_frame',
- 'script': 'script',
- 'img': 'image',
- 'input': 'image',
- 'object': 'object',
- 'embed': 'object',
- 'link': 'stylesheet'
+ "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;
@@ -224,7 +221,7 @@ var shouldBlockDetailedRequest = function(details) {
return !(safari.self.tab.canLoad(beforeLoadEvent, details));
}
var onBeforeLoad = function(e) {
- if(e.url.lastIndexOf('data:', 0) === 0) {
+ if(e.url.lastIndexOf("data:", 0) === 0) {
return;
}
linkHelper.href = e.url;
@@ -240,28 +237,6 @@ var onBeforeLoad = function(e) {
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));
-
- 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
var firstMutation = function() {
- document.removeEventListener('DOMSubtreeModified', firstMutation, true);
+ document.removeEventListener('DOMContentLoaded', firstMutation, true);
firstMutation = false;
var randEventName = uniqueId();
@@ -302,7 +277,7 @@ var firstMutation = function() {
'};'
];
- if ( frameId === 0 ) {
+ if(frameId === 0) {
tmpScript.push(
'var pS = history.pushState, rS = history.replaceState,',
'onpopstate = function(e) {',
@@ -322,22 +297,20 @@ var firstMutation = function() {
);
}
- var block = safari.self.tab.canLoad(beforeLoadEvent, {
- isURLWhiteListed: location.href
+ var whiteListed = safari.self.tab.canLoad(beforeLoadEvent, {
+ type: "isWhiteListed",
+ url: location.href
});
-
- if ( vAPI.sitePatch && !block ) {
- tmpScript.push('(' + vAPI.sitePatch + ')();');
+ if(vAPI.sitePatch && !whiteListed) {
+ tmpScript.push('(' + vAPI.sitePatch + ')();');
}
tmpScript.push('})();');
tmpJS.textContent = tmpScript.join('');
- document.documentElement.removeChild(
- document.documentElement.appendChild(tmpJS)
- );
+ document.documentElement.removeChild(document.documentElement.appendChild(tmpJS));
};
-document.addEventListener('DOMSubtreeModified', firstMutation, true);
+document.addEventListener('DOMContentLoaded', firstMutation, true);
/******************************************************************************/
Something went wrong with that request. Please try again.