9 Commits
1.0.1 ... 1.0.2

Author SHA1 Message Date
William Oldham
6a3d32dcc3 Merge pull request #9 from movie-web/dev
Extension v1.0.2
2024-01-25 21:39:15 +00:00
William Oldham
3b88b136e8 Merge pull request #8 from movie-web/firefox-android-styling
Make frame compatible with firefox android
2024-01-25 21:28:39 +00:00
mrjvs
67ef3a1e88 Merge pull request #7 from movie-web/feature/#820
Add FormData, URLSearchParams and User-Agent support
2024-01-25 20:37:22 +01:00
mrjvs
302b6ef71c Make frame compatible with firefox android 2024-01-25 20:25:00 +01:00
Jorrin
c740bc6685 Replace record type logic with their own bodyType 2024-01-25 19:38:06 +01:00
Jorrin
f49cd01b7a return body if body type is undefined 2024-01-25 19:27:19 +01:00
Jorrin
65ff4ab91a mr feedback 2024-01-25 19:25:44 +01:00
Jorrin
a2647a58d6 cleanup and fix targetDomain 2024-01-25 16:38:04 +01:00
Jorrin
658f59eb24 serialize body 2024-01-24 19:41:20 +01:00
7 changed files with 168 additions and 110 deletions

View File

