Skip to content

Commit

Permalink
https://github.com/AdguardTeam/AdguardBrowserExtension/issues/512
Browse files Browse the repository at this point in the history
  • Loading branch information
atropnikov committed Jan 17, 2017
1 parent 159f82b commit f82b056
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 45 deletions.
25 changes: 23 additions & 2 deletions Extension/browser/chrome/lib/api/background-page.js
Expand Up @@ -46,7 +46,10 @@ var browser = window.browser || chrome;
};

return {
onMessage: onMessage
onMessage: onMessage,
get lastError() {
return browser.runtime.lastError;
}
};
})();

Expand Down Expand Up @@ -259,8 +262,26 @@ var browser = window.browser || chrome;
}
};

var onCommitted = {

addListener: function (callback) {

// https://developer.chrome.com/extensions/webNavigation#event-onCommitted
browser.webNavigation.onCommitted.addListener(function (details) {

if (details.tabId === -1) {
return;
}

callback(details.tabId, details.frameId, details.url);
});
}
};

// https://developer.chrome.com/extensions/webNavigation
adguard.webNavigation = {
onCreatedNavigationTarget: onCreatedNavigationTarget
onCreatedNavigationTarget: onCreatedNavigationTarget,
onCommitted: onCommitted
};

//noinspection JSUnusedLocalSymbols,JSHint
Expand Down
6 changes: 5 additions & 1 deletion Extension/browser/chrome/lib/api/tabs.js
Expand Up @@ -269,8 +269,12 @@ adguard.tabsImpl = (function (adguard) {
}
};

