Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introduce enhanced installation prompts and setting #620

Merged
merged 7 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions public/ext/safari-15/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,14 @@
},
{
"js": ["dist/content-scripts/dot-user-js.js"],
"matches": [
"*://*/*.user.js",
"*://*/*.user.js?*",
"*://*/*.user.css",
"*://*/*.user.css?*"
],
"run_at": "document_start",
"all_frames": false
"matches": ["*://*/*.user.js", "*://*/*.user.js?*"],
"run_at": "document_start"
},
{
"js": ["dist/content-scripts/greasyfork.js"],
"js": ["dist/content-scripts/script-market.js"],
"matches": ["*://*.greasyfork.org/*"],
"run_at": "document_start",
"all_frames": false
"exclude_matches": ["*://*/*.user.js", "*://*/*.user.js?*"],
"run_at": "document_end"
}
],
"permissions": [
Expand Down
6 changes: 6 additions & 0 deletions public/ext/shared/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@
"settings_settings_sync_desc": {
"message": "Sync settings across devices"
},
"settings_augmented_userjs_install": {
"message": "Enhanced installation prompts"
},
"settings_augmented_userjs_install_desc": {
"message": "Automatically pop up the installation interface when opening a user script URL (.user.js), and takes over the install button of the user scripts market"
},
"settings_toolbar_badge_count": {
"message": "Show Toolbar Count Badge"
},
Expand Down
6 changes: 6 additions & 0 deletions public/ext/shared/_locales/zh/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@
"settings_settings_sync_desc": {
"message": "跨设备同步设置"
},
"settings_augmented_userjs_install": {
"message": "增强的脚本安装提示"
},
"settings_augmented_userjs_install_desc": {
"message": "当打开一个用户脚本 URL(.user.js)时自动弹出安装界面,并接管用户脚本市场的安装按钮"
},
"settings_toolbar_badge_count": {
"message": "工具栏图标显示计数徽章"
},
Expand Down
6 changes: 6 additions & 0 deletions public/ext/shared/_locales/zh_HK/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@
"settings_settings_sync_desc": {
"message": "跨裝置同步設定"
},
"settings_augmented_userjs_install": {
"message": "增強的腳本安裝提示"
},
"settings_augmented_userjs_install_desc": {
"message": "當開啟一個使用者腳本 URL(.user.js)時自動彈出安裝介面,並接管使用者腳本市場的安裝按鈕"
},
"settings_toolbar_badge_count": {
"message": "工具欄圖示顯示計數徽章"
},
Expand Down
6 changes: 6 additions & 0 deletions public/ext/shared/_locales/zh_MO/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@
"settings_settings_sync_desc": {
"message": "跨裝置同步設定"
},
"settings_augmented_userjs_install": {
"message": "增強的腳本安裝提示"
},
"settings_augmented_userjs_install_desc": {
"message": "當開啟一個使用者腳本 URL(.user.js)時自動彈出安裝介面,並接管使用者腳本市場的安裝按鈕"
},
"settings_toolbar_badge_count": {
"message": "工具欄圖示顯示計數徽章"
},
Expand Down
6 changes: 6 additions & 0 deletions public/ext/shared/_locales/zh_TW/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@
"settings_settings_sync_desc": {
"message": "跨裝置同步設定"
},
"settings_augmented_userjs_install": {
"message": "增強的腳本安裝提示"
},
"settings_augmented_userjs_install_desc": {
"message": "當開啟一個使用者腳本 URL(.user.js)時自動彈出安裝介面,並接管使用者腳本市場的安裝按鈕"
},
"settings_toolbar_badge_count": {
"message": "工具欄圖示顯示計數徽章"
},
Expand Down
1 change: 1 addition & 0 deletions scripts/build-ext-demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const defineConfig = {
define: {
"import.meta.env.BROWSER": JSON.stringify("Safari"),
"import.meta.env.NATIVE_APP": JSON.stringify("app"),
"import.meta.env.SAFARI_VERSION": JSON.stringify(15),
"import.meta.env.SAFARI_PLATFORM": JSON.stringify(
process.env.SAFARI_PLATFORM,
),
Expand Down
3 changes: 2 additions & 1 deletion scripts/build-ext-safari-15.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const defineConfig = {
define: {
"import.meta.env.BROWSER": JSON.stringify("Safari"),
"import.meta.env.NATIVE_APP": JSON.stringify("app"),
"import.meta.env.SAFARI_VERSION": JSON.stringify(15),
"import.meta.env.SAFARI_PLATFORM": JSON.stringify(
process.env.SAFARI_PLATFORM,
),
Expand All @@ -52,7 +53,7 @@ cp("public/ext/safari-15", SAFARI_EXT_RESOURCES);
[
{ userscripts: "src/ext/content-scripts/entry-userscripts.js" },
{ "dot-user-js": "src/ext/content-scripts/entry-dot-user-js.js" },
{ greasyfork: "src/ext/content-scripts/entry-greasyfork.js" },
{ "script-market": "src/ext/content-scripts/entry-script-market.js" },
].forEach((input) => {
build({
...defineConfig,
Expand Down
3 changes: 2 additions & 1 deletion scripts/build-ext-safari-16.4.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const defineConfig = {
define: {
"import.meta.env.BROWSER": JSON.stringify("Safari"),
"import.meta.env.NATIVE_APP": JSON.stringify("app"),
"import.meta.env.SAFARI_VERSION": JSON.stringify(16.4),
"import.meta.env.SAFARI_PLATFORM": JSON.stringify(
process.env.SAFARI_PLATFORM,
),
Expand All @@ -51,7 +52,7 @@ cp("public/ext/safari-16.4", SAFARI_EXT_RESOURCES);
[
{ userscripts: "src/ext/content-scripts/entry-userscripts.js" },
{ "dot-user-js": "src/ext/content-scripts/entry-dot-user-js.js" },
{ greasyfork: "src/ext/content-scripts/entry-greasyfork.js" },
{ "script-market": "src/ext/content-scripts/entry-script-market.js" },
].forEach((input) => {
build({
...defineConfig,
Expand Down
25 changes: 15 additions & 10 deletions scripts/dev-ext-safari.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const defineConfig = {
define: {
"import.meta.env.BROWSER": JSON.stringify("Safari"),
"import.meta.env.NATIVE_APP": JSON.stringify("app"),
"import.meta.env.SAFARI_VERSION": JSON.stringify(16.4),
"import.meta.env.SAFARI_PLATFORM": JSON.stringify(
process.env.SAFARI_PLATFORM,
),
Expand Down Expand Up @@ -70,7 +71,7 @@ async function buildResources(server, origin) {
[
{ userscripts: "src/ext/content-scripts/entry-userscripts.js" },
{ "dot-user-js": "src/ext/content-scripts/entry-dot-user-js.js" },
{ greasyfork: "src/ext/content-scripts/entry-greasyfork.js" },
{ "script-market": "src/ext/content-scripts/entry-script-market.js" },
].forEach((input) => {
/** build proxy content scripts replace actual code */
build({
Expand All @@ -82,15 +83,19 @@ async function buildResources(server, origin) {
const name = id.replace(/.+entry-/, "");
const url = `${origin}/dist/content-scripts/${name}`;
return `// proxy content
const xhr = new XMLHttpRequest();
xhr.open("GET", "${url}", false);
xhr.send();
const code = xhr.responseText;
try {
Function(code + "//# sourceURL=proxy-${name}")();
} catch (error) {
console.error(error);
}`;
(function () {
if (window["${id}"]) return;
window["${id}"] = 1;
const xhr = new XMLHttpRequest();
xhr.open("GET", "${url}", false);
xhr.send();
const code = xhr.responseText;
try {
Function(code + "//# sourceURL=proxy-${name}")();
} catch (error) {
console.error(error);
}
})();`;
},
},
],
Expand Down
58 changes: 42 additions & 16 deletions src/ext/action-popup/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@
let scriptInstalled;
let showInstallPrompt;
let showInstall;
let installUserscript; // url, content
/**
* @typedef CheckedUserscript
* @prop {import("webextension-polyfill").Tabs.Tab} tab - checked tab
* @prop {URL} url - userjs/usercss url
* @prop {"js"|"css"} type - userscript or userstyle
* @prop {string} content - userjs/usercss content
*/
/** @type {CheckedUserscript} */
let checkedUserscript;
let installViewUserscript; // metadata
let installViewUserscriptError;
let showAll;
Expand Down Expand Up @@ -336,15 +344,8 @@
abort = false;
}

// check if current page url is a userscript
if (strippedUrl.endsWith(".user.js")) {
// set checking state
scriptChecking = true;
// show checking banner
showInstallPrompt = "checking...";
// start async check
installCheck(currentTab);
}
// start async check
installCheck(currentTab);

loading = false;
disabled = false;
Expand Down Expand Up @@ -389,21 +390,43 @@
}, 25);
}

/**
* Check if the current page contains a user script
* @param {import("webextension-polyfill").Tabs.Tab} currentTab
*/
async function installCheck(currentTab) {
const tabUrl = new URL(currentTab.url);
/** @type {URL} */
let url;
// check if current page url is a userscript
if (tabUrl.pathname.endsWith(".user.js")) {
url = tabUrl;
} else {
const res = await browser.tabs.sendMessage(
currentTab.id,
"TAB_CLICK_USERJS",
);
if (!res) return;
url = new URL(res);
}
// set checking state
scriptChecking = true;
// show checking banner
showInstallPrompt = "checking...";
// refetch script from URL to avoid tampered DOM content
let res; // fetch response
try {
res = await fetch(currentTab.url);
res = await fetch(url);
if (!res.ok) throw new Error(`httpcode-${res.status}`);
} catch (error) {
console.error("Error fetching .user.js url", error);
errorNotification = "Fetching failed, refresh to retry.";
errorNotification = `Userscript fetching failed (${res.status})`;
showInstallPrompt = undefined;
return;
}
const content = await res.text();
// caching script data
installUserscript = { url: currentTab.url, content };
checkedUserscript = { tab: currentTab, url, type: "js", content };
// send native swift a message, parse metadata and check if installed
const response = await sendNativeMessage({
name: "POPUP_INSTALL_CHECK",
Expand All @@ -423,6 +446,7 @@
showInstallPrompt = response.success;
}
scriptChecking = false;
scriptInstalled || showInstallView();
}

async function showInstallView() {
Expand All @@ -441,11 +465,11 @@
// go back to main view
showInstall = false;
// double check before send install message
if (!installUserscript || !installUserscript.content) {
if (!checkedUserscript || !checkedUserscript.content) {
errorNotification = "Install failed: userscript missing";
}
const currentTab = await browser.tabs.getCurrent();
if (currentTab.url !== installUserscript.url) {
if (currentTab.id !== checkedUserscript.tab.id) {
errorNotification = "Install failed: tab changed unexpectedly";
}
if (errorNotification) {
Expand All @@ -456,7 +480,9 @@
// send native swift a message, which will start the install process
const response = await sendNativeMessage({
name: "POPUP_INSTALL_SCRIPT",
content: installUserscript.content,
url: checkedUserscript.url.href,
type: checkedUserscript.type,
content: checkedUserscript.content,
});
if (response.error) {
errorNotification = response.error;
Expand Down
23 changes: 20 additions & 3 deletions src/ext/background/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { openExtensionPage } from "../shared/utils.js";
import {
contentScriptRegistration,
openExtensionPage,
} from "../shared/utils.js";
import * as settingsStorage from "../shared/settings.js";
import { connectNative, sendNativeMessage } from "../shared/native.js";

Expand Down Expand Up @@ -285,7 +288,12 @@ async function nativeChecks() {
return true;
}

// handles messages sent with browser.runtime.sendMessage
/**
* handles messages sent with browser.runtime.sendMessage
* @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage#listener}
* @type {Parameters<typeof browser.runtime.onMessage.addListener>[0]}
* @param {(response: any) => void} sendResponse send a response to the message
*/
async function handleMessage(request, sender, sendResponse) {
switch (request.name) {
case "REQ_USERSCRIPTS": {
Expand Down Expand Up @@ -469,10 +477,19 @@ async function handleMessage(request, sender, sendResponse) {
getContextMenuItems();
break;
}
case "WEB_USERJS_POPUP": {
const currentTab = await browser.tabs.getCurrent();
if (currentTab.id === sender.tab.id) {
browser.browserAction.openPopup();
}
break;
}
}
}
browser.runtime.onInstalled.addListener(async () => {
nativeChecks();
await nativeChecks();
const enable = await settingsStorage.get("augmented_userjs_install");
await contentScriptRegistration(enable);
});
browser.runtime.onStartup.addListener(async () => {
setSessionRules();
Expand Down
12 changes: 12 additions & 0 deletions src/ext/content-scripts/entry-dot-user-js.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
async function initialize() {
// avoid duplicate injection of content scripts
if (window["CS_ENTRY_DOT_USER_JS"]) return;
window["CS_ENTRY_DOT_USER_JS"] = 1;
// check user settings
const key = "US_AUGMENTED_USERJS_INSTALL";
if ((await browser.storage.local.get(key))[key] === false) return;
// actual execution content
browser.runtime.sendMessage({ name: "WEB_USERJS_POPUP" });
}

initialize();
Empty file.
Loading
Loading