Skip to content

Commit

Permalink
Rewrite for Manifest v3
Browse files Browse the repository at this point in the history
  • Loading branch information
soruly committed May 30, 2024
1 parent cc639b4 commit 88162e0
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 268 deletions.
3 changes: 0 additions & 3 deletions background.html

This file was deleted.

230 changes: 79 additions & 151 deletions bg.js
Original file line number Diff line number Diff line change
@@ -1,151 +1,79 @@
if (!self.browser && self.chrome) {
browser = chrome;
}

browser.contextMenus.create({
id: "search-on-trace.moe",
title: "Search on trace.moe",
contexts: ["image", "video"],
});

var imageDataURL;

var handleMessage = function (request, sender, sendResponse) {
if (request.type === "getImageDataURL" && imageDataURL) {
sendResponse({
imageDataURL: imageDataURL,
});
imageDataURL = null;
}
return true;
};

browser.runtime.onMessage.addListener(handleMessage);

var search = function (dataURL) {
imageDataURL = dataURL;
browser.tabs.create({
url: "https://trace.moe",
});
};

var toDataURL = function (source) {
try {
var canvas = document.createElement("canvas");
canvas.crossOrigin = "anonymous";
canvas.height = 720;
if (source.nodeName === "VIDEO") {
canvas.width = (source.videoWidth / source.videoHeight) * canvas.height;
} else {
canvas.width = (source.width / source.height) * canvas.height;
}
canvas.getContext("2d").drawImage(source, 0, 0, canvas.width, canvas.height);
return canvas.toDataURL("image/jpeg", 0.9);
} catch (err) {
return null;
}
};

var getDataURL = function (target) {
return new Promise(function (resolve, reject) {
browser.tabs.query(
{
active: true,
},
function (tabs) {
browser.tabs.sendMessage(
tabs[0].id,
{
action: "getDataURL",
target: target,
},
function (response) {
if (response && response.dataURL) {
resolve(response.dataURL);
} else {
reject(Error("CORS Error"));
}
}
);
}
);
});
};

var fetchImage = function (src) {
var img = new Image();
img.crossOrigin = "anonymous";
img.onload = function () {
search(toDataURL(this));
};
img.src = src;
};

var getCurrentTime = function (target) {
return new Promise(function (resolve, reject) {
browser.tabs.query(
{
active: true,
},
function (tabs) {
browser.tabs.sendMessage(
tabs[0].id,
{
action: "getCurrentTime",
target: target,
},
function (response) {
resolve(response.currentTime);
}
);
}
);
});
};

var fetchVideo = function (src, currentTime) {
var player = document.createElement("video");
player.crossOrigin = "anonymous";
player.src = src;
player.width = player.videoWidth;
player.height = player.height;
player.currentTime = currentTime;
player.volume = 0;
player.onloadeddata = function () {
search(toDataURL(player));
};
};

browser.contextMenus.onClicked.addListener(function (info, tab) {
if (info.srcUrl) {
if (info.srcUrl.indexOf("blob:") === 0) {
// must capture on context script
// for video it will return capture at currentTime
getDataURL(info.srcUrl).then(function (dataURL) {
search(dataURL);
});
} else if (info.mediaType === "image" && info.srcUrl.indexOf("data:") === 0) {
search(info.srcUrl);
} else if (info.mediaType === "image") {
getDataURL(info.srcUrl).then(
function (dataURL) {
search(dataURL);
},
function () {
fetchImage(info.srcUrl);
}
);
} else if (info.mediaType === "video") {
getDataURL(info.srcUrl).then(
function (dataURL) {
search(dataURL);
},
function () {
getCurrentTime(info.srcUrl).then(function (currentTime) {
fetchVideo(info.srcUrl, currentTime);
});
}
);
}
}
});
if (!self.browser && self.chrome) {
browser = chrome;
}

(async () => {
await browser.contextMenus.removeAll();
await browser.contextMenus.create({
id: "search-on-trace.moe",
title: "Search on trace.moe",
contexts: ["image", "video"],
});
})();

let imageDataURL = null;
let targetSrc = null;
let targetCurrentTime = null;
let tempTab = null;
let newTab = null;

browser.runtime.onMessage.addListener((request, { tab }, sendResponse) => {
if (newTab && tab.id === newTab.id && request.type === "getImageDataURL" && imageDataURL) {
sendResponse({ imageDataURL });
imageDataURL = null;
newTab = null;
}
if (tempTab && tab.id === tempTab.id && request.type === "getTargetSrc" && targetSrc) {
browser.tabs.sendMessage(
tempTab.id,
{
action: "getSearchImage",
srcUrl: targetSrc,
currentTime: targetCurrentTime,
},
(response) => {
browser.tabs.remove(tempTab.id).catch(() => {});
tempTab = null;
if (!response) return;
if (response.searchImage) {
search(response.searchImage);
}
}
);
targetSrc = null;
targetCurrentTime = null;
}
return true;
});

