First of all, please note that I am not fluent in English, so I am using machine translation.
- Summary
I have created a Safari extension with Manifest v3. However, when I perform the following specific actions, I get the error "The service worker script failed to load due to an error".
- Restart Safari and click the "Save Options" button on the Settings screen.
- After restarting Safari and opening the settings screen, click the button on the toolbar.
Since all of the specific behaviors are related to chrome.storage.local.set, we believe that this is the cause of the error, but we are having trouble guessing what the error is from the error message. Furthermore, the fact that this error occurs only with Safari extensions and not with Chrome extensions is another reason why I cannot understand the error. Any advice on how to make this process work properly would be appreciated.
- Expected Result
No service_worker error should occur and the save process should be normal.
- Actual behavior
After the settings screen blinks, the corresponding error should appear when the Extensions tab of the Safari settings (formerly Preferences) screen is opened.
- Environment
Macbook Pro 13-inch (2020,M1) macOS 13.3.1(a) Mac Studio (2022,M1Max) macOS 13.3.1(a)
Here is the code
manifest.json
{
"manifest_version": 3,
"default_locale": "en",
"name": "__MSG_extension_name__",
"description": "__MSG_extension_description__",
"version": "1.0",
"icons": {
"48": "images/icon-48.png",
"96": "images/icon-96.png",
"128": "images/icon-128.png",
"256": "images/icon-256.png",
"512": "images/icon-512.png"
},
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"js": [ "content.js" ],
"matches": [ "<all_urls>" ]
}],
"action": {
"default_title": "Safari Only Error",
"default_icon": {
"16": "images/enabled_toolbar-icon/toolbar-icon-16a.png",
"19": "images/enabled_toolbar-icon/toolbar-icon-19a.png",
"32": "images/enabled_toolbar-icon/toolbar-icon-32a.png",
"38": "images/enabled_toolbar-icon/toolbar-icon-38a.png",
"48": "images/enabled_toolbar-icon/toolbar-icon-48a.png",
"72": "images/enabled_toolbar-icon/toolbar-icon-72a.png"
}
},
"options_ui" : {
"page": "options.html",
"open_in_tab": true
},
"permissions": ["storage"]
}
background.js
// List of exceptions (exceptions or blacklist). This must be a complete domain or subdomain.
var g_exceptions = [];
var g_isEnabled = true;
var g_isWhitelist = true;
var c_enabledIcons = {
16: "images/enabled_toolbar-icon/toolbar-icon-16a.png",
19: "images/enabled_toolbar-icon/toolbar-icon-19a.png",
32: "images/enabled_toolbar-icon/toolbar-icon-32a.png",
38: "images/enabled_toolbar-icon/toolbar-icon-38a.png",
48: "images/enabled_toolbar-icon/toolbar-icon-48a.png",
72: "images/enabled_toolbar-icon/toolbar-icon-72a.png"
};
var c_disabledIcons = {
16: "images/disabled_toolbar-icon/toolbar-icon-16d.png",
19: "images/disabled_toolbar-icon/toolbar-icon-19d.png",
32: "images/disabled_toolbar-icon/toolbar-icon-32d.png",
38: "images/disabled_toolbar-icon/toolbar-icon-38d.png",
48: "images/disabled_toolbar-icon/toolbar-icon-48d.png",
72: "images/disabled_toolbar-icon/toolbar-icon-72d.png"
};
function updateOptions() {
console.log("Updating options");
g_exceptions = [];
var domains = [];
chrome.storage.local.get(null, function(items) {
domains = items.exceptions;
for (d in domains) {
var domain = domains[d].trim();
if (domain != "") { // Ignore empty lines
g_exceptions.push(RegExp("(.|^)" + domain + "$"));
}
}
g_isWhitelist = (items.exceptionType == "whitelist");
g_isEnabled = items.enabled;
if (g_isEnabled) {
chrome.action.setIcon({path: c_enabledIcons});
} else {
chrome.action.setIcon({path: c_disabledIcons});
}
});
}
function setEnabled(enabled) {
/* Reflect the value of the enabled key of the Storage API */
chrome.storage.local.set({'enabled': enabled}, function () {
updateOptions();
});
}
chrome.runtime.onInstalled.addListener((details) => {
var init_exceptions = ["mail.google.com", "gmail.com"];
var init_exceptionType = "whitelist";
var init_enabled = true;
console.log("init");
// Processing during update and installation
if (details.reason === "install") {
/* Reflect the value of the enabled key of the Storage API */
chrome.storage.local.set({
exceptions: init_exceptions,
exceptionType: init_exceptionType,
enabled: init_enabled
});
console.log("install");
return;
}
});
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.method === "updateOptions") {
console.log(request);
/* Reflect settings in Storage API data */
updateOptions();
sendResponse({});
} else {
sendResponse({});
}
return true;
}
);
/* Changed browserAction to action to support Manifest v3 */
chrome.action.onClicked.addListener(function(tab) {
setEnabled(!g_isEnabled);
});
updateOptions();
options.js
/* Save options to Storage API in background.js */
function save_options() {
var exceptions = document.getElementById("exceptions").value.split("\n");
var exceptionType = document.getElementById("exceptionType").value;
var enabled = document.getElementById("enabled").checked;
//Process to send options to background.js
chrome.storage.local.set({
exceptions: exceptions,
exceptionType: exceptionType,
enabled: enabled
});
chrome.runtime.sendMessage({ method: "updateOptions" });
// Update status to let user know options were saved.
$("#status").fadeIn();
setTimeout(function () {
$("#status").fadeOut();
}, 2000);
}
/* Restore Storage API values */
function restore_options() {
/* Get settings from background.js */
chrome.storage.local.get(null, function (items) {
console.log(items);
var exceptions = items.exceptions.join("\n");
var exceptionType = items.exceptionType;
var enabled = items.enabled;
console.log("exceptionType: " + items.exceptionType);
if (exceptions != null) {
document.getElementById("exceptions").value = exceptions;
}
if (exceptionType != null) {
$('#exceptionType option[value="' + exceptionType + '"]').prop('selected', true);
}
if (enabled != null) {
document.getElementById("enabled").checked = enabled;
}
});
}
//Code for localization support
function localizeHtmlPage() {
//Localize by replacing __MSG_***__ meta tags
var objects = document.getElementsByTagName('html');
for (var j = 0; j < objects.length; j++) {
var obj = objects[j];
var valStrH = obj.innerHTML.toString();
var valNewH = valStrH.replace(/__MSG_(\w+)__/g, function (match, v1) {
return v1 ? chrome.i18n.getMessage(v1) : "";
});
if (valNewH != valStrH) {
obj.innerHTML = valNewH;
}
}
}
localizeHtmlPage()
document.addEventListener('DOMContentLoaded', restore_options);
document.querySelector('#save').addEventListener('click', save_options);
- Confirmation of operation with Manifest v2 This code is for verifying the migration to Manifest v3, so we have confirmed that it works with Manifest v2.
- Confirmation of operation with Chrome Extension Since the error display in Safari was unclear, we tried to check what kind of error is displayed in Chrome. However, we could not confirm the occurrence of the error and gave up. If you import Resources folder, you can check it as a Chrome extension.