Skip to content

Commit 88162e0

Browse files
committed
Rewrite for Manifest v3
1 parent cc639b4 commit 88162e0

5 files changed

Lines changed: 162 additions & 268 deletions

File tree

background.html

Lines changed: 0 additions & 3 deletions
This file was deleted.

bg.js

Lines changed: 79 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,151 +1,79 @@
1-
if (!self.browser && self.chrome) {
2-
browser = chrome;
3-
}
4-
5-
browser.contextMenus.create({
6-
id: "search-on-trace.moe",
7-
title: "Search on trace.moe",
8-
contexts: ["image", "video"],
9-
});
10-
11-
var imageDataURL;
12-
13-
var handleMessage = function (request, sender, sendResponse) {
14-
if (request.type === "getImageDataURL" && imageDataURL) {
15-
sendResponse({
16-
imageDataURL: imageDataURL,
17-
});
18-
imageDataURL = null;
19-
}
20-
return true;
21-
};
22-
23-
browser.runtime.onMessage.addListener(handleMessage);
24-
25-
var search = function (dataURL) {
26-
imageDataURL = dataURL;
27-
browser.tabs.create({
28-
url: "https://trace.moe",
29-
});
30-
};
31-
32-
var toDataURL = function (source) {
33-
try {
34-
var canvas = document.createElement("canvas");
35-
canvas.crossOrigin = "anonymous";
36-
canvas.height = 720;
37-
if (source.nodeName === "VIDEO") {
38-
canvas.width = (source.videoWidth / source.videoHeight) * canvas.height;
39-
} else {
40-
canvas.width = (source.width / source.height) * canvas.height;
41-
}
42-
canvas.getContext("2d").drawImage(source, 0, 0, canvas.width, canvas.height);
43-
return canvas.toDataURL("image/jpeg", 0.9);
44-
} catch (err) {
45-
return null;
46-
}
47-
};
48-
49-
var getDataURL = function (target) {
50-
return new Promise(function (resolve, reject) {
51-
browser.tabs.query(
52-
{
53-
active: true,
54-
},
55-
function (tabs) {
56-
browser.tabs.sendMessage(
57-
tabs[0].id,
58-
{
59-
action: "getDataURL",
60-
target: target,
61-
},
62-
function (response) {
63-
if (response && response.dataURL) {
64-
resolve(response.dataURL);
65-
} else {
66-
reject(Error("CORS Error"));
67-
}
68-
}
69-
);
70-
}
71-
);
72-
});
73-
};
74-
75-
var fetchImage = function (src) {
76-
var img = new Image();
77-
img.crossOrigin = "anonymous";
78-
img.onload = function () {
79-
search(toDataURL(this));
80-
};
81-
img.src = src;
82-
};
83-
84-
var getCurrentTime = function (target) {
85-
return new Promise(function (resolve, reject) {
86-
browser.tabs.query(
87-
{
88-
active: true,
89-
},
90-
function (tabs) {
91-
browser.tabs.sendMessage(
92-
tabs[0].id,
93-
{
94-
action: "getCurrentTime",
95-
target: target,
96-
},
97-
function (response) {
98-
resolve(response.currentTime);
99-
}
100-
);
101-
}
102-
);
103-
});
104-
};
105-
106-
var fetchVideo = function (src, currentTime) {
107-
var player = document.createElement("video");
108-
player.crossOrigin = "anonymous";
109-
player.src = src;
110-
player.width = player.videoWidth;
111-
player.height = player.height;
112-
player.currentTime = currentTime;
113-
player.volume = 0;
114-
player.onloadeddata = function () {
115-
search(toDataURL(player));
116-
};
117-
};
118-
119-
browser.contextMenus.onClicked.addListener(function (info, tab) {
120-
if (info.srcUrl) {
121-
if (info.srcUrl.indexOf("blob:") === 0) {
122-
// must capture on context script
123-
// for video it will return capture at currentTime
124-
getDataURL(info.srcUrl).then(function (dataURL) {
125-
search(dataURL);
126-
});
127-
} else if (info.mediaType === "image" && info.srcUrl.indexOf("data:") === 0) {
128-
search(info.srcUrl);
129-
} else if (info.mediaType === "image") {
130-
getDataURL(info.srcUrl).then(
131-
function (dataURL) {
132-
search(dataURL);
133-
},
134-
function () {
135-
fetchImage(info.srcUrl);
136-
}
137-
);
138-
} else if (info.mediaType === "video") {
139-
getDataURL(info.srcUrl).then(
140-
function (dataURL) {
141-
search(dataURL);
142-
},
143-
function () {
144-
getCurrentTime(info.srcUrl).then(function (currentTime) {
145-
fetchVideo(info.srcUrl, currentTime);
146-
});
147-
}
148-
);
149-
}
150-
}
151-
});
1+
if (!self.browser && self.chrome) {
2+
browser = chrome;
3+
}
4+
5+
(async () => {
6+
await browser.contextMenus.removeAll();
7+
await browser.contextMenus.create({
8+
id: "search-on-trace.moe",
9+
title: "Search on trace.moe",
10+
contexts: ["image", "video"],
11+
});
12+
})();
13+
14+
let imageDataURL = null;
15+
let targetSrc = null;
16+
let targetCurrentTime = null;
17+
let tempTab = null;
18+
let newTab = null;
19+
20+
browser.runtime.onMessage.addListener((request, { tab }, sendResponse) => {
21+
if (newTab && tab.id === newTab.id && request.type === "getImageDataURL" && imageDataURL) {
22+
sendResponse({ imageDataURL });
23+
imageDataURL = null;
24+
newTab = null;
25+
}
26+
if (tempTab && tab.id === tempTab.id && request.type === "getTargetSrc" && targetSrc) {
27+
browser.tabs.sendMessage(
28+
tempTab.id,
29+
{
30+
action: "getSearchImage",
31+
srcUrl: targetSrc,
32+
currentTime: targetCurrentTime,
33+
},
34+
(response) => {
35+
browser.tabs.remove(tempTab.id).catch(() => {});
36+
tempTab = null;
37+
if (!response) return;
38+
if (response.searchImage) {
39+
search(response.searchImage);
40+
}
41+
}
42+
);
43+
targetSrc = null;
44+
targetCurrentTime = null;
45+
}
46+
return true;
47+
});
48+
49+
const search = async (dataURL) => {
50+
imageDataURL = dataURL;
51+
newTab = await browser.tabs.create({
52+
url: "https://trace.moe",
53+
});
54+
};
55+
56+
browser.contextMenus.onClicked.addListener(async ({ srcUrl }) => {
57+
if (!srcUrl) return;
58+
const activeTabs = await browser.tabs.query({ active: true });
59+
browser.tabs.sendMessage(
60+
activeTabs[0].id,
61+
{
62+
action: "getSearchImage",
63+
srcUrl,
64+
},
65+
async (response) => {
66+
if (!response) return;
67+
if (response.searchImage) {
68+
search(response.searchImage);
69+
return;
70+
}
71+
targetSrc = srcUrl;
72+
targetCurrentTime = response.currentTime;
73+
tempTab = await browser.tabs.create({
74+
active: response.currentTime !== null,
75+
url: srcUrl,
76+
});
77+
}
78+
);
79+
});

