29 Commits

Author SHA1 Message Date
William Oldham
ec7d9c1237 Merge pull request #26 from movie-web/dev
Version 1.1.3: Remove Lonelil as default redirect, fix centering and fix type issues
2024-03-15 19:58:15 +00:00
William Oldham
bb61fef30a Merge pull request #25 from movie-web/remove-lonelil
Remove Lonelil, fix centering and enable strict mode
2024-03-15 19:44:19 +00:00
William Oldham
8e179e4455 Remove any in error handling 2024-03-15 19:42:51 +00:00
William Oldham
327f175241 Do safe checking on exception message 2024-03-15 19:39:03 +00:00
William Oldham
c72ec41228 Bump version 2024-03-15 19:24:07 +00:00
William Oldham
0bd1a39b53 Remove react import 2024-03-15 19:24:03 +00:00
William Oldham
de0a1b3849 Fix centering of permission grant page 2024-03-15 18:53:44 +00:00
William Oldham
8ba0544468 Enable TS strict mode and fix all associated errors 2024-03-15 18:49:12 +00:00
William Oldham
a884c785f0 Remove lonelil as a redirect, Firefox didn't like 2024-03-15 18:48:46 +00:00
William Oldham
0801f64e1b Fix content type for extension deployment 2024-03-05 21:13:59 +00:00
William Oldham
8735f7b4b2 Update deploying.yml 2024-03-05 21:13:22 +00:00
William Oldham
a2eef13d28 Merge pull request #24 from movie-web/dev
Version 1.1.2
2024-03-05 21:08:35 +00:00
William Oldham
90f941431c Bump extension to 1.1.2 2024-03-05 18:51:26 +00:00
William Oldham
df05547581 Merge pull request #23 from movie-web/feature/#867
add inactive icon if the domain is not whitelisted
2024-03-05 18:51:01 +00:00
William Oldham
a8e3de1451 Update inactive logo and bold enabled/disabled 2024-03-05 18:46:37 +00:00
Jorrin
1801ee238d Delete icon.development.png 2024-03-04 21:51:15 +01:00
William Oldham
434b2475cb Merge pull request #22 from movie-web/feature/update-default-domains
update default domain whitelist, remove movie-web references
2024-03-04 20:49:24 +00:00
William Oldham
50166457b8 Merge pull request #21 from movie-web/fix/#952
add firstPartyDomain for first-party isolation
2024-03-04 20:48:19 +00:00
Jorrin
e2ea8a3c7e remove unused useEffect 2024-03-04 21:45:37 +01:00
Jorrin
213828e818 add inactive icon if the domain is not whitelisted 2024-03-03 22:56:13 +01:00
Jorrin
755bba3e1e update default domain whitelist, remove movie-web references 2024-03-03 20:20:34 +01:00
Jorrin
e7ca90b75f add firstPartyDomain for first-party isolation 2024-03-03 20:14:56 +01:00
Jorrin
d74f0abbf6 Merge pull request #20 from movie-web/fix/improve-error-message
Improve "Domain is not whitelisted" error message
2024-03-03 13:45:24 +01:00
Jorrin
cade0b50ab Add more details to the error message 2024-03-01 21:59:38 +01:00
Jorrin
1ac8147cdd add instruction to domain whitelist error message 2024-03-01 21:57:18 +01:00
William Oldham
01a03cfeb8 Merge pull request #19 from movie-web/dev
Version 1.1.1 - Apply CORS header rules to all requests regardless of MW set headers
2024-02-21 18:57:54 +00:00
William Oldham
6d1fa16553 Bump version 2024-02-21 18:53:08 +00:00
William Oldham
a8417c75a3 Merge pull request #18 from movie-web/fix/#904
always create dynamic rule for fetch request
2024-02-21 18:50:40 +00:00
Jorrin
abf26103e1 always create dynamic rule for fetch request 2024-02-15 14:17:08 +01:00
19 changed files with 101 additions and 45 deletions

10
.github/SECURITY.md vendored
View File

@@ -2,13 +2,9 @@
## Supported Versions
The movie-web maintainers only support the latest version of movie-web published at https://movie-web.app.
This published version is equivalent to the master branch.
Support is not provided for any forks or mirrors of movie-web.
The latest version of movie-web is the only version that is supported, as it is the only version that is being actively developed.
## Reporting a Vulnerability
There are two ways you can contact the movie-web maintainers to report a vulnerability:
- Email [security@movie-web.app](mailto:security@movie-web.app)
- Report the vulnerability in the [movie-web Discord server](https://discord.movie-web.app)
You can contact the movie-web maintainers to report a vulnerability:
- Report the vulnerability in the [movie-web Discord server](https://movie-web.github.io/links/discord)

View File

@@ -94,8 +94,8 @@ jobs:
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./chrome/chrome-mv3-prod.zip
asset_name: extension-mw.chrome.crx
asset_content_type: application/x-chrome-extension
asset_name: extension-mw.chrome.zip
asset_content_type: application/zip
- name: Upload Firefox release
uses: actions/upload-release-asset@v1

BIN
assets/active.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
assets/inactive.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -1,7 +1,7 @@
{
"name": "@movie-web/extension",
"displayName": "movie-web extension",
"version": "1.1.0",
"version": "1.1.3",
"description": "Enhance your movie-web experience with just one click",
"author": "movie-web",
"scripts": {
@@ -54,6 +54,17 @@
"gecko": {
"id": "{3fd86354-c73f-4395-9e26-2c5c984579bf}"
}
}
},
"web_accessible_resources": [
{
"resources": [
"assets/active.png",
"assets/inactive.png"
],
"matches": [
"<all_urls>"
]
}
]
}
}

