diff --git a/src/ThemeDialogUtils.cs b/src/ThemeDialogUtils.cs index 074aa58..ae54022 100644 --- a/src/ThemeDialogUtils.cs +++ b/src/ThemeDialogUtils.cs @@ -1,4 +1,4 @@ -// This Source Code Form is subject to the terms of the Mozilla Public +// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -54,20 +54,40 @@ internal static string[] GetDisplayNames() internal static void LoadThemes(List themes, ListView listView, ThemeLoadOpts opts) { - loadSemaphore.Wait(60000); - Size thumbnailSize = ThemeThumbLoader.GetThumbnailSize(listView); - ListViewItem focusedItem = null; + if (!loadSemaphore.Wait(60000)) + { + LoggingHandler.LogMessage("Timed out waiting for theme load semaphore"); + return; + } - foreach (ThemeConfig theme in themes.ToList()) + try { - if (JsonConfig.settings.showInstalledOnly && !ThemeManager.IsThemeDownloaded(theme)) - { - continue; - } + Size thumbnailSize = ThemeThumbLoader.GetThumbnailSize(listView); + ListViewItem focusedItem = null; - try + foreach (ThemeConfig theme in themes.ToList()) { - using (Image thumbnailImage = ThemeThumbLoader.GetThumbnailImage(theme, thumbnailSize, true)) + if (JsonConfig.settings.showInstalledOnly && !ThemeManager.IsThemeDownloaded(theme)) + { + continue; + } + + Image thumbnailImage; + try + { + thumbnailImage = ThemeThumbLoader.GetThumbnailImage(theme, thumbnailSize, true); + } + catch (Exception exc) + { + // Unsupported or corrupt images can throw more than OutOfMemoryException. + LoggingHandler.LogMessage("Failed to generate thumbnail for '{0}' theme: {1}", theme.themeId, + exc); + listView.Invoke(new Action(() => + ThemeLoader.HandleError(new FailedToCreateThumbnail(theme.themeId)))); + continue; + } + + using (thumbnailImage) { listView.Invoke(new Action(() => { @@ -93,27 +113,26 @@ internal static void LoadThemes(List themes, ListView listView, The })); } } - catch (OutOfMemoryException) - { - ThemeLoader.HandleError(new FailedToCreateThumbnail(theme.themeId)); - } - } - - listView.Invoke(new Action(() => - { - listView.Sort(); - if (focusedItem == null) + listView.Invoke(new Action(() => { - focusedItem = listView.Items[0]; - } + listView.Sort(); + + if (focusedItem == null) + { + focusedItem = listView.Items[0]; + } - focusedItem.Selected = true; - listView.EnsureVisible(focusedItem.Index); + focusedItem.Selected = true; + listView.EnsureVisible(focusedItem.Index); - ThemeThumbLoader.CacheThumbnails(listView); - })); - loadSemaphore.Release(); + ThemeThumbLoader.CacheThumbnails(listView); + })); + } + finally + { + loadSemaphore.Release(); + } } internal static void LoadImportedThemes(List themes, ListView listView, ImportDialog importDialog) @@ -135,13 +154,23 @@ internal static void LoadImportedThemes(List themes, ListView listV Task.Run(() => { - LoadThemes(themes, listView, new ThemeLoadOpts()); - - importDialog.Invoke(new Action(() => + try { - importDialog.thumbnailsLoaded = true; - importDialog.Close(); - })); + LoadThemes(themes, listView, new ThemeLoadOpts()); + } + catch (Exception exc) + { + LoggingHandler.LogMessage("Failed to load imported themes: {0}", exc); + } + finally + { + // Close the import dialog even if thumbnail loading fails. + importDialog.Invoke(new Action(() => + { + importDialog.thumbnailsLoaded = true; + importDialog.Close(); + })); + } }); }