content.js

Lines changed: 53 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,53 @@
1-
if (!self.browser && self.chrome) {
2-
browser = chrome;
3-
}
4-
5-
var toDataURL = function (source) {
6-
try {
7-
var canvas = document.createElement("canvas");
8-
canvas.crossOrigin = "anonymous";
9-
canvas.height = 720;
10-
if (source.nodeName === "VIDEO") {
11-
canvas.width = (source.videoWidth / source.videoHeight) * canvas.height;
12-
} else {
13-
canvas.width = (source.width / source.height) * canvas.height;
14-
}
15-
canvas.getContext("2d").drawImage(source, 0, 0, canvas.width, canvas.height);
16-
return canvas.toDataURL("image/jpeg", 0.9);
17-
} catch (err) {
18-
return null;
19-
}
20-
};
21-
22-
var absolutePath = function (href) {
23-
var link = document.createElement("a");
24-
link.href = href;
25-
return link.protocol + "//" + link.host + link.pathname + link.search + link.hash;
26-
};
27-
28-
var handleMessage = (request, sender, sendResponse) => {
29-
if (request.action === "getCurrentTime") {
30-
var currentTime = 0;
31-
var videos = document.querySelectorAll("video");
32-
for (var i = 0; i < videos.length; ++i) {
33-
if (absolutePath(videos[i].src).indexOf(request.target)) {
34-
currentTime = videos[i].currentTime;
35-
break;
36-
}
37-
var sources = videos[i].querySelectorAll("source");
38-
for (var j = 0; j < sources.length; ++j) {
39-
if (absolutePath(sources[j].src).indexOf(request.target)) {
40-
currentTime = videos[i].currentTime;
41-
}
42-
break;
43-
}
44-
}
45-
sendResponse({
46-
currentTime: currentTime,
47-
});
48-
} else if (request.action === "getDataURL") {
49-
//assume only one element match the blob URL
50-
var source = null;
51-
var elem = document.querySelectorAll("img, video");
52-
53-
for (var i = 0; i < elem.length; ++i) {
54-
if (absolutePath(elem[i].src) === request.target) {
55-
source = elem[i];
56-
break;
57-
}
58-
var sources = elem[i].querySelectorAll("source");
59-
for (var j = 0; j < sources.length; ++j) {
60-
if (absolutePath(sources[j].src) === request.target) {
61-
source = elem[i];
62-
}
63-
break;
64-
}
65-
}
66-
67-
if (source) {
68-
sendResponse({
69-
dataURL: toDataURL(source),
70-
});
71-
} else {
72-
alert("Failed to get search image");
73-
}
74-
}
75-
return true;
76-
};
77-
78-
browser.runtime.onMessage.addListener(handleMessage);
1+
if (!self.browser && self.chrome) {
2+
browser = chrome;
3+
}
4+
5+
const toDataURL = (element) => {
6+
try {
7+
const canvas = document.createElement("canvas");
8+
canvas.crossOrigin = "anonymous";
9+
canvas.height = 720;
10+
if (element instanceof HTMLVideoElement) {
11+
canvas.width = (element.videoWidth / element.videoHeight) * canvas.height;
12+
} else {
13+
canvas.width = (element.width / element.height) * canvas.height;
14+
}
15+
canvas.getContext("2d").drawImage(element, 0, 0, canvas.width, canvas.height);
16+
return canvas.toDataURL("image/jpeg", 0.9);
17+
} catch (err) {
18+
return null;
19+
}
20+
};
21+
22+
browser.runtime.sendMessage({ type: "getTargetSrc" });
23+
24+
browser.runtime.onMessage.addListener(({ action, srcUrl, currentTime }, sender, sendResponse) => {
25+
if (action === "getSearchImage" && srcUrl) {
26+
//assume only one element match the src
27+
const element = Array.from(document.querySelectorAll("img, video")).find(
28+
(e) => e.currentSrc === srcUrl
29+
);
30+
if (!element) return alert("Fail to get search image");
31+
if (currentTime && element instanceof HTMLVideoElement) {
32+
element.pause();
33+
element.volume = 0;
34+
element.currentTime = currentTime;
35+
element.oncanplay = () => {
36+
const searchImage = toDataURL(element);
37+
if (searchImage) {
38+
sendResponse({ searchImage });
39+
}
40+
};
41+
} else {
42+
const searchImage = toDataURL(element);
43+
if (searchImage) {
44+
sendResponse({ searchImage });
45+
} else {
46+
sendResponse({
47+
currentTime: element instanceof HTMLVideoElement ? element.currentTime : null,
48+
});
49+
}
50+
}
51+
}
52+
return true;
53+
});

0 commit comments

Comments
 (0)