const search = async (dataURL) => {
imageDataURL = dataURL;
newTab = await browser.tabs.create({
url: "https://trace.moe",
});
};

browser.contextMenus.onClicked.addListener(async ({ srcUrl }) => {
if (!srcUrl) return;
const activeTabs = await browser.tabs.query({ active: true });
browser.tabs.sendMessage(
activeTabs[0].id,
{
action: "getSearchImage",
srcUrl,
},
async (response) => {
if (!response) return;
if (response.searchImage) {
search(response.searchImage);
return;
}
targetSrc = srcUrl;
targetCurrentTime = response.currentTime;
tempTab = await browser.tabs.create({
active: response.currentTime !== null,
url: srcUrl,
});
}
);
});
131 changes: 53 additions & 78 deletions content.js
Original file line number Diff line number Diff line change
@@ -1,78 +1,53 @@
if (!self.browser && self.chrome) {
browser = chrome;
}

var toDataURL = function (source) {
try {
var canvas = document.createElement("canvas");
canvas.crossOrigin = "anonymous";
canvas.height = 720;
if (source.nodeName === "VIDEO") {
canvas.width = (source.videoWidth / source.videoHeight) * canvas.height;
} else {
canvas.width = (source.width / source.height) * canvas.height;
}
canvas.getContext("2d").drawImage(source, 0, 0, canvas.width, canvas.height);
return canvas.toDataURL("image/jpeg", 0.9);
} catch (err) {
return null;
}
};

var absolutePath = function (href) {
var link = document.createElement("a");
link.href = href;
return link.protocol + "//" + link.host + link.pathname + link.search + link.hash;
};

var handleMessage = (request, sender, sendResponse) => {
if (request.action === "getCurrentTime") {
var currentTime = 0;
var videos = document.querySelectorAll("video");
for (var i = 0; i < videos.length; ++i) {
if (absolutePath(videos[i].src).indexOf(request.target)) {
currentTime = videos[i].currentTime;
break;
}
var sources = videos[i].querySelectorAll("source");
for (var j = 0; j < sources.length; ++j) {
if (absolutePath(sources[j].src).indexOf(request.target)) {
currentTime = videos[i].currentTime;
}
break;
}
}
sendResponse({
currentTime: currentTime,
});
} else if (request.action === "getDataURL") {
//assume only one element match the blob URL
var source = null;
var elem = document.querySelectorAll("img, video");

for (var i = 0; i < elem.length; ++i) {
if (absolutePath(elem[i].src) === request.target) {
source = elem[i];
break;
}
var sources = elem[i].querySelectorAll("source");
for (var j = 0; j < sources.length; ++j) {
if (absolutePath(sources[j].src) === request.target) {
source = elem[i];
}
break;
}
}

if (source) {
sendResponse({
dataURL: toDataURL(source),
});
} else {
alert("Failed to get search image");
}
}
return true;
};

browser.runtime.onMessage.addListener(handleMessage);
if (!self.browser && self.chrome) {
browser = chrome;
}

const toDataURL = (element) => {
try {
const canvas = document.createElement("canvas");
canvas.crossOrigin = "anonymous";
canvas.height = 720;
if (element instanceof HTMLVideoElement) {
canvas.width = (element.videoWidth / element.videoHeight) * canvas.height;
} else {
canvas.width = (element.width / element.height) * canvas.height;
}
canvas.getContext("2d").drawImage(element, 0, 0, canvas.width, canvas.height);
return canvas.toDataURL("image/jpeg", 0.9);
} catch (err) {
return null;
}
};

browser.runtime.sendMessage({ type: "getTargetSrc" });

browser.runtime.onMessage.addListener(({ action, srcUrl, currentTime }, sender, sendResponse) => {
if (action === "getSearchImage" && srcUrl) {
//assume only one element match the src
const element = Array.from(document.querySelectorAll("img, video")).find(
(e) => e.currentSrc === srcUrl
);
if (!element) return alert("Fail to get search image");
if (currentTime && element instanceof HTMLVideoElement) {
element.pause();
element.volume = 0;
element.currentTime = currentTime;
element.oncanplay = () => {
const searchImage = toDataURL(element);
if (searchImage) {
sendResponse({ searchImage });
}
};
} else {
const searchImage = toDataURL(element);
if (searchImage) {
sendResponse({ searchImage });
} else {
sendResponse({
currentTime: element instanceof HTMLVideoElement ? element.currentTime : null,
});
}
}
}
return true;
});
Loading

0 comments on commit 88162e0

Please sign in to comment.