View File

@@ -14,6 +14,8 @@ type Response = BaseResponse<{
const handler: PlasmoMessaging.MessageHandler<BaseRequest, Response> = async (req, res) => {
try {
if (!req.sender?.tab?.url) throw new Error('No tab URL found in the request.');
const version = getVersion();
res.send({
success: true,
@@ -24,7 +26,7 @@ const handler: PlasmoMessaging.MessageHandler<BaseRequest, Response> = async (re
} catch (err) {
res.send({
success: false,
error: err.message,
error: err instanceof Error ? err.message : String(err),
});
}
};

View File

@@ -3,6 +3,7 @@ import type { PlasmoMessaging } from '@plasmohq/messaging';
import type { BaseRequest } from '~types/request';
import type { BaseResponse } from '~types/response';
import { removeDynamicRules, setDynamicRules } from '~utils/declarativeNetRequest';
import { isFirefox } from '~utils/extension';
import { makeFullUrl } from '~utils/fetcher';
import { assertDomainWhitelist } from '~utils/storage';
@@ -31,7 +32,7 @@ type Response<T> = BaseResponse<{
const mapBodyToFetchBody = (body: Request['body'], bodyType: Request['bodyType']): BodyInit => {
if (bodyType === 'FormData') {
const formData = new FormData();
body.forEach(([key, value]) => {
body.forEach(([key, value]: [any, any]) => {
formData.append(key, value.toString());
});
}
@@ -49,16 +50,17 @@ const mapBodyToFetchBody = (body: Request['body'], bodyType: Request['bodyType']
const handler: PlasmoMessaging.MessageHandler<Request, Response<any>> = async (req, res) => {
try {
if (!req.sender?.tab?.url) throw new Error('No tab URL found in the request.');
if (!req.body) throw new Error('No request body found in the request.');
const url = makeFullUrl(req.body.url, req.body);
await assertDomainWhitelist(req.sender.tab.url);
if (Object.keys(req.body.headers).length > 0) {
await setDynamicRules({
ruleId: MAKE_REQUEST_DYNAMIC_RULE,
targetDomains: [new URL(url).hostname],
requestHeaders: req.body.headers,
});
}
const response = await fetch(url, {
method: req.body.method,
@@ -71,6 +73,9 @@ const handler: PlasmoMessaging.MessageHandler<Request, Response<any>> = async (r
const cookies = await (chrome || browser).cookies.getAll({
url: response.url,
...(isFirefox() && {
firstPartyDomain: new URL(response.url).hostname,
}),
});
res.send({
@@ -89,7 +94,7 @@ const handler: PlasmoMessaging.MessageHandler<Request, Response<any>> = async (r
console.error('failed request', err);
res.send({
success: false,
error: err.message,
error: err instanceof Error ? err.message : String(err),
});
}
};

View File

@@ -11,6 +11,9 @@ type Request = BaseRequest & {
const handler: PlasmoMessaging.MessageHandler<Request, BaseResponse> = async (req, res) => {
try {
if (!req.sender?.tab?.id) throw new Error('No tab ID found in the request.');
if (!req.body) throw new Error('No body found in the request.');
const searchParams = new URLSearchParams();
searchParams.set('redirectUrl', req.body.redirectUrl);
const url = (chrome || browser).runtime.getURL(`/tabs/${req.body.page}.html?${searchParams.toString()}`);
@@ -29,7 +32,7 @@ const handler: PlasmoMessaging.MessageHandler<Request, BaseResponse> = async (re
} catch (err) {
res.send({
success: false,
error: err.message,
error: err instanceof Error ? err.message : String(err),
});
}
};

View File

@@ -15,6 +15,9 @@ interface Request extends BaseRequest {
const handler: PlasmoMessaging.MessageHandler<Request, BaseResponse> = async (req, res) => {
try {
if (!req.sender?.tab?.url) throw new Error('No tab URL found in the request.');
if (!req.body) throw new Error('No request body found in the request.');
await assertDomainWhitelist(req.sender.tab.url);
await setDynamicRules(req.body);
res.send({
@@ -23,7 +26,7 @@ const handler: PlasmoMessaging.MessageHandler<Request, BaseResponse> = async (re
} catch (err) {
res.send({
success: false,
error: err.message,
error: err instanceof Error ? err.message : String(err),
});
}
};

View File

@@ -36,7 +36,7 @@ export function ToggleButton(props: ToggleButtonProps) {
</button>
</div>
<p>
Extension {props.active ? 'enabled' : 'disabled'} <br /> on <strong>{props.domain}</strong>
Extension <strong>{props.active ? 'enabled' : 'disabled'}</strong> <br /> on <strong>{props.domain}</strong>
</p>
</div>
);

View File

@@ -15,5 +15,5 @@ export function useDomain(): null | string {
};
}, []);
return makeUrlIntoDomain(domain);
return domain ? makeUrlIntoDomain(domain) : null;
}

View File

@@ -8,12 +8,12 @@ export function useDomainWhitelist() {
const removeDomain = useCallback((domain: string | null) => {
if (!domain) return;
setDomainWhitelist((s) => [...s.filter((v) => v !== domain)]);
setDomainWhitelist((s) => [...(s ?? []).filter((v) => v !== domain)]);
}, []);
const addDomain = useCallback((domain: string | null) => {
if (!domain) return;
setDomainWhitelist((s) => [...s.filter((v) => v !== domain), domain]);
setDomainWhitelist((s) => [...(s ?? []).filter((v) => v !== domain), domain]);
}, []);
return {
@@ -27,6 +27,11 @@ export function useToggleWhitelistDomain(domain: string) {
const { domainWhitelist, addDomain, removeDomain } = useDomainWhitelist();
const isWhitelisted = domainWhitelist.includes(domain);
const { grantPermission } = usePermission();
const iconPath = (chrome || browser).runtime.getURL(isWhitelisted ? 'assets/active.png' : 'assets/inactive.png');
(chrome || browser).action.setIcon({
path: iconPath,
});
const toggle = useCallback(() => {
if (!isWhitelisted) {

View File

@@ -13,7 +13,7 @@ body {
#__plasmo {
display: flex;
flex-direction: column;
min-height: 100%;
height: 100%;
background-color: #0A0A10;
}

View File

@@ -8,11 +8,27 @@ export default function PermissionGrant() {
const { grantPermission } = usePermission();
const queryParams = new URLSearchParams(window.location.search);
const redirectUrl = queryParams.get('redirectUrl') ?? 'https://movie-web.app';
const domain = makeUrlIntoDomain(redirectUrl);
const redirectUrl = queryParams.get('redirectUrl') ?? undefined;
const domain = redirectUrl ? makeUrlIntoDomain(redirectUrl) : undefined;
if (!domain) {
return (
<div className="permission-grant container">
<div className="inner-container">
<div className="permission-card">
<h1 className="color-white">Permission</h1>
<p className="text-color" style={{ textAlign: 'center' }}>
No domain found to grant permission to.
</p>
</div>
</div>
</div>
);
}
const redirectBack = () => {
chrome.tabs.getCurrent((tab) => {
if (!tab?.id) return;
chrome.tabs.update(tab.id, { url: redirectUrl });
});
};

View File

@@ -123,5 +123,6 @@ 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);
if ((chrome || browser).runtime.lastError?.message)
throw new Error((chrome || browser).runtime.lastError?.message ?? 'Unknown error');
};

View File

@@ -1,3 +1,11 @@
export const isChrome = () => {
return chrome.runtime.getURL('').startsWith('chrome-extension://');
};
export const isFirefox = () => {
try {
return browser.runtime.getURL('').startsWith('moz-extension://');
} catch {
return false;
}
};

View File

@@ -3,7 +3,14 @@ import { useStorage } from '@plasmohq/storage/hook';
import { makeUrlIntoDomain } from '~utils/domains';
export const DEFAULT_DOMAIN_WHITELIST = ['movie-web.app', 'dev.movie-web.app'];
export const DEFAULT_DOMAIN_WHITELIST = [
'mw.lonelil.ru',
'watch.qtchaos.de',
'bmov.vercel.app',
'stream.thehairy.me',
'scootydooter.vercel.app',
'movie-web-me.vercel.app',
];
export const storage = new Storage();
@@ -31,5 +38,9 @@ export const isDomainWhitelisted = async (url: string | undefined) => {
export const assertDomainWhitelist = async (url: string) => {
const isWhiteListed = await isDomainWhitelisted(url);
if (!isWhiteListed) throw new Error('Domain is not whitelisted');
const currentDomain = makeUrlIntoDomain(url);
if (!isWhiteListed)
throw new Error(
`${currentDomain} is not whitelisted. Open the extension and click on the power button to whitelist the site.`,
);
};

View File

@@ -1,7 +1,7 @@
import { isChrome } from './extension';
export function queryCurrentDomain(cb: (domain: string | null) => void) {
const handle = (tabUrl: string | null) => {
const handle = (tabUrl: string | undefined) => {
if (!tabUrl) cb(null);
else cb(tabUrl);
};

View File

@@ -1,18 +1,13 @@
{
"extends": "plasmo/templates/tsconfig.base",
"exclude": [
"node_modules"
],
"include": [
".plasmo/index.d.ts",
"./**/*.ts",
"./**/*.tsx"
],
"exclude": ["node_modules"],
"include": [".plasmo/index.d.ts", "./**/*.ts", "./**/*.tsx"],
"compilerOptions": {
"jsx": "react-jsx",
"strict": true,
"paths": {
"~*": [
"./src/*"
]
"~*": ["./src/*"]
},
"baseUrl": "."
}