var sendMessage = function (tabId, message, responseCallback) {
var sendMessage = function (tabId, message, responseCallback, options) {
// https://developer.chrome.com/extensions/tabs#method-sendMessage
if (typeof options === 'object' && browser.tabs.sendMessage) {
browser.tabs.sendMessage(tabIdToInt(tabId), message, options, responseCallback);
return;
}
(browser.tabs.sendMessage || browser.tabs.sendRequest)(tabIdToInt(tabId), message, responseCallback);
};

Expand Down
17 changes: 11 additions & 6 deletions Extension/browser/firefox/lib/api/webrequest-api.js
@@ -1,16 +1,14 @@
/* global XPCOMUtils, Services, Cc, Ci, Cr, Cm, components */

/* global Map */

/**
* Web requests implementation
*/
(function (adguard) {

adguard.webRequest = (function (adguard) {
function noOpFunc() {
}

function noOpFunc() {
}
adguard.webRequest = (function (adguard) {

var onBeforeRequestChannel = adguard.utils.channels.newChannel();
var onBeforeSendHeadersChannel = adguard.utils.channels.newChannel();
Expand Down Expand Up @@ -648,6 +646,12 @@
adguard.webNavigation = (function (adguard) {

var onCreatedNavigationTargetChannel = adguard.utils.channels.newChannel();
/**
* There is no need in this event for Firefox
* It is used in Chromium for fast applying js rules
* In Firefox they are applied quite fast
*/
var onCommitted = {addListener: noOpFunc};

var onPopupCreated = function (tabId, targetUrl, sourceUrl) {

Expand Down Expand Up @@ -686,7 +690,8 @@

onPopupCreated: onPopupCreated,

onCreatedNavigationTarget: onCreatedNavigationTargetChannel
onCreatedNavigationTarget: onCreatedNavigationTargetChannel,
onCommitted: onCommitted
};

})(adguard);
Expand Down
3 changes: 2 additions & 1 deletion Extension/browser/safari/lib/api/background-page.js
Expand Up @@ -219,7 +219,8 @@
};

adguard.webNavigation = {
onCreatedNavigationTarget: emptyListener
onCreatedNavigationTarget: emptyListener,
onCommitted: emptyListener
};


Expand Down
2 changes: 1 addition & 1 deletion Extension/lib/content-message-handler.js
Expand Up @@ -342,7 +342,7 @@
if (adguard.utils.workaround.isFacebookIframe(message.documentUrl)) {
return {};
}
var cssAndScripts = adguard.webRequestService.processGetSelectorsAndScripts(sender.tab, message.documentUrl, message.loadTruncatedCss);
var cssAndScripts = adguard.webRequestService.processGetSelectorsAndScripts(sender.tab, message.documentUrl, message.options);
return cssAndScripts || {};
case 'checkWebSocketRequest':
var block = adguard.webRequestService.checkWebSocketRequest(sender.tab, message.elementUrl, message.documentUrl);
Expand Down
30 changes: 29 additions & 1 deletion Extension/lib/content-script/preload.js
Expand Up @@ -27,6 +27,9 @@
"iframe": "SUBDOCUMENT",
"embed": "OBJECT"
};

// Don't apply scripts twice
var scriptsApplied = false;

/**
* Do not use shadow DOM on some websites
Expand All @@ -53,6 +56,22 @@
contentPage.sendMessage({type: 'saveCssHitStats', stats: stats});
});
}

/**
* When Background page receives 'onCommitted' frame event then it sends scripts to corresponding frame
* It allows us to execute script as soon as possible, because runtime.messaging makes huge overhead
* If onCommitted event doesn't occur for the frame, scripts will be applied in usual way.
*/
contentPage.onMessage.addListener(function (response, sender, sendResponse) {
if (response.type === 'injectScripts') {
// Notify background-page that content-script was received scripts
sendResponse({applied: true});
if (!isHtml()) {
return;
}
applyScripts(response.scripts);
}
});

/**
* Initializing content script
Expand Down Expand Up @@ -253,7 +272,10 @@
var message = {
type: 'getSelectorsAndScripts',
documentUrl: window.location.href,
loadTruncatedCss: loadTruncatedCss
options: {
filter: ['selectors', 'scripts'],
genericHide: loadTruncatedCss
}
};

/**
Expand Down Expand Up @@ -477,6 +499,12 @@
* @param scripts Array with JS scripts and scriptSource ('remote' or 'local')
*/
var applyScripts = function(scripts) {

if (scriptsApplied) {
return;
}
scriptsApplied = true;

if (!scripts || scripts.length === 0) {
return;
}
Expand Down
82 changes: 51 additions & 31 deletions Extension/lib/filter/request-blocking.js
Expand Up @@ -26,7 +26,7 @@ adguard.webRequestService = (function (adguard) {
* @param requestRule Rule to record
* @param requestUrl Request URL
*/
var recordRuleHit = function(tab, requestRule, requestUrl) {
var recordRuleHit = function (tab, requestRule, requestUrl) {
if (requestRule &&
adguard.settings.collectHitsCount() &&
!adguard.utils.filters.isUserFilterRule(requestRule) &&
Expand All @@ -43,21 +43,25 @@ adguard.webRequestService = (function (adguard) {
*
* @param tab Tab
* @param documentUrl Document URL
* @param genericHide flag to hide common rules
* @param options Options for select:
* options = {
* filter: ['selectors', 'scripts'] (selection filter) (mandatory)
* genericHide: true|false ( select only generic hide css rules) (optional)
* }
*
* @returns {*} null or object the following properties: "selectors", "scripts", "collapseAllElements"
*/
var processGetSelectorsAndScripts = function (tab, documentUrl, genericHide) {
var processGetSelectorsAndScripts = function (tab, documentUrl, options) {

var result = {};
var result = Object.create(null);

if (!tab) {
return result;
}

if (!adguard.requestFilter.isReady()) {
return {
requestFilterReady: false
};
result.requestFilterReady = false;
return result;
}

if (adguard.frames.isTabAdguardDetected(tab) ||
Expand All @@ -73,8 +77,13 @@ adguard.webRequestService = (function (adguard) {
whitelistRule = adguard.requestFilter.findWhiteListRule(documentUrl, mainFrameUrl, adguard.RequestTypes.DOCUMENT);
}

// Record rule hit
recordRuleHit(tab, whitelistRule, documentUrl);
var retrieveSelectors = options.filter.indexOf('selectors') >= 0;
var retrieveScripts = options.filter.indexOf('scripts') >= 0;

if (retrieveSelectors) {
// Record rule hit
recordRuleHit(tab, whitelistRule, documentUrl);
}

// It's important to check this after the recordRuleHit call
// as otherwise we will never record $document rules hit for domain
Expand All @@ -83,34 +92,45 @@ adguard.webRequestService = (function (adguard) {
}

// Prepare result
result = {
selectors: {
result = Object.create(null);

if (retrieveSelectors) {
result.selectors = {
css: null,
extendedCss: null,
cssHitsCounterEnabled: false
},
scripts: null,
collapseAllElements: adguard.requestFilter.shouldCollapseAllElements(),
useShadowDom: adguard.utils.browser.isShadowDomSupported()
};

// Check what exactly is disabled by this rule
var genericHideFlag = genericHide || (whitelistRule && whitelistRule.checkContentType("GENERICHIDE"));
var elemHideFlag = whitelistRule && whitelistRule.checkContentType("ELEMHIDE");

if (!elemHideFlag) {
// Element hiding rules aren't disabled, so we should use them
if (shouldLoadAllSelectors(result.collapseAllElements)) {
result.selectors = adguard.requestFilter.getSelectorsForUrl(documentUrl, genericHideFlag);
} else {
result.selectors = adguard.requestFilter.getInjectedSelectorsForUrl(documentUrl, genericHideFlag);

};
result.collapseAllElements = adguard.requestFilter.shouldCollapseAllElements();
result.useShadowDom = adguard.utils.browser.isShadowDomSupported();
}

if (retrieveScripts) {
result.scripts = null;
}

if (retrieveSelectors) {

// Check what exactly is disabled by this rule
var genericHideFlag = options.genericHide || (whitelistRule && whitelistRule.checkContentType("GENERICHIDE"));
var elemHideFlag = whitelistRule && whitelistRule.checkContentType("ELEMHIDE");

if (!elemHideFlag) {
// Element hiding rules aren't disabled, so we should use them
if (shouldLoadAllSelectors(result.collapseAllElements)) {
result.selectors = adguard.requestFilter.getSelectorsForUrl(documentUrl, genericHideFlag);
} else {
result.selectors = adguard.requestFilter.getInjectedSelectorsForUrl(documentUrl, genericHideFlag);
}
}
}

var jsInjectFlag = whitelistRule && whitelistRule.checkContentType("JSINJECT");
if (!jsInjectFlag) {
// JS rules aren't disabled, returning them
result.scripts = adguard.requestFilter.getScriptsForUrl(documentUrl);
if (retrieveScripts) {
var jsInjectFlag = whitelistRule && whitelistRule.checkContentType("JSINJECT");
if (!jsInjectFlag) {
// JS rules aren't disabled, returning them
result.scripts = adguard.requestFilter.getScriptsForUrl(documentUrl);
}
}

return result;
Expand Down
4 changes: 2 additions & 2 deletions Extension/lib/tabs/tabs-api.js
Expand Up @@ -235,8 +235,8 @@
};

// Sends message to tab
var sendMessage = function (tabId, message, responseCallback) {
tabsImpl.sendMessage(tabId, message, responseCallback);
var sendMessage = function (tabId, message, responseCallback, options) {
tabsImpl.sendMessage(tabId, message, responseCallback, options);
};

// Gets all opened tabs
Expand Down
52 changes: 52 additions & 0 deletions Extension/lib/webrequest.js
Expand Up @@ -238,4 +238,56 @@
}
});

/**
* When frame is committed we send to it js rules
* We do this because we need to apply js rules as soon as possible
*/
(function fastScriptRulesLoader(adguard) {

var isEdgeBrowser = adguard.utils.browser.isEdgeBrowser();

function tryInjectScripts(tabId, frameId, url, result, limit) {

var options = null;
if (!isEdgeBrowser) {
options = {frameId: frameId};
}

adguard.tabs.sendMessage(tabId, result, function (response) {

// Try again if no response was received from content-script
if (adguard.runtime.lastError || !response) {

if (--limit <= 0) {
return;
}

setTimeout(function () {
tryInjectScripts(tabId, frameId, url, result, limit);
}, 10);
}

}, options);
}

adguard.webNavigation.onCommitted.addListener(function (tabId, frameId, url) {

/**
* Messaging a specific frame is not yet supported in Edge
*/
if (frameId !== 0 && isEdgeBrowser) {
return;
}

var result = adguard.webRequestService.processGetSelectorsAndScripts({tabId: tabId}, url, {filter: ['scripts']});
if (!result.scripts || result.scripts.length === 0) {
return;
}

result.type = 'injectScripts';
tryInjectScripts(tabId, frameId, url, result, 5);
});

})(adguard);

})(adguard);

0 comments on commit f82b056

Please sign in to comment.