Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
type PermissionOverlayWindowLike,
} from '../permission-overlay/permission-overlay-controller.js';
import {
BUNDLE_ICON_OPTIONS,
loadNativeBundleIcon,
resolveAppBundle,
} from '../permission-overlay/app-bundle.js';
Expand Down Expand Up @@ -317,6 +318,12 @@ describe('app bundle resolution for the drag', () => {
assert.equal(await loadNativeBundleIcon(true, async () => 'icon'), 'icon');
});

it('never requests the large icon size that kills packaged macOS builds', () => {
// 'large' hits a fatal NOTREACHED inside Chromium's IconLoader on
// macOS (SIGTRAP, not a catchable error) — see issue #3352.
assert.notEqual(BUNDLE_ICON_OPTIONS.size as string, 'large');
});

it('walks three levels up from the executable to the .app', () => {
assert.deepEqual(
resolveAppBundle({
Expand Down
9 changes: 9 additions & 0 deletions apps/desktop/src/main/permission-overlay/app-bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ export interface ResolveAppBundleDeps {
exists(path: string): boolean;
}

/**
* The only size every platform can actually deliver. `'large'` is
* unsupported on macOS: Chromium's IconLoader hits a fatal NOTREACHED and
* the process dies with SIGTRAP before the promise settles — no JavaScript
* error is ever thrown, so the try/catch in `loadNativeBundleIcon` cannot
* save the app. Callers upscale the 32x32 result as needed.
*/
export const BUNDLE_ICON_OPTIONS = { size: 'normal' } as const;

/**
* Reading a bundle icon is presentation-only. The original unpackaged npm
* Electron runtime could terminate natively while macOS resolved its bundle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { join } from 'node:path';
import type { UiLocale } from '@maka/core/ui-locale';
import { resolveOverlayAssetDir } from '../overlay-assets.js';
import { openSystemPermissionPane, requestPermissionAccess } from '../permissions-actions.js';
import { loadNativeBundleIcon, resolveAppBundle } from './app-bundle.js';
import { BUNDLE_ICON_OPTIONS, loadNativeBundleIcon, resolveAppBundle } from './app-bundle.js';
import { getPermissionOverlayCopy } from './permission-overlay-copy.js';
import {
createPermissionOverlayController,
Expand Down Expand Up @@ -77,7 +77,7 @@ export function createPermissionOverlayMain(
async function resolveAppIconDataUrl(bundlePath: string | null): Promise<string | null> {
if (!bundlePath) return null;
const icon = await loadNativeBundleIcon(app.isPackaged, () =>
app.getFileIcon(bundlePath, { size: 'large' }),
app.getFileIcon(bundlePath, BUNDLE_ICON_OPTIONS),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Use the canonical Maka icon instead of the macOS file-type icon

Thanks for fixing the crash here. One non-blocking issue remains: on macOS, Chromium's IconLoader resolves this path through its UTType and returns the generic application-bundle icon, rather than the icon belonging to this particular Maka.app. The current device evidence proves that the PNG is valid, but not that its identity is correct.

Since #3451 already packages the canonical assets/icon.png and provides desktopAssetPath(), the clean final state is to load that asset with nativeImage.createFromPath(). That would also let us delete both getFileIcon() calls, BUNDLE_ICON_OPTIONS, the native bundle-icon loader, and the implementation-level "not large" test, while keeping resolveAppBundle() solely responsible for the file being dragged.

);
if (!icon || icon.isEmpty()) return null;
// nativeImage.createFromPath does not decode .icns reliably. Asking
Expand Down Expand Up @@ -274,7 +274,7 @@ function attachCardGestures(win: import('electron').BrowserWindow): void {
}
if (icon.isEmpty()) {
const fallback = await loadNativeBundleIcon(app.isPackaged, () =>
app.getFileIcon(resolved.bundlePath, { size: 'large' }),
app.getFileIcon(resolved.bundlePath, BUNDLE_ICON_OPTIONS),
);
if (fallback && !fallback.isEmpty()) icon = fallback.resize({ width: 64, height: 64 });
// The file drag still works without a decorative drag image.
Expand Down