Skip to content

Commit 1660c5b

Browse files
authored
Merge pull request #671 from OneNoteDev/user/sandeepgupta/firefox-mv3-compat
feat(firefox): add MV3 compatibility
2 parents f488525 + e33a940 commit 1660c5b

4 files changed

Lines changed: 147 additions & 5 deletions

File tree

‎gulpfile.js‎

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ var PATHS = {
2626
TARGET: {
2727
ROOT: "target/",
2828
CHROME: "target/chrome/",
29+
FIREFOX: "target/firefox/",
2930
EDGE_ROOT: "target/edge/OneNoteWebClipper/edgeextension/",
3031
EDGE_EXTENSION: "target/edge/OneNoteWebClipper/edgeextension/manifest/extension/"
3132
},
@@ -207,6 +208,10 @@ gulp.task("bundleChrome", function () {
207208
return bundleEntry(PATHS.BUILDROOT + "scripts/extensions/chrome/", "chromeExtension.js");
208209
});
209210

211+
gulp.task("bundleFirefox", function () {
212+
return bundleEntry(PATHS.BUILDROOT + "scripts/extensions/firefox/", "firefoxExtension.js");
213+
});
214+
210215
gulp.task("bundleEdge", function () {
211216
return bundleEntry(PATHS.BUILDROOT + "scripts/extensions/edge/", "edgeExtension.js");
212217
});
@@ -219,6 +224,7 @@ gulp.task("bundle", gulp.series(
219224
"bundleRenderer",
220225
"bundleLogManager",
221226
"bundleChrome",
227+
"bundleFirefox",
222228
"bundleEdge"
223229
));
224230

@@ -235,6 +241,7 @@ function lowerCasePathName() {
235241

236242
var targetDirHasExportedCommonJs = {};
237243
targetDirHasExportedCommonJs[PATHS.TARGET.CHROME] = false;
244+
targetDirHasExportedCommonJs[PATHS.TARGET.FIREFOX] = false;
238245
targetDirHasExportedCommonJs[PATHS.TARGET.EDGE_EXTENSION] = false;
239246
function exportCommonJS(targetDir) {
240247
if (targetDirHasExportedCommonJs[targetDir]) {
@@ -342,6 +349,31 @@ function exportChromeLibFiles() {
342349
return exportCommonLibFiles(PATHS.TARGET.CHROME);
343350
}
344351

352+
function exportFirefoxJS() {
353+
var targetDir = PATHS.TARGET.FIREFOX;
354+
var bundles = ["appendIsInstalledMarker.js", "regionOverlay.js", "contentCaptureInject.js", "renderer.js"];
355+
var bundleStreams = bundles.map(function(name) {
356+
return gulp.src([PATHS.BUNDLEROOT + name]).pipe(concat(name)).pipe(gulp.dest(targetDir));
357+
});
358+
var backgroundTask = gulp.src([
359+
targetDir + "logManager.js",
360+
PATHS.BUNDLEROOT + "firefoxExtension.js"
361+
]).pipe(concat("firefoxExtension.js")).pipe(gulp.dest(targetDir));
362+
363+
return exportCommonJS(targetDir).then(function() {
364+
return streamsToPromise.apply(null, bundleStreams.concat([backgroundTask]));
365+
});
366+
}
367+
368+
function exportFirefoxSrcFiles() {
369+
var targetDir = PATHS.TARGET.FIREFOX;
370+
return Promise.all([
371+
exportCommonSrcFiles(targetDir),
372+
exportCommonWebExtensionFiles(targetDir),
373+
streamToPromise(gulp.src([PATHS.SRC.ROOT + "scripts/extensions/firefox/manifest.json"]).pipe(gulp.dest(targetDir)))
374+
]);
375+
}
376+
345377
function exportEdgeJS() {
346378
var targetDir = PATHS.TARGET.EDGE_EXTENSION;
347379

@@ -443,18 +475,24 @@ gulp.task("exportChromeSrcFiles", function() { return exportChromeSrcFiles(); })
443475
gulp.task("exportChromeLibFiles", function() { return exportChromeLibFiles(); });
444476
gulp.task("exportChrome", gulp.series("exportChromeJS", "exportChromeCSS", "exportChromeSrcFiles", "exportChromeLibFiles"));
445477

478+
gulp.task("exportFirefoxJS", function() { return exportFirefoxJS(); });
479+
gulp.task("exportFirefoxCSS", function() { return exportCommonCSS(PATHS.TARGET.FIREFOX); });
480+
gulp.task("exportFirefoxSrcFiles", function() { return exportFirefoxSrcFiles(); });
481+
gulp.task("exportFirefoxLibFiles", function() { return exportCommonLibFiles(PATHS.TARGET.FIREFOX); });
482+
gulp.task("exportFirefox", gulp.series("exportFirefoxJS", "exportFirefoxCSS", "exportFirefoxSrcFiles", "exportFirefoxLibFiles"));
483+
446484
gulp.task("exportEdgeJS", function() { return exportEdgeJS(); });
447485
gulp.task("exportEdgeCSS", function() { return exportEdgeCSS(); });
448486
gulp.task("exportEdgeSrcFiles", function() { return exportEdgeSrcFiles(); });
449487
gulp.task("exportEdgePackageFiles", function() { return exportEdgePackageFiles(); });
450488
gulp.task("exportEdgeLibFiles", function() { return exportEdgeLibFiles(); });
451489
gulp.task("exportEdge", gulp.series("exportEdgeJS", "exportEdgeCSS", "exportEdgeSrcFiles", "exportEdgePackageFiles", "exportEdgeLibFiles"));
452490

453-
gulp.task("exportJS", gulp.series("exportChromeJS", "exportEdgeJS"));
454-
gulp.task("exportCSS", gulp.series("exportChromeCSS", "exportEdgeCSS"));
455-
gulp.task("exportSrcFiles", gulp.series("exportChromeSrcFiles", "exportEdgeSrcFiles"));
491+
gulp.task("exportJS", gulp.series("exportChromeJS", "exportFirefoxJS", "exportEdgeJS"));
492+
gulp.task("exportCSS", gulp.series("exportChromeCSS", "exportFirefoxCSS", "exportEdgeCSS"));
493+
gulp.task("exportSrcFiles", gulp.series("exportChromeSrcFiles", "exportFirefoxSrcFiles", "exportEdgeSrcFiles"));
456494

457-
gulp.task("export", gulp.series("exportAllCommonJS", "exportChrome", "exportEdge"));
495+
gulp.task("export", gulp.series("exportAllCommonJS", "exportChrome", "exportFirefox", "exportEdge"));
458496

459497
////////////////////////////////////////
460498
// PACKAGING TASKS
@@ -465,7 +503,13 @@ gulp.task("packageChrome", function() {
465503
.pipe(gulp.dest(PATHS.TARGET.CHROME));
466504
});
467505

468-
gulp.task("package", gulp.series("packageChrome"));
506+
gulp.task("packageFirefox", function() {
507+
return gulp.src([PATHS.TARGET.FIREFOX + "/**/*", "!" + PATHS.TARGET.FIREFOX + "/OneNoteWebClipper.xpi"], { encoding: false })
508+
.pipe(zip("OneNoteWebClipper.xpi"))
509+
.pipe(gulp.dest(PATHS.TARGET.FIREFOX));
510+
});
511+
512+
gulp.task("package", gulp.series("packageChrome", "packageFirefox"));
469513

470514
////////////////////////////////////////
471515
// PRODUCTION-ONLY TASKS
@@ -513,6 +557,7 @@ gulp.task("watchSrcFiles", function() {
513557
PATHS.SRC.ROOT + "images/*",
514558
PATHS.SRC.ROOT + "renderer.html",
515559
PATHS.SRC.ROOT + "scripts/extensions/chrome/manifest.json",
560+
PATHS.SRC.ROOT + "scripts/extensions/firefox/manifest.json",
516561
PATHS.SRC.ROOT + "scripts/extensions/offscreen.html",
517562
PATHS.SRC.ROOT + "scripts/extensions/edge/edgeExtension.html",
518563
PATHS.SRC.ROOT + "scripts/extensions/edge/manifest.json"

‎src/scripts/communicator/offscreenCommunicator.ts‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ export async function sendToOffscreenDocument(type: string, data: any): Promise<
3535
let chromeRuntime = chrome.runtime as any;
3636
let chromeOffscreen = (chrome as any).offscreen;
3737

38+
if (typeof chromeRuntime.getContexts !== "function" || !chromeOffscreen) {
39+
return handleWithoutOffscreenDocument(type, data);
40+
}
41+
3842
const existingContexts = await chromeRuntime.getContexts({
3943
contextTypes: [chromeRuntime.ContextType.OFFSCREEN_DOCUMENT],
4044
documentUrls: [offscreenUrl]
@@ -64,3 +68,26 @@ export async function sendToOffscreenDocument(type: string, data: any): Promise<
6468
});
6569
});
6670
}
71+
72+
function handleWithoutOffscreenDocument(type: string, data: any): string {
73+
switch (type) {
74+
case OffscreenMessageTypes.getFromLocalStorage:
75+
return localStorage.getItem(data.key);
76+
case OffscreenMessageTypes.setToLocalStorage:
77+
localStorage.setItem(data.key, data.value);
78+
return "SUCCESS";
79+
case OffscreenMessageTypes.removeFromLocalStorage:
80+
localStorage.removeItem(data.key);
81+
return "SUCCESS";
82+
case OffscreenMessageTypes.getHostname: {
83+
let url = new URL(data.url, offscreenUrl);
84+
return url.protocol + "//" + url.host + "/";
85+
}
86+
case OffscreenMessageTypes.getPathname:
87+
return new URL(data.url, offscreenUrl).pathname;
88+
default:
89+
// eslint-disable-next-line no-console -- match the offscreen handler's failure mode
90+
console.warn(`Unexpected message type received: '${type}'.`);
91+
return;
92+
}
93+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import {ClientType} from "../../clientType";
2+
import {WebExtension} from "../webExtensionBase/webExtension";
3+
4+
// Firefox exposes the callback-based chrome namespace used by the shared implementation.
5+
WebExtension.browser = chrome;
6+
let clipperBackground = new WebExtension(ClientType.FirefoxExtension);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"manifest_version": 3,
3+
"name": "OneNote Web Clipper",
4+
"description": "__MSG_appDesc__",
5+
"default_locale": "en",
6+
"version": "3.11.2",
7+
"browser_specific_settings": {
8+
"gecko": {
9+
"id": "Clipper@OneNote.com"
10+
}
11+
},
12+
"background": {
13+
"scripts": [
14+
"firefoxExtension.js"
15+
]
16+
},
17+
"content_scripts": [
18+
{
19+
"matches": [
20+
"https://onenote.officeapps.live.com/*",
21+
"https://ppc-onenote.officeapps.live.com/*",
22+
"https://onenote.officeapps-df.live.com/*",
23+
"https://onenote.officeapps.live-int.com/*"
24+
],
25+
"js": [
26+
"appendIsInstalledMarker.js"
27+
],
28+
"run_at": "document_start",
29+
"all_frames": true
30+
}
31+
],
32+
"permissions": [
33+
"activeTab",
34+
"scripting",
35+
"contextMenus",
36+
"tabs",
37+
"webRequest",
38+
"webNavigation"
39+
],
40+
"host_permissions": [
41+
"<all_urls>"
42+
],
43+
"content_security_policy": {
44+
"extension_pages": "script-src 'self'; object-src 'self'"
45+
},
46+
"icons": {
47+
"16": "icons/icon-16.png",
48+
"19": "icons/icon-19.png",
49+
"32": "icons/icon-32.png",
50+
"38": "icons/icon-38.png",
51+
"48": "icons/icon-48.png",
52+
"64": "icons/icon-64.png",
53+
"96": "icons/icon-96.png",
54+
"128": "icons/icon-128.png",
55+
"256": "icons/icon-256.png"
56+
},
57+
"action": {
58+
"default_title": "OneNote Web Clipper",
59+
"default_icon": {
60+
"19": "icons/icon-19.png",
61+
"38": "icons/icon-38.png"
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)