@@ -1,7 +1,7 @@
{ {
"name": "@movie-web/extension", "name": "@movie-web/extension",
"displayName": "movie-web extension", "displayName": "movie-web extension",
"version": "1.0.1", "version": "1.0.2",
"description": "Enhance your movie-web experience with just one click", "description": "Enhance your movie-web experience with just one click",
"author": "movie-web", "author": "movie-web",
"scripts": { "scripts": {

View File

@@ -1,6 +1,13 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@500;800&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Inter:wght@500;800&display=swap');
html {
min-height: 300px;
min-width: 300px;
}
body { body {
min-height: 300px;
min-width: 300px;
margin: 0; margin: 0;
font-family: 'Inter', sans-serif; font-family: 'Inter', sans-serif;
} }

View File

@@ -2,9 +2,12 @@ import type { PlasmoMessaging } from '@plasmohq/messaging';
import type { BaseRequest } from '~types/request'; import type { BaseRequest } from '~types/request';
import type { BaseResponse } from '~types/response'; import type { BaseResponse } from '~types/response';
import { removeDynamicRules, setDynamicRules } from '~utils/declarativeNetRequest';
import { makeFullUrl } from '~utils/fetcher'; import { makeFullUrl } from '~utils/fetcher';
import { assertDomainWhitelist } from '~utils/storage'; import { assertDomainWhitelist } from '~utils/storage';
const MAKE_REQUEST_DYNAMIC_RULE = 23498;
export interface Request extends BaseRequest { export interface Request extends BaseRequest {
baseUrl?: string; baseUrl?: string;
headers?: Record<string, string>; headers?: Record<string, string>;
@@ -12,7 +15,8 @@ export interface Request extends BaseRequest {
query?: Record<string, string>; query?: Record<string, string>;
readHeaders?: Record<string, string>; readHeaders?: Record<string, string>;
url: string; url: string;
body?: string | FormData | URLSearchParams; body?: any;
bodyType?: 'string' | 'FormData' | 'URLSearchParams' | 'object';
} }
type Response<T> = BaseResponse<{ type Response<T> = BaseResponse<{
@@ -24,15 +28,45 @@ type Response<T> = BaseResponse<{
}; };
}>; }>;
const mapBodyToFetchBody = (body: Request['body'], bodyType: Request['bodyType']): BodyInit => {
if (bodyType === 'FormData') {
const formData = new FormData();
body.forEach(([key, value]) => {
formData.append(key, value.toString());
});
}
if (bodyType === 'URLSearchParams') {
return new URLSearchParams(body);
}
if (bodyType === 'object') {
return JSON.stringify(body);
}
if (bodyType === 'string') {
return body;
}
return body;
};
const handler: PlasmoMessaging.MessageHandler<Request, Response<any>> = async (req, res) => { const handler: PlasmoMessaging.MessageHandler<Request, Response<any>> = async (req, res) => {
try { try {
await assertDomainWhitelist(req.sender.tab.url); await assertDomainWhitelist(req.sender.tab.url);
if (req.body.headers['User-Agent']) {
await setDynamicRules({
ruleId: MAKE_REQUEST_DYNAMIC_RULE,
targetDomains: [new URL(req.body.url).hostname],
requestHeaders: {
'User-Agent': req.body.headers['User-Agent'],
},
});
}
const response = await fetch(makeFullUrl(req.body.url, req.body), { const response = await fetch(makeFullUrl(req.body.url, req.body), {
method: req.body.method, method: req.body.method,
headers: req.body.headers, headers: req.body.headers,
body: req.body.body, body: mapBodyToFetchBody(req.body.body, req.body.bodyType),
}); });
await removeDynamicRules([MAKE_REQUEST_DYNAMIC_RULE]);
const contentType = response.headers.get('content-type'); const contentType = response.headers.get('content-type');
const body = contentType?.includes('application/json') ? await response.json() : await response.text(); const body = contentType?.includes('application/json') ? await response.json() : await response.text();

View File

@@ -2,7 +2,7 @@ import type { PlasmoMessaging } from '@plasmohq/messaging';
import type { BaseRequest } from '~types/request'; import type { BaseRequest } from '~types/request';
import type { BaseResponse } from '~types/response'; import type { BaseResponse } from '~types/response';
import { isChrome } from '~utils/extension'; import { setDynamicRules } from '~utils/declarativeNetRequest';
import { assertDomainWhitelist } from '~utils/storage'; import { assertDomainWhitelist } from '~utils/storage';
interface Request extends BaseRequest { interface Request extends BaseRequest {
@@ -13,108 +13,10 @@ interface Request extends BaseRequest {
responseHeaders?: Record<string, string>; responseHeaders?: Record<string, string>;
} }
const mapHeadersToDeclarativeNetRequestHeaders = (
headers: Record<string, string>,
op: string,
): { header: string; operation: any; value: string }[] => {
return Object.entries(headers).map(([name, value]) => ({
header: name,
operation: op,
value,
}));
};
const handler: PlasmoMessaging.MessageHandler<Request, BaseResponse> = async (req, res) => { const handler: PlasmoMessaging.MessageHandler<Request, BaseResponse> = async (req, res) => {
try { try {
await assertDomainWhitelist(req.sender.tab.url); await assertDomainWhitelist(req.sender.tab.url);
if (isChrome()) { await setDynamicRules(req.body);
await chrome.declarativeNetRequest.updateDynamicRules({
removeRuleIds: [req.body.ruleId],
addRules: [
{
id: req.body.ruleId,
condition: {
...(req.body.targetDomains && { requestDomains: req.body.targetDomains }),
...(req.body.targetRegex && { regexFilter: req.body.targetRegex }),
},
action: {
type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
...(req.body.requestHeaders && Object.keys(req.body.requestHeaders).length > 0
? {
requestHeaders: mapHeadersToDeclarativeNetRequestHeaders(
req.body.requestHeaders,
chrome.declarativeNetRequest.HeaderOperation.SET,
),
}
: {}),
responseHeaders: [
{
header: 'Access-Control-Allow-Origin',
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
value: '*',
},
{
header: 'Access-Control-Allow-Methods',
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
value: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
},
{
header: 'Access-Control-Allow-Headers',
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
value: '*',
},
...mapHeadersToDeclarativeNetRequestHeaders(
req.body.responseHeaders ?? {},
chrome.declarativeNetRequest.HeaderOperation.SET,
),
],
},
},
],
});
if (chrome.runtime.lastError?.message) throw new Error(chrome.runtime.lastError.message);
} else {
await browser.declarativeNetRequest.updateDynamicRules({
removeRuleIds: [req.body.ruleId],
addRules: [
{
id: req.body.ruleId,
condition: {
...(req.body.targetDomains && { requestDomains: req.body.targetDomains }),
...(req.body.targetRegex && { regexFilter: req.body.targetRegex }),
},
action: {
type: 'modifyHeaders',
...(req.body.requestHeaders && Object.keys(req.body.requestHeaders).length > 0
? {
requestHeaders: mapHeadersToDeclarativeNetRequestHeaders(req.body.requestHeaders, 'set'),
}
: {}),
responseHeaders: [
{
header: 'Access-Control-Allow-Origin',
operation: 'set',
value: '*',
},
{
header: 'Access-Control-Allow-Methods',
operation: 'set',
value: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
},
{
header: 'Access-Control-Allow-Headers',
operation: 'set',
value: '*',
},
...mapHeadersToDeclarativeNetRequestHeaders(req.body.responseHeaders ?? {}, 'set'),
],
},
},
],
});
if (browser.runtime.lastError?.message) throw new Error(browser.runtime.lastError.message);
}
res.send({ res.send({
success: true, success: true,
}); });

View File

@@ -1,4 +1,6 @@
.frame { .frame {
height: 100%;
width: 100%;
background-color: #0a080e; background-color: #0a080e;
background-image: radial-gradient(271.48% 132.05% at 136.13% 65.62%, #271945b3 0%, #1c1c2c00 100%), radial-gradient(671.15% 123.02% at 76.68% -34.38%, #272753 0%, #17172000 100%); background-image: radial-gradient(271.48% 132.05% at 136.13% 65.62%, #271945b3 0%, #1c1c2c00 100%), radial-gradient(671.15% 123.02% at 76.68% -34.38%, #272753 0%, #17172000 100%);
} }

View File

@@ -7,9 +7,5 @@ export interface FrameProps {
} }
export function Frame(props: FrameProps) { export function Frame(props: FrameProps) {
return ( return <div className="frame">{props.children}</div>;
<div className="frame" style={{ width: 300, height: 300 }}>
{props.children}
</div>
);
} }

View File

@@ -0,0 +1,117 @@
import { isChrome } from './extension';
interface DynamicRule {
ruleId: number;
targetDomains?: [string, ...string[]];
targetRegex?: string;
requestHeaders?: Record<string, string>;
responseHeaders?: Record<string, string>;
}
const mapHeadersToDeclarativeNetRequestHeaders = (
headers: Record<string, string>,
op: string,
): { header: string; operation: any; value: string }[] => {
return Object.entries(headers).map(([name, value]) => ({
header: name,
operation: op,
value,
}));
};
export const setDynamicRules = async (body: DynamicRule) => {
if (isChrome()) {
await chrome.declarativeNetRequest.updateDynamicRules({
removeRuleIds: [body.ruleId],
addRules: [
{
id: body.ruleId,
condition: {
...(body.targetDomains && { requestDomains: body.targetDomains }),
...(body.targetRegex && { regexFilter: body.targetRegex }),
},
action: {
type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
...(body.requestHeaders && Object.keys(body.requestHeaders).length > 0
? {
requestHeaders: mapHeadersToDeclarativeNetRequestHeaders(
body.requestHeaders,
chrome.declarativeNetRequest.HeaderOperation.SET,
),
}
: {}),
responseHeaders: [
{
header: 'Access-Control-Allow-Origin',
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
value: '*',
},
{
header: 'Access-Control-Allow-Methods',
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
value: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
},
{
header: 'Access-Control-Allow-Headers',
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
value: '*',
},
...mapHeadersToDeclarativeNetRequestHeaders(
body.responseHeaders ?? {},
chrome.declarativeNetRequest.HeaderOperation.SET,
),
],
},
},
],
});
if (chrome.runtime.lastError?.message) throw new Error(chrome.runtime.lastError.message);
} else {
await browser.declarativeNetRequest.updateDynamicRules({
removeRuleIds: [body.ruleId],
addRules: [
{
id: body.ruleId,
condition: {
...(body.targetDomains && { requestDomains: body.targetDomains }),
...(body.targetRegex && { regexFilter: body.targetRegex }),
},
action: {
type: 'modifyHeaders',
...(body.requestHeaders && Object.keys(body.requestHeaders).length > 0
? {
requestHeaders: mapHeadersToDeclarativeNetRequestHeaders(body.requestHeaders, 'set'),
}
: {}),
responseHeaders: [
{
header: 'Access-Control-Allow-Origin',
operation: 'set',
value: '*',
},
{
header: 'Access-Control-Allow-Methods',
operation: 'set',
value: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
},
{
header: 'Access-Control-Allow-Headers',
operation: 'set',
value: '*',
},
...mapHeadersToDeclarativeNetRequestHeaders(body.responseHeaders ?? {}, 'set'),
],
},
},
],
});
if (browser.runtime.lastError?.message) throw new Error(browser.runtime.lastError.message);
}
};
export const removeDynamicRules = async (ruleIds: number[]) => {
await (chrome || browser).declarativeNetRequest.updateDynamicRules({
removeRuleIds: ruleIds,
});
if ((chrome || browser).runtime.lastError?.message) throw new Error((chrome || browser).runtime.lastError.message);
};