invoke USO style API in iframe

fixes #417
This commit is contained in:
tophf 2018-07-05 21:01:50 +03:00
parent 626030c42c
commit 7f5a5fecbf
2 changed files with 25 additions and 31 deletions

View File

@ -380,7 +380,6 @@ document.documentElement.appendChild(document.createElement('script')).text = `(
} }
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
xhr.onloadend = xhr.onerror = () => { xhr.onloadend = xhr.onerror = () => {
window.stop();
top.postMessage({ top.postMessage({
id: data.xhr.id, id: data.xhr.id,
status: xhr.status, status: xhr.status,

View File

@ -52,8 +52,8 @@ window.addEventListener('showStyles:done', function _() {
let searchCurrentPage = 1; let searchCurrentPage = 1;
let searchExhausted = false; let searchExhausted = false;
let searchFrame; let usoFrame;
let searchFrameQueue; let usoFrameQueue;
const processedResults = []; const processedResults = [];
const unprocessedResults = []; const unprocessedResults = [];
@ -651,9 +651,7 @@ window.addEventListener('showStyles:done', function _() {
function fetchStyleJson(result) { function fetchStyleJson(result) {
return Promise.resolve( return Promise.resolve(
result.json || result.json ||
download(BASE_URL + '/styles/chrome/' + result.id + '.json', { downloadInFrame(BASE_URL + '/styles/chrome/' + result.id + '.json').then(json => {
responseType: 'json',
}).then(json => {
result.json = json; result.json = json;
return json; return json;
})); }));
@ -667,15 +665,7 @@ window.addEventListener('showStyles:done', function _() {
function fetchStyle(userstylesId) { function fetchStyle(userstylesId) {
return readCache(userstylesId).then(json => return readCache(userstylesId).then(json =>
json || json ||
download(BASE_URL + '/api/v1/styles/' + userstylesId, { downloadInFrame(BASE_URL + '/api/v1/styles/' + userstylesId).then(writeCache));
method: 'GET',
headers: {
'Content-type': 'application/json',
'Accept': '*/*'
},
responseType: 'json',
body: null
}).then(writeCache));
} }
/** /**
@ -704,7 +694,7 @@ window.addEventListener('showStyles:done', function _() {
return readCache(cacheKey) return readCache(cacheKey)
.then(json => .then(json =>
json || json ||
searchInFrame(searchURL).then(writeCache)) downloadInFrame(searchURL).then(writeCache))
.then(json => { .then(json => {
searchCurrentPage = json.current_page + 1; searchCurrentPage = json.current_page + 1;
searchTotalPages = json.total_pages; searchTotalPages = json.total_pages;
@ -787,21 +777,26 @@ window.addEventListener('showStyles:done', function _() {
//endregion //endregion
//region USO referrer spoofing via iframe //region USO referrer spoofing via iframe
function searchInFrame(url) { function downloadInFrame(url) {
return searchFrame ? new Promise((resolve, reject) => { return usoFrame ? new Promise((resolve, reject) => {
const id = performance.now(); const id = performance.now();
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
searchFrameQueue.get(id).reject(); const {reject} = usoFrameQueue.get(id) || {};
searchFrameQueue.delete(id); usoFrameQueue.delete(id);
if (reject) reject();
}, 10e3); }, 10e3);
searchFrameQueue.set(id, {resolve, reject, timeout}); const data = {url, resolve, reject, timeout};
searchFrame.contentWindow.postMessage({xhr: {id, url}}, '*'); usoFrameQueue.set(id, data);
}) : setupFrame().then(() => searchInFrame(url)); usoFrame.contentWindow.postMessage({xhr: {id, url}}, '*');
}) :
setupFrame()
.then(() => new Promise(setTimeout))
.then(() => downloadInFrame(url));
} }
function setupFrame() { function setupFrame() {
searchFrame = $create('iframe', {src: BASE_URL}); usoFrame = $create('iframe', {src: BASE_URL});
searchFrameQueue = new Map(); usoFrameQueue = new Map();
const stripHeaders = info => ({ const stripHeaders = info => ({
responseHeaders: info.responseHeaders.filter(({name}) => !/^X-Frame-Options$/i.test(name)), responseHeaders: info.responseHeaders.filter(({name}) => !/^X-Frame-Options$/i.test(name)),
@ -833,10 +828,10 @@ window.addEventListener('showStyles:done', function _() {
window.addEventListener('message', ({data, origin}) => { window.addEventListener('message', ({data, origin}) => {
if (!data || origin !== BASE_URL) return; if (!data || origin !== BASE_URL) return;
const {resolve, reject, timeout} = searchFrameQueue.get(data.id) || {}; const {resolve, reject, timeout} = usoFrameQueue.get(data.id) || {};
if (!resolve) return; if (!resolve) return;
chrome.webRequest.onBeforeRequest.removeListener(stripResources); chrome.webRequest.onBeforeRequest.removeListener(stripResources);
searchFrameQueue.delete(data.id); usoFrameQueue.delete(data.id);
clearTimeout(timeout); clearTimeout(timeout);
// [being overcautious] a string response is used instead of relying on responseType=json // [being overcautious] a string response is used instead of relying on responseType=json
// because it was invoked in a web page context so another extension may have incorrectly spoofed it // because it was invoked in a web page context so another extension may have incorrectly spoofed it
@ -853,10 +848,10 @@ window.addEventListener('showStyles:done', function _() {
chrome.webRequest.onHeadersReceived.removeListener(stripHeaders); chrome.webRequest.onHeadersReceived.removeListener(stripHeaders);
(event.type === 'load' ? resolve : reject)(); (event.type === 'load' ? resolve : reject)();
}; };
searchFrame.addEventListener('load', done, {once: true}); usoFrame.addEventListener('load', done, {once: true});
searchFrame.addEventListener('error', done, {once: true}); usoFrame.addEventListener('error', done, {once: true});
searchFrame.style.setProperty('display', 'none', 'important'); usoFrame.style.setProperty('display', 'none', 'important');
document.body.appendChild(searchFrame); document.body.appendChild(usoFrame);
}); });
} }