mirror of
https://github.com/zen-browser/desktop.git
synced 2025-09-05 19:08:18 +00:00
Merge pull request #8384 from JosueGalRe/bugfix/mods-page-empty-on-invalid-preferences
bugfix(mods): add file download retry and try catchs to fallback on f…
This commit is contained in:
@@ -47,9 +47,10 @@ var ZenThemesCommon = {
|
||||
if (themes === null || typeof themes !== 'object') {
|
||||
throw new Error('Themes data file is null');
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// If we have a corrupted file, reset it
|
||||
await IOUtils.writeJSON(this.themesDataFile, {});
|
||||
|
||||
Services.wm
|
||||
.getMostRecentWindow('navigator:browser')
|
||||
.gZenUIManager.showToast('zen-themes-corrupted', {
|
||||
@@ -61,46 +62,54 @@ var ZenThemesCommon = {
|
||||
|
||||
async getThemePreferences(theme) {
|
||||
const themePath = PathUtils.join(this.themesRootPath, theme.id, 'preferences.json');
|
||||
|
||||
if (!(await IOUtils.exists(themePath)) || !theme.preferences) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const preferences = await IOUtils.readJSON(themePath);
|
||||
try {
|
||||
const preferences = await IOUtils.readJSON(themePath);
|
||||
|
||||
// compat mode for old preferences, all of them can only be checkboxes
|
||||
if (typeof preferences === 'object' && !Array.isArray(preferences)) {
|
||||
console.warn(
|
||||
`[ZenThemes]: Warning, ${theme.name} uses legacy preferences, please migrate them to the new preferences style, as legacy preferences might be removed at a future release. More information at: https://docs.zen-browser.app/themes-store/themes-marketplace-preferences`
|
||||
);
|
||||
const newThemePreferences = [];
|
||||
// compat mode for old preferences, all of them can only be checkboxes
|
||||
if (typeof preferences === 'object' && !Array.isArray(preferences)) {
|
||||
console.warn(
|
||||
`[ZenThemes]: Warning, ${theme.name} uses legacy preferences, please migrate them to the new preferences style, as legacy preferences might be removed at a future release. More information at: https://docs.zen-browser.app/themes-store/themes-marketplace-preferences`
|
||||
);
|
||||
const newThemePreferences = [];
|
||||
|
||||
for (let [entry, label] of Object.entries(preferences)) {
|
||||
const [_, negation = '', os = '', property] =
|
||||
/(!?)(?:(macos|windows|linux):)?([A-Za-z0-9-_.]+)/g.exec(entry);
|
||||
const isNegation = negation === '!';
|
||||
for (let [entry, label] of Object.entries(preferences)) {
|
||||
const [, negation = '', os = '', property] =
|
||||
/(!?)(?:(macos|windows|linux):)?([A-Za-z0-9-_.]+)/g.exec(entry);
|
||||
const isNegation = negation === '!';
|
||||
|
||||
if (
|
||||
(isNegation && os === gZenOperatingSystemCommonUtils.currentOperatingSystem) ||
|
||||
(os !== '' && os !== gZenOperatingSystemCommonUtils.currentOperatingSystem && !isNegation)
|
||||
) {
|
||||
continue;
|
||||
if (
|
||||
(isNegation && os === gZenOperatingSystemCommonUtils.currentOperatingSystem) ||
|
||||
(os !== '' &&
|
||||
os !== gZenOperatingSystemCommonUtils.currentOperatingSystem &&
|
||||
!isNegation)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
newThemePreferences.push({
|
||||
property,
|
||||
label,
|
||||
type: 'checkbox',
|
||||
disabledOn: os !== '' ? [os] : [],
|
||||
});
|
||||
}
|
||||
|
||||
newThemePreferences.push({
|
||||
property,
|
||||
label,
|
||||
type: 'checkbox',
|
||||
disabledOn: os !== '' ? [os] : [],
|
||||
});
|
||||
return newThemePreferences;
|
||||
}
|
||||
|
||||
return newThemePreferences;
|
||||
return preferences.filter(
|
||||
({ disabledOn = [] }) =>
|
||||
!disabledOn.includes(gZenOperatingSystemCommonUtils.currentOperatingSystem)
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(`[ZenThemes]: Error reading preferences for ${theme.name}:`, e);
|
||||
return [];
|
||||
}
|
||||
|
||||
return preferences.filter(
|
||||
({ disabledOn = [] }) =>
|
||||
!disabledOn.includes(gZenOperatingSystemCommonUtils.currentOperatingSystem)
|
||||
);
|
||||
},
|
||||
|
||||
throttle(mainFunction, delay) {
|
||||
|
@@ -211,35 +211,30 @@ var gZenThemesImporter = new (class {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'checkbox': {
|
||||
const value = Services.prefs.getBoolPref(property, false);
|
||||
if (typeof defaultValue !== 'boolean') {
|
||||
console.log(
|
||||
`[ZenThemesImporter]: Warning, invalid data type received for expected type boolean, skipping.`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
Services.prefs.setBoolPref(property, defaultValue);
|
||||
}
|
||||
break;
|
||||
if (type === 'checkbox') {
|
||||
const value = Services.prefs.getBoolPref(property, false);
|
||||
if (typeof defaultValue !== 'boolean') {
|
||||
console.log(
|
||||
`[ZenThemesImporter]: Warning, invalid data type received for expected type boolean, skipping.`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
default: {
|
||||
const value = Services.prefs.getStringPref(property, 'zen-property-no-saved');
|
||||
if (!value) {
|
||||
Services.prefs.setBoolPref(property, defaultValue);
|
||||
}
|
||||
} else {
|
||||
const value = Services.prefs.getStringPref(property, 'zen-property-no-saved');
|
||||
|
||||
if (typeof defaultValue !== 'string' && typeof defaultValue !== 'number') {
|
||||
console.log(
|
||||
`[ZenThemesImporter]: Warning, invalid data type received (${typeof defaultValue}), skipping.`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (typeof defaultValue !== 'string' && typeof defaultValue !== 'number') {
|
||||
console.log(
|
||||
`[ZenThemesImporter]: Warning, invalid data type received (${typeof defaultValue}), skipping.`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value === 'zen-property-no-saved') {
|
||||
Services.prefs.setStringPref(property, defaultValue.toString());
|
||||
}
|
||||
if (value === 'zen-property-no-saved') {
|
||||
Services.prefs.setStringPref(property, defaultValue.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -162,9 +162,12 @@ export class ZenThemeMarketplaceChild extends JSWindowActorChild {
|
||||
const obj = await data.json();
|
||||
return obj;
|
||||
} catch (e) {
|
||||
console.error('ZTM: Error parsing theme info: ', e);
|
||||
console.error('ZenThemeMarketplace: Error parsing theme info: ', e);
|
||||
}
|
||||
} else console.log(data.status);
|
||||
} else {
|
||||
console.error('ZenThemeMarketplace: Error fetching theme info: ', data.status);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -185,11 +188,11 @@ export class ZenThemeMarketplaceChild extends JSWindowActorChild {
|
||||
} else {
|
||||
themeId = object.themeId;
|
||||
}
|
||||
console.info('ZTM: Installing theme with id: ', themeId);
|
||||
console.info('ZenThemeMarketplace: Installing theme with id: ', themeId);
|
||||
|
||||
const theme = await this.getThemeInfo(themeId);
|
||||
if (!theme) {
|
||||
console.error('ZTM: Error fetching theme info');
|
||||
console.error('ZenThemeMarketplace: Error fetching theme info');
|
||||
return;
|
||||
}
|
||||
this.addTheme(theme);
|
||||
|
@@ -28,7 +28,8 @@ export class ZenThemeMarketplaceParent extends JSWindowActorParent {
|
||||
case 'ZenThemeMarketplace:IsThemeInstalled': {
|
||||
const themeId = message.data.themeId;
|
||||
const themes = await this.getThemes();
|
||||
return themes[themeId] ? true : false;
|
||||
|
||||
return Boolean(themes?.[themeId]);
|
||||
}
|
||||
case 'ZenThemeMarketplace:CheckForUpdates': {
|
||||
this.checkForThemeUpdates();
|
||||
@@ -46,14 +47,17 @@ export class ZenThemeMarketplaceParent extends JSWindowActorParent {
|
||||
}
|
||||
|
||||
compareVersions(version1, version2) {
|
||||
var result = false;
|
||||
let result = false;
|
||||
|
||||
if (typeof version1 !== 'object') {
|
||||
version1 = version1.toString().split('.');
|
||||
}
|
||||
|
||||
if (typeof version2 !== 'object') {
|
||||
version2 = version2.toString().split('.');
|
||||
}
|
||||
for (var i = 0; i < Math.max(version1.length, version2.length); i++) {
|
||||
|
||||
for (let i = 0; i < Math.max(version1.length, version2.length); i++) {
|
||||
if (version1[i] == undefined) {
|
||||
version1[i] = 0;
|
||||
}
|
||||
@@ -76,7 +80,7 @@ export class ZenThemeMarketplaceParent extends JSWindowActorParent {
|
||||
|
||||
let updates = [];
|
||||
const themes = await this.getThemes();
|
||||
for (const theme of Object.values(await this.getThemes())) {
|
||||
for (const theme of Object.values(themes)) {
|
||||
try {
|
||||
const themeInfo = await this.sendQuery('ZenThemeMarketplace:GetThemeInfo', {
|
||||
themeId: theme.id,
|
||||
@@ -141,29 +145,58 @@ export class ZenThemeMarketplaceParent extends JSWindowActorParent {
|
||||
return stylesheet;
|
||||
}
|
||||
|
||||
async downloadUrlToFile(url, path, isStyleSheet = false) {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
const data = await response.text();
|
||||
const content = isStyleSheet ? this.getStyleSheetFullContent(data) : data;
|
||||
// convert the data into a Uint8Array
|
||||
let buffer = new TextEncoder().encode(content);
|
||||
await IOUtils.write(path, buffer);
|
||||
} catch (e) {
|
||||
console.error('ZenThemeMarketplaceParent: Error downloading file', url, e);
|
||||
async downloadUrlToFile(url, path, isStyleSheet = false, maxRetries = 3, retryDelayMs = 500) {
|
||||
let attempt = 0;
|
||||
|
||||
while (attempt < maxRetries) {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`ZenThemeMarketplaceParent: HTTP error! status: ${response.status} for url: ${url}`
|
||||
);
|
||||
}
|
||||
|
||||
const data = await response.text();
|
||||
const content = isStyleSheet ? this.getStyleSheetFullContent(data) : data;
|
||||
// convert the data into a Uint8Array
|
||||
const buffer = new TextEncoder().encode(content);
|
||||
await IOUtils.write(path, buffer);
|
||||
|
||||
return;
|
||||
} catch (e) {
|
||||
attempt++;
|
||||
if (attempt >= maxRetries) {
|
||||
console.error('ZenThemeMarketplaceParent: Error downloading file after retries', url, e);
|
||||
} else {
|
||||
console.warn(
|
||||
`ZenThemeMarketplaceParent: Download failed (attempt ${attempt} of ${maxRetries}), retrying in ${retryDelayMs}ms...`,
|
||||
url,
|
||||
e
|
||||
);
|
||||
await new Promise((res) => setTimeout(res, retryDelayMs));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async downloadThemeFileContents(theme) {
|
||||
const themePath = PathUtils.join(this.themesRootPath, theme.id);
|
||||
await IOUtils.makeDirectory(themePath, { ignoreExisting: true });
|
||||
await this.downloadUrlToFile(theme.style, PathUtils.join(themePath, 'chrome.css'), true);
|
||||
await this.downloadUrlToFile(theme.readme, PathUtils.join(themePath, 'readme.md'));
|
||||
if (theme.preferences) {
|
||||
await this.downloadUrlToFile(
|
||||
theme.preferences,
|
||||
PathUtils.join(themePath, 'preferences.json')
|
||||
);
|
||||
try {
|
||||
const themePath = PathUtils.join(this.themesRootPath, theme.id);
|
||||
await IOUtils.makeDirectory(themePath, { ignoreExisting: true });
|
||||
|
||||
await this.downloadUrlToFile(theme.style, PathUtils.join(themePath, 'chrome.css'), true);
|
||||
await this.downloadUrlToFile(theme.readme, PathUtils.join(themePath, 'readme.md'));
|
||||
|
||||
if (theme.preferences) {
|
||||
await this.downloadUrlToFile(
|
||||
theme.preferences,
|
||||
PathUtils.join(themePath, 'preferences.json')
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('ZenThemeMarketplaceParent: Error downloading theme file contents', theme.id, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user