parent
5b2dba4cdf
commit
7c9fd5e611
|
@ -330,12 +330,13 @@
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
document.documentElement.appendChild(document.createElement('script')).text = '(' +
|
// run in page context
|
||||||
function () {
|
document.documentElement.appendChild(document.createElement('script')).text = `(${
|
||||||
|
EXTENSION_ORIGIN => {
|
||||||
document.currentScript.remove();
|
document.currentScript.remove();
|
||||||
|
|
||||||
// spoof Stylish extension presence in Chrome
|
// spoof Stylish extension presence in Chrome
|
||||||
if (chrome.app) {
|
if (window.chrome && chrome.app) {
|
||||||
const realImage = window.Image;
|
const realImage = window.Image;
|
||||||
window.Image = function Image(...args) {
|
window.Image = function Image(...args) {
|
||||||
return new Proxy(new realImage(...args), {
|
return new Proxy(new realImage(...args), {
|
||||||
|
@ -354,6 +355,29 @@ document.documentElement.appendChild(document.createElement('script')).text = '(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// spoof USO referrer for style search in the popup
|
||||||
|
if (window !== top && location.pathname === '/') {
|
||||||
|
window.addEventListener('message', ({data, origin}) => {
|
||||||
|
if (!data ||
|
||||||
|
!data.xhr ||
|
||||||
|
origin !== EXTENSION_ORIGIN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.responseType = 'json';
|
||||||
|
xhr.onloadend = xhr.onerror = () => {
|
||||||
|
window.stop();
|
||||||
|
top.postMessage({
|
||||||
|
id: data.xhr.id,
|
||||||
|
status: xhr.status,
|
||||||
|
response: xhr.response,
|
||||||
|
}, EXTENSION_ORIGIN);
|
||||||
|
};
|
||||||
|
xhr.open('GET', data.xhr.url);
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// USO bug workaround: use the actual style settings in API response
|
// USO bug workaround: use the actual style settings in API response
|
||||||
let settings;
|
let settings;
|
||||||
const originalResponseJson = Response.prototype.json;
|
const originalResponseJson = Response.prototype.json;
|
||||||
|
@ -426,7 +450,8 @@ document.documentElement.appendChild(document.createElement('script')).text = '(
|
||||||
return json;
|
return json;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
} + ')()';
|
}
|
||||||
|
})('${chrome.runtime.getURL('').slice(0, -1)}')`;
|
||||||
|
|
||||||
// TODO: remove the following statement when USO pagination is fixed
|
// TODO: remove the following statement when USO pagination is fixed
|
||||||
if (location.search.includes('category=')) {
|
if (location.search.includes('category=')) {
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"tabs",
|
"tabs",
|
||||||
"webNavigation",
|
"webNavigation",
|
||||||
|
"webRequest",
|
||||||
|
"webRequestBlocking",
|
||||||
"contextMenus",
|
"contextMenus",
|
||||||
"storage",
|
"storage",
|
||||||
"alarms",
|
"alarms",
|
||||||
|
@ -60,7 +62,7 @@
|
||||||
{
|
{
|
||||||
"matches": ["http://userstyles.org/*", "https://userstyles.org/*"],
|
"matches": ["http://userstyles.org/*", "https://userstyles.org/*"],
|
||||||
"run_at": "document_start",
|
"run_at": "document_start",
|
||||||
"all_frames": false,
|
"all_frames": true,
|
||||||
"js": ["content/install-hook-userstyles.js"]
|
"js": ["content/install-hook-userstyles.js"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,6 +51,9 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
let searchCurrentPage = 1;
|
let searchCurrentPage = 1;
|
||||||
let searchExhausted = false;
|
let searchExhausted = false;
|
||||||
|
|
||||||
|
let searchFrame;
|
||||||
|
let searchFrameQueue;
|
||||||
|
|
||||||
const processedResults = [];
|
const processedResults = [];
|
||||||
const unprocessedResults = [];
|
const unprocessedResults = [];
|
||||||
|
|
||||||
|
@ -697,15 +700,7 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
return readCache(cacheKey)
|
return readCache(cacheKey)
|
||||||
.then(json =>
|
.then(json =>
|
||||||
json ||
|
json ||
|
||||||
download(searchURL, {
|
searchInFrame(searchURL).then(writeCache))
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-type': 'application/json',
|
|
||||||
'Accept': '*/*'
|
|
||||||
},
|
|
||||||
responseType: 'json',
|
|
||||||
body: null
|
|
||||||
}).then(writeCache))
|
|
||||||
.then(json => {
|
.then(json => {
|
||||||
searchCurrentPage = json.current_page + 1;
|
searchCurrentPage = json.current_page + 1;
|
||||||
searchTotalPages = json.total_pages;
|
searchTotalPages = json.total_pages;
|
||||||
|
@ -783,5 +778,78 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
ignoreChromeError();
|
ignoreChromeError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
//region USO referrer spoofing via iframe
|
||||||
|
|
||||||
|
function searchInFrame(url) {
|
||||||
|
return searchFrame ? new Promise((resolve, reject) => {
|
||||||
|
const id = performance.now();
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
searchFrameQueue.get(id).reject();
|
||||||
|
searchFrameQueue.delete(id);
|
||||||
|
}, 10e3);
|
||||||
|
searchFrameQueue.set(id, {resolve, reject, timeout});
|
||||||
|
searchFrame.contentWindow.postMessage({xhr: {id, url}}, '*');
|
||||||
|
}) : setupFrame().then(() => searchInFrame(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupFrame() {
|
||||||
|
searchFrame = $create('iframe', {src: BASE_URL});
|
||||||
|
searchFrameQueue = new Map();
|
||||||
|
|
||||||
|
const stripHeaders = info => ({
|
||||||
|
responseHeaders: info.responseHeaders.filter(({name}) => !/^X-Frame-Options$/i.test(name)),
|
||||||
|
});
|
||||||
|
chrome.webRequest.onHeadersReceived.addListener(stripHeaders, {
|
||||||
|
urls: [BASE_URL + '/'],
|
||||||
|
types: ['sub_frame'],
|
||||||
|
}, [
|
||||||
|
'blocking',
|
||||||
|
'responseHeaders',
|
||||||
|
]);
|
||||||
|
|
||||||
|
let frameId;
|
||||||
|
const stripResources = info => {
|
||||||
|
if (!frameId && info.url === BASE_URL + '/') {
|
||||||
|
frameId = info.frameId;
|
||||||
|
} else if (frameId === info.frameId && info.type !== 'xmlhttprequest') {
|
||||||
|
return {redirectUrl: 'data:,'};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
chrome.webRequest.onBeforeRequest.addListener(stripResources, {
|
||||||
|
urls: ['<all_urls>'],
|
||||||
|
}, [
|
||||||
|
'blocking',
|
||||||
|
]);
|
||||||
|
setTimeout(() => {
|
||||||
|
chrome.webRequest.onBeforeRequest.removeListener(stripResources);
|
||||||
|
}, 10e3);
|
||||||
|
|
||||||
|
window.addEventListener('message', ({data, origin}) => {
|
||||||
|
if (!data || origin !== BASE_URL) return;
|
||||||
|
const {resolve, reject, timeout} = searchFrameQueue.get(data.id) || {};
|
||||||
|
if (!resolve) return;
|
||||||
|
chrome.webRequest.onBeforeRequest.removeListener(stripResources);
|
||||||
|
searchFrameQueue.delete(data.id);
|
||||||
|
clearTimeout(timeout);
|
||||||
|
if (data.response && data.status < 400) {
|
||||||
|
resolve(data.response);
|
||||||
|
} else {
|
||||||
|
reject(data.status);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const done = event => {
|
||||||
|
chrome.webRequest.onHeadersReceived.removeListener(stripHeaders);
|
||||||
|
(event.type === 'load' ? resolve : reject)();
|
||||||
|
};
|
||||||
|
searchFrame.addEventListener('load', done, {once: true});
|
||||||
|
searchFrame.addEventListener('error', done, {once: true});
|
||||||
|
searchFrame.style.setProperty('display', 'none', 'important');
|
||||||
|
document.body.appendChild(searchFrame);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user