From 815f8ca9593a4cea201ff2c809f5202034bcd3c2 Mon Sep 17 00:00:00 2001 From: tophf Date: Wed, 16 Aug 2017 20:40:24 +0300 Subject: [PATCH] also find styles for URLs with stripped #hash kinda fixes #155 as per spec the fragment portion is ignored in @-moz-document: https://www.w3.org/TR/2012/WD-css3-conditional-20120911/#url-of-doc but we still respect url("foo#hash") set in userstyles because the spec is outdated and doesn't account for SPA sites collateral damage: simplified URLS.supported() --- background/storage.js | 38 +++++++++++++++++++++++++------------- edit/edit.js | 2 +- js/messaging.js | 19 +++++++------------ popup/popup.js | 2 +- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/background/storage.js b/background/storage.js index 6e764edd..0fe28c29 100644 --- a/background/storage.js +++ b/background/storage.js @@ -129,12 +129,7 @@ function filterStyles({ exposeIframes: prefs.get('exposeIframes'), }; - if (matchUrl && ( - // Web Store doesn't run content scripts - matchUrl.startsWith(URLS.browserWebStore) || - // Chrome 61.0.3161+ doesn't run content scripts on NTP - URLS.chromeProtectsNTP && matchUrl.startsWith('chrome://newtab/') - )) { + if (matchUrl && !URLS.supported(matchUrl)) { return asHash ? {} : []; } @@ -193,6 +188,7 @@ function filterStylesInternal({ } const needSections = asHash || matchUrl !== null; + const matchUrlBase = matchUrl && matchUrl.includes('#') && matchUrl.split('#', 1)[0]; let style; for (let i = 0; (style = styles[i]); i++) { @@ -200,7 +196,14 @@ function filterStylesInternal({ && (url === null || style.url === url) && (id === null || style.id === id)) { const sections = needSections && - getApplicableSections({style, matchUrl, strictRegexp, stopOnFirst: !asHash}); + getApplicableSections({ + style, + matchUrl, + strictRegexp, + stopOnFirst: !asHash, + skipUrlCheck: true, + matchUrlBase, + }); if (asHash) { if (sections.length) { filtered[style.id] = sections; @@ -322,11 +325,20 @@ function deleteStyle({id, notify = true}) { } -function getApplicableSections({style, matchUrl, strictRegexp = true, stopOnFirst}) { - if (!matchUrl.startsWith('http') - && !matchUrl.startsWith('ftp') - && !matchUrl.startsWith('file') - && !matchUrl.startsWith(URLS.ownOrigin)) { +function getApplicableSections({ + style, + matchUrl, + strictRegexp = true, + // filterStylesInternal() sets the following to avoid recalc on each style: + stopOnFirst, + skipUrlCheck, + matchUrlBase = matchUrl.includes('#') && matchUrl.split('#', 1)[0], + // as per spec the fragment portion is ignored in @-moz-document: + // https://www.w3.org/TR/2012/WD-css3-conditional-20120911/#url-of-doc + // but the spec is outdated and doesn't account for SPA sites + // so we only respect it in case of url("http://exact.url/without/hash") +}) { + if (!skipUrlCheck && !URLS.supported(matchUrl)) { return []; } const sections = []; @@ -335,7 +347,7 @@ function getApplicableSections({style, matchUrl, strictRegexp = true, stopOnFirs const isGlobal = !urls.length && !urlPrefixes.length && !domains.length && !regexps.length; const isMatching = !isGlobal && ( urls.length - && urls.indexOf(matchUrl) >= 0 + && (urls.includes(matchUrl) || matchUrlBase && urls.includes(matchUrlBase)) || urlPrefixes.length && arraySomeIsPrefix(urlPrefixes, matchUrl) || domains.length diff --git a/edit/edit.js b/edit/edit.js index ff29c0d5..1f64ee57 100644 --- a/edit/edit.js +++ b/edit/edit.js @@ -1862,7 +1862,7 @@ function showRegExpTester(event, section = getSectionForChild(this)) { }); queryTabs().then(tabs => { const supported = tabs.map(tab => tab.url) - .filter(url => URLS.supported.test(url)); + .filter(url => URLS.supported(url)); const unique = [...new Set(supported).values()]; for (const rxData of regexps) { const {rx, urls} = rxData; diff --git a/js/messaging.js b/js/messaging.js index ffc594bf..7d916bc9 100644 --- a/js/messaging.js +++ b/js/messaging.js @@ -31,20 +31,15 @@ const URLS = { chromeProtectsNTP: parseInt(navigator.userAgent.match(/Chrom\w+\/(?:\d+\.){2}(\d+)|$/)[1]) >= 3161, - supported: null, + supported: url => ( + url.startsWith('http') && !url.startsWith(URLS.browserWebStore) || + url.startsWith('ftp') || + url.startsWith('file') || + url.startsWith(URLS.ownOrigin) || + !URLS.chromeProtectsNTP && url.startsWith('chrome://newtab/') + ), }; -URLS.supported = new RegExp( - '^(file|ftps?|http)://|' + - `^https://(?!${ - URLS.browserWebStore.split('://')[1].replace(/\./g, '\\.') - })|` + - (URLS.chromeProtectsNTP - ? '^chrome://(?!newtab)/|' - : '') + - '^' + chrome.runtime.getURL('') -); - let BG = chrome.extension.getBackgroundPage(); if (BG && !BG.getStyles && BG !== window) { // own page like editor/manage is being loaded on browser startup diff --git a/popup/popup.js b/popup/popup.js index 09cffa22..364c2b75 100644 --- a/popup/popup.js +++ b/popup/popup.js @@ -9,7 +9,7 @@ const ENTRY_ID_PREFIX_RAW = 'style-'; const ENTRY_ID_PREFIX = '#' + ENTRY_ID_PREFIX_RAW; getActiveTabRealURL().then(url => { - tabURL = URLS.supported.test(url) ? url : ''; + tabURL = URLS.supported(url) ? url : ''; Promise.all([ tabURL && getStylesSafe({matchUrl: tabURL}), onDOMready().then(() => {