@glassly/engine 0.3.0-beta.489 → 0.3.0-dev.462
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/engine.d.ts +0 -3
- package/build/engine.d.ts.map +1 -1
- package/build/facades/miniapps.d.ts +0 -6
- package/build/facades/miniapps.d.ts.map +1 -1
- package/build/facades/miniapps.js +0 -7
- package/build/facades/miniapps.js.map +1 -1
- package/build/generated/releaseMetadata.js +3 -3
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +2 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -2
- package/build/index.js.map +1 -1
- package/build/services/AppRegistry.js +1 -1
- package/build/services/AppRegistry.js.map +1 -1
- package/build/services/LocalDisplayManager.d.ts +2 -1
- package/build/services/LocalDisplayManager.d.ts.map +1 -1
- package/build/services/LocalDisplayManager.js +2 -1
- package/build/services/LocalDisplayManager.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +9 -22
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +52 -117
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/MiniappLauncher.d.ts +0 -2
- package/build/services/MiniappLauncher.d.ts.map +1 -1
- package/build/services/MiniappLauncher.js +1 -6
- package/build/services/MiniappLauncher.js.map +1 -1
- package/build/services/pages/OverlayPages.d.ts +2 -13
- package/build/services/pages/OverlayPages.d.ts.map +1 -1
- package/build/services/pages/OverlayPages.js +10 -11
- package/build/services/pages/OverlayPages.js.map +1 -1
- package/build/services/pages/PageHost.d.ts +1 -1
- package/build/services/pages/PageHost.d.ts.map +1 -1
- package/build/services/pages/PageHost.js +2 -2
- package/build/services/pages/PageHost.js.map +1 -1
- package/build/services/pages/overlayApps.d.ts +13 -20
- package/build/services/pages/overlayApps.d.ts.map +1 -1
- package/build/services/pages/overlayApps.js +31 -50
- package/build/services/pages/overlayApps.js.map +1 -1
- package/build/services/settingsBridge.d.ts +14 -15
- package/build/services/settingsBridge.d.ts.map +1 -1
- package/build/services/settingsBridge.js +20 -20
- package/build/services/settingsBridge.js.map +1 -1
- package/build/stores/appVisibility.d.ts +0 -5
- package/build/stores/appVisibility.d.ts.map +1 -1
- package/build/stores/appVisibility.js +0 -2
- package/build/stores/appVisibility.js.map +1 -1
- package/build/stores/apps.d.ts +0 -5
- package/build/stores/apps.d.ts.map +1 -1
- package/build/stores/apps.js +10 -40
- package/build/stores/apps.js.map +1 -1
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +45 -19
- package/build/stores/settings.js.map +1 -1
- package/build/types/applet.d.ts +2 -2
- package/build/types/applet.d.ts.map +1 -1
- package/build/types/applet.js.map +1 -1
- package/build/utils/display/scene/anchor.d.ts +2 -1
- package/build/utils/display/scene/anchor.d.ts.map +1 -1
- package/build/utils/display/scene/anchor.js +2 -1
- package/build/utils/display/scene/anchor.js.map +1 -1
- package/package.json +7 -7
- package/src/facades/miniapps.ts +0 -9
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/index.ts +1 -3
- package/src/services/AppRegistry.ts +1 -1
- package/src/services/LocalDisplayManager.ts +2 -1
- package/src/services/LocalMiniappRuntime.ts +52 -136
- package/src/services/MiniappLauncher.ts +1 -6
- package/src/services/pages/OverlayPages.ts +10 -11
- package/src/services/pages/PageHost.ts +2 -2
- package/src/services/pages/overlayApps.ts +30 -51
- package/src/services/settingsBridge.ts +20 -20
- package/src/stores/appVisibility.ts +0 -4
- package/src/stores/apps.ts +12 -44
- package/src/stores/settings.ts +45 -19
- package/src/types/applet.ts +1 -3
- package/src/utils/display/scene/anchor.ts +2 -1
- package/build/services/miniappPermissions.d.ts +0 -16
- package/build/services/miniappPermissions.d.ts.map +0 -1
- package/build/services/miniappPermissions.js +0 -7
- package/build/services/miniappPermissions.js.map +0 -1
- package/build/services/pages/activeDashboard.d.ts +0 -7
- package/build/services/pages/activeDashboard.d.ts.map +0 -1
- package/build/services/pages/activeDashboard.js +0 -21
- package/build/services/pages/activeDashboard.js.map +0 -1
- package/src/services/miniappPermissions.ts +0 -19
- package/src/services/pages/activeDashboard.ts +0 -24
|
@@ -42,9 +42,7 @@ import dashboardOpenTrace from "./debug/DashboardOpenTrace";
|
|
|
42
42
|
import { isAppForegrounded, isPhoneActive, onAppForegroundChange, onPhoneActivityChange } from "./PhoneActivity";
|
|
43
43
|
import { installedNotificationApps } from "./PhoneNotificationsSync";
|
|
44
44
|
import { DERIVED_SETTINGS_KEYS, SETTINGS_BRIDGE_KEYS, isDerivedSettingsKey, ringBatteryFrom, selectSettingsBridgeKeys, validateSettingsSet, } from "./settingsBridge";
|
|
45
|
-
import {
|
|
46
|
-
import { activeDashboardAmong } from "./pages/activeDashboard";
|
|
47
|
-
import { activeDashboard, addDashboardApp, displayViewsFor, isDashboardApp, isOverlayApp, onOverlayAppsChange, removeDashboardApp, setActiveDashboard, setOverlayViewer, } from "./pages/overlayApps";
|
|
45
|
+
import { addOverlayApp, displayViewsFor, isOverlayApp, removeOverlayApp, setOverlayViewer } from "./pages/overlayApps";
|
|
48
46
|
import { pagesEligible } from "./pages/pageEligibility";
|
|
49
47
|
import nativeNavigationService from "./NativeNavigationService";
|
|
50
48
|
import headingService from "./HeadingService";
|
|
@@ -75,7 +73,6 @@ import { buildMiniappManifestSnapshot } from "../utils/miniappDiagnostics";
|
|
|
75
73
|
import ttsModelManager from "./TTSModelManager";
|
|
76
74
|
import { NavigationHandlers } from "./NavigationHandlers";
|
|
77
75
|
import { useAppStatusStore } from "../stores/apps";
|
|
78
|
-
import { isSystemMiniapp } from "../stores/appVisibility";
|
|
79
76
|
import { getDevAppAttestation, getDevAppSourcePackage } from "./AppRegistry";
|
|
80
77
|
import { resolveForegroundLocationPermission } from "./ForegroundLocationPermission";
|
|
81
78
|
import { advanceMiniappPingLiveness } from "./MiniappLiveness";
|
|
@@ -133,6 +130,9 @@ const SYSTEM_MINIAPP_PACKAGES = new Set([
|
|
|
133
130
|
"com.glassly.ai",
|
|
134
131
|
"com.glassly.feedback",
|
|
135
132
|
"com.glassly.miniappdev",
|
|
133
|
+
// The dashboard: the settings bridge and the miniapp list/start/stop are its side menu and settings
|
|
134
|
+
// page, and the notification app list is its notification settings' per-app filter.
|
|
135
|
+
"com.glassly.dashboard",
|
|
136
136
|
]);
|
|
137
137
|
const PING_INTERVAL_MS = 5_000;
|
|
138
138
|
// Min gap between "transcription limit reached" notices on the glasses. A
|
|
@@ -214,8 +214,6 @@ const PERMISSION_TYPE_TO_CANONICAL = {
|
|
|
214
214
|
MEMORY: "memory",
|
|
215
215
|
AI: "ai",
|
|
216
216
|
SPEAKERS: "speakers",
|
|
217
|
-
MANAGE_MINIAPPS: "manageMiniapps",
|
|
218
|
-
PLATFORM_SETTINGS: "platformSettings",
|
|
219
217
|
};
|
|
220
218
|
/**
|
|
221
219
|
* User API keys (Settings > API Keys) a miniapp may read via
|
|
@@ -315,8 +313,6 @@ const ALL_CANONICAL_PERMISSIONS = [
|
|
|
315
313
|
"ai",
|
|
316
314
|
"speakers",
|
|
317
315
|
"displayMirror",
|
|
318
|
-
"manageMiniapps",
|
|
319
|
-
"platformSettings",
|
|
320
316
|
];
|
|
321
317
|
/**
|
|
322
318
|
* Build the {location, microphone, camera, notifications, calendar, apiKeys}
|
|
@@ -965,11 +961,11 @@ class LocalMiniappRuntime {
|
|
|
965
961
|
// Drop this app's transcription hints; the cloud subscription rebuild
|
|
966
962
|
// below (via replaceStreamSubscribers) re-derives the hint union without it.
|
|
967
963
|
this.transcriptionHintsByApp.delete(packageName);
|
|
968
|
-
//
|
|
964
|
+
// An overlay app is going: release the slot if it holds it, and drop the
|
|
969
965
|
// dashboard view from its capabilities record.
|
|
970
|
-
if (
|
|
966
|
+
if (isOverlayApp(packageName)) {
|
|
971
967
|
overlayPages.remove(packageName);
|
|
972
|
-
|
|
968
|
+
removeOverlayApp(packageName);
|
|
973
969
|
}
|
|
974
970
|
// Its gesture claims go back to whoever claimed them before.
|
|
975
971
|
this.applyGestureClaimChanges(dropGestureClaims(this.gestureClaims, packageName));
|
|
@@ -1328,10 +1324,7 @@ class LocalMiniappRuntime {
|
|
|
1328
1324
|
this.handleOpenUrl(packageName, payload);
|
|
1329
1325
|
break;
|
|
1330
1326
|
case MiniappRequestType.DISPLAY_DIAGNOSTICS: {
|
|
1331
|
-
|
|
1332
|
-
const settings = useSettingsStore.getState();
|
|
1333
|
-
const enabled = settings.getSetting(SETTINGS.debug_console.key) === true &&
|
|
1334
|
-
settings.getSetting(SETTINGS.g2_perf_logs.key) === true;
|
|
1327
|
+
const enabled = useSettingsStore.getState().getSetting(SETTINGS.debug_console.key) === true;
|
|
1335
1328
|
this.sendResult(packageName, requestId, true, {
|
|
1336
1329
|
enabled,
|
|
1337
1330
|
generatedAt: Date.now(),
|
|
@@ -1485,12 +1478,10 @@ class LocalMiniappRuntime {
|
|
|
1485
1478
|
// Update lastPongAt so it doesn't time out right away
|
|
1486
1479
|
existing.lastPongAt = Date.now();
|
|
1487
1480
|
existing.unansweredPingRounds = 0;
|
|
1488
|
-
//
|
|
1489
|
-
//
|
|
1490
|
-
if (existing.installedManifest?.type === "
|
|
1491
|
-
|
|
1492
|
-
this.syncActiveDashboard();
|
|
1493
|
-
}
|
|
1481
|
+
// A system_dashboard app may take the overlay slot: its capabilities
|
|
1482
|
+
// carry the dashboard view from the start.
|
|
1483
|
+
if (existing.installedManifest?.type === "system_dashboard")
|
|
1484
|
+
addOverlayApp(packageName);
|
|
1494
1485
|
const capabilities = this.capabilitiesFor(packageName);
|
|
1495
1486
|
// Build the declared-permission record for the SDK's session.permissions
|
|
1496
1487
|
// module. Lower-cased to match v3's PermissionType union (microphone,
|
|
@@ -1834,25 +1825,23 @@ class LocalMiniappRuntime {
|
|
|
1834
1825
|
const required = permissionForStream(stream);
|
|
1835
1826
|
if (required && !declaredTypes.has(required)) {
|
|
1836
1827
|
logPermissionNotDeclared(packageName, required, `to subscribe to "${stream}"`, `{"type": "${required}"}`);
|
|
1837
|
-
|
|
1828
|
+
this.sendResult(packageName, requestId, false, undefined, {
|
|
1838
1829
|
code: MiniappErrorCode.PERMISSION_NOT_DECLARED,
|
|
1839
1830
|
message: `${required} permission not declared in miniapp.json (required for "${stream}"). Add {"type": "${required}"} to the "permissions" array.`,
|
|
1840
1831
|
// Extra context fields read by the SDK so authors that subscribe
|
|
1841
1832
|
// to session.on("error") can format their own messages.
|
|
1842
1833
|
permission: required,
|
|
1843
1834
|
subscription: stream,
|
|
1844
|
-
};
|
|
1845
|
-
// The SDK sends SUBSCRIBE without a requestId, so push the rejection.
|
|
1846
|
-
if (requestId)
|
|
1847
|
-
this.sendResult(packageName, requestId, false, undefined, error);
|
|
1848
|
-
else
|
|
1849
|
-
this.sendToMiniapp(packageName, { type: MiniappResponseType.ERROR, ...error });
|
|
1835
|
+
});
|
|
1850
1836
|
return;
|
|
1851
1837
|
}
|
|
1852
1838
|
}
|
|
1853
|
-
// The settings stream carries the wearer's settings.
|
|
1854
|
-
if (streams.includes(MiniappStreamType.SETTINGS_CHANGED) &&
|
|
1855
|
-
|
|
1839
|
+
// The settings stream carries the wearer's settings: system apps only.
|
|
1840
|
+
if (streams.includes(MiniappStreamType.SETTINGS_CHANGED) && !this.isSystemPackage(packageName)) {
|
|
1841
|
+
this.sendResult(packageName, requestId, false, undefined, {
|
|
1842
|
+
code: MiniappErrorCode.NOT_PERMITTED,
|
|
1843
|
+
message: "The settings stream is restricted to system apps",
|
|
1844
|
+
});
|
|
1856
1845
|
return;
|
|
1857
1846
|
}
|
|
1858
1847
|
// Add new subscriptions
|
|
@@ -1861,9 +1850,8 @@ class LocalMiniappRuntime {
|
|
|
1861
1850
|
app.forceLocalTranscriptionStreams = new Set([...forceLocalTranscriptionStreams].filter((stream) => app.subscriptions.has(stream)));
|
|
1862
1851
|
app.cloudTranscriptionStreams = new Set([...cloudTranscriptionStreams].filter((stream) => app.subscriptions.has(stream)));
|
|
1863
1852
|
this.replaceStreamSubscribers(packageName, previousSubscriptions, app.subscriptions);
|
|
1864
|
-
//
|
|
1865
|
-
|
|
1866
|
-
if (isDashboardApp(packageName)) {
|
|
1853
|
+
// An overlay app that listens to phone notifications presents them on the glasses.
|
|
1854
|
+
if (isOverlayApp(packageName)) {
|
|
1867
1855
|
setOverlayViewer(packageName, app.subscriptions.has(MiniappStreamType.PHONE_NOTIFICATION));
|
|
1868
1856
|
}
|
|
1869
1857
|
this.recomputeMicRequirements();
|
|
@@ -2085,13 +2073,13 @@ class LocalMiniappRuntime {
|
|
|
2085
2073
|
});
|
|
2086
2074
|
return;
|
|
2087
2075
|
}
|
|
2088
|
-
// The dashboard view is the overlay
|
|
2076
|
+
// The dashboard view is the overlay apps' alone; anyone else's frame
|
|
2089
2077
|
// is dropped, reported rather than silently lost.
|
|
2090
2078
|
if (payload.view === "dashboard" && !isOverlayApp(packageName)) {
|
|
2091
2079
|
this.sendResult(packageName, requestId, true, {
|
|
2092
2080
|
status: "displayed",
|
|
2093
2081
|
presented: false,
|
|
2094
|
-
reason: "not the
|
|
2082
|
+
reason: "not the dashboard app",
|
|
2095
2083
|
});
|
|
2096
2084
|
return;
|
|
2097
2085
|
}
|
|
@@ -2110,11 +2098,10 @@ class LocalMiniappRuntime {
|
|
|
2110
2098
|
}
|
|
2111
2099
|
}
|
|
2112
2100
|
/**
|
|
2113
|
-
* display.showView: the
|
|
2114
|
-
* slot. Refused (NOT_PERMITTED) for
|
|
2115
|
-
*
|
|
2116
|
-
*
|
|
2117
|
-
* comes back to the app as a display_view change.
|
|
2101
|
+
* display.showView: the designated dashboard app takes or releases the
|
|
2102
|
+
* overlay slot. Refused (NOT_PERMITTED) for any other app; "unsupported"
|
|
2103
|
+
* while the glasses cannot show the dashboard view. Idempotent either way;
|
|
2104
|
+
* the slot's state comes back to the app as a display_view change.
|
|
2118
2105
|
*/
|
|
2119
2106
|
handleShowView(packageName, payload, requestId) {
|
|
2120
2107
|
if (!this.connectedApps.has(packageName)) {
|
|
@@ -2129,17 +2116,13 @@ class LocalMiniappRuntime {
|
|
|
2129
2116
|
});
|
|
2130
2117
|
return;
|
|
2131
2118
|
}
|
|
2132
|
-
if (!
|
|
2119
|
+
if (!isOverlayApp(packageName)) {
|
|
2133
2120
|
this.sendResult(packageName, requestId, false, undefined, {
|
|
2134
2121
|
code: MiniappErrorCode.NOT_PERMITTED,
|
|
2135
|
-
message:
|
|
2122
|
+
message: "The dashboard view belongs to system_dashboard apps",
|
|
2136
2123
|
});
|
|
2137
2124
|
return;
|
|
2138
2125
|
}
|
|
2139
|
-
if (!isOverlayApp(packageName)) {
|
|
2140
|
-
this.sendResult(packageName, requestId, true, { status: "unsupported", reason: "not the active dashboard" });
|
|
2141
|
-
return;
|
|
2142
|
-
}
|
|
2143
2126
|
if (view === "main") {
|
|
2144
2127
|
overlayPages.hide(packageName);
|
|
2145
2128
|
this.sendResult(packageName, requestId, true, { status: "shown" });
|
|
@@ -2158,31 +2141,18 @@ class LocalMiniappRuntime {
|
|
|
2158
2141
|
dashboardOpenTrace.slotGranted();
|
|
2159
2142
|
this.sendResult(packageName, requestId, true, shown ? { status: "shown" } : { status: "unsupported", reason: "the overlay slot was refused" });
|
|
2160
2143
|
}
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
const caller = {
|
|
2167
|
-
system: this.isSystemPackage(packageName),
|
|
2168
|
-
permissions: this.connectedApps.get(packageName)?.installedManifest?.permissions,
|
|
2169
|
-
};
|
|
2170
|
-
if (mayUsePermission(caller, permission))
|
|
2144
|
+
// ---------------------------------------------------------------------------
|
|
2145
|
+
// Settings bridge (session.settings) — system apps only
|
|
2146
|
+
// ---------------------------------------------------------------------------
|
|
2147
|
+
requireSystemForSettings(packageName, requestId) {
|
|
2148
|
+
if (this.isSystemPackage(packageName))
|
|
2171
2149
|
return true;
|
|
2172
|
-
logPermissionNotDeclared(packageName, permission, context, `{"type": "${permission}"}`);
|
|
2173
2150
|
this.sendResult(packageName, requestId, false, undefined, {
|
|
2174
|
-
code: MiniappErrorCode.
|
|
2175
|
-
message:
|
|
2176
|
-
permission,
|
|
2151
|
+
code: MiniappErrorCode.NOT_PERMITTED,
|
|
2152
|
+
message: "The settings bridge is restricted to system apps",
|
|
2177
2153
|
});
|
|
2178
2154
|
return false;
|
|
2179
2155
|
}
|
|
2180
|
-
// ---------------------------------------------------------------------------
|
|
2181
|
-
// Settings bridge (session.settings) — PLATFORM_SETTINGS permission
|
|
2182
|
-
// ---------------------------------------------------------------------------
|
|
2183
|
-
requireSettingsPermission(packageName, requestId) {
|
|
2184
|
-
return this.requirePermission(packageName, requestId, "PLATFORM_SETTINGS", "to use the settings bridge");
|
|
2185
|
-
}
|
|
2186
2156
|
/** A bridged key's current value: the store's, or the engine's for a derived key. */
|
|
2187
2157
|
settingsBridgeValue(key) {
|
|
2188
2158
|
if (isDerivedSettingsKey(key))
|
|
@@ -2197,12 +2167,10 @@ class LocalMiniappRuntime {
|
|
|
2197
2167
|
return localDisplayManager.foregroundAppOnScreen();
|
|
2198
2168
|
case "ring_battery":
|
|
2199
2169
|
return ringBatteryFrom(useGlassesStore.getState());
|
|
2200
|
-
case "active_dashboard":
|
|
2201
|
-
return activeDashboard();
|
|
2202
2170
|
}
|
|
2203
2171
|
}
|
|
2204
2172
|
handleSettingsGet(packageName, payload, requestId) {
|
|
2205
|
-
if (!this.
|
|
2173
|
+
if (!this.requireSystemForSettings(packageName, requestId))
|
|
2206
2174
|
return;
|
|
2207
2175
|
const values = {};
|
|
2208
2176
|
for (const key of selectSettingsBridgeKeys(payload.keys))
|
|
@@ -2210,7 +2178,7 @@ class LocalMiniappRuntime {
|
|
|
2210
2178
|
this.sendResult(packageName, requestId, true, { values });
|
|
2211
2179
|
}
|
|
2212
2180
|
async handleSettingsSet(packageName, payload, requestId) {
|
|
2213
|
-
if (!this.
|
|
2181
|
+
if (!this.requireSystemForSettings(packageName, requestId))
|
|
2214
2182
|
return;
|
|
2215
2183
|
const validated = validateSettingsSet(payload);
|
|
2216
2184
|
if (!validated.ok) {
|
|
@@ -2230,9 +2198,8 @@ class LocalMiniappRuntime {
|
|
|
2230
2198
|
this.sendResult(packageName, requestId, true);
|
|
2231
2199
|
}
|
|
2232
2200
|
async handleNotificationAppsList(packageName, requestId) {
|
|
2233
|
-
if (!this.
|
|
2201
|
+
if (!this.requireSystemForSettings(packageName, requestId))
|
|
2234
2202
|
return;
|
|
2235
|
-
}
|
|
2236
2203
|
try {
|
|
2237
2204
|
this.sendResult(packageName, requestId, true, await installedNotificationApps());
|
|
2238
2205
|
}
|
|
@@ -2246,9 +2213,8 @@ class LocalMiniappRuntime {
|
|
|
2246
2213
|
/**
|
|
2247
2214
|
* Push bridged settings as they change: stored keys from the store, the
|
|
2248
2215
|
* derived keys whenever their inputs move (phone activity, the display,
|
|
2249
|
-
* the apps store, the ring
|
|
2250
|
-
*
|
|
2251
|
-
* everyone else.
|
|
2216
|
+
* the apps store, the ring). Subscribers are system apps only (gated at
|
|
2217
|
+
* SUBSCRIBE), so this is a no-op fan-out for everyone else.
|
|
2252
2218
|
*/
|
|
2253
2219
|
ensureSettingsBridgeWired() {
|
|
2254
2220
|
if (this.settingsBridgeWired)
|
|
@@ -2283,7 +2249,6 @@ class LocalMiniappRuntime {
|
|
|
2283
2249
|
onAppForegroundChange((foregrounded) => this.broadcastVisibility(foregrounded));
|
|
2284
2250
|
localDisplayManager.onActiveDisplayChange(pushDerived);
|
|
2285
2251
|
useAppStatusStore.subscribe(pushDerived);
|
|
2286
|
-
onOverlayAppsChange(pushDerived);
|
|
2287
2252
|
useGlassesStore.subscribe((s) => `${s.ringConnected}:${s.ringBatteryLevel}:${s.controllerConnected}:${s.controllerBatteryLevel}`, pushDerived);
|
|
2288
2253
|
}
|
|
2289
2254
|
/**
|
|
@@ -4597,33 +4562,6 @@ class LocalMiniappRuntime {
|
|
|
4597
4562
|
useSettingsStore.subscribe((s) => s.getSetting(SETTINGS.cfw_native_navigation.key), broadcast);
|
|
4598
4563
|
// The dashboard master switch flips the dashboard view.
|
|
4599
4564
|
useSettingsStore.subscribe((s) => s.getSetting(SETTINGS.custom_dashboard_enabled.key), broadcast);
|
|
4600
|
-
// The wearer's choice and the installed dashboards decide who holds the role.
|
|
4601
|
-
const syncRole = () => this.syncActiveDashboard();
|
|
4602
|
-
useSettingsStore.subscribe((s) => s.getSetting(SETTINGS.active_dashboard.key), syncRole);
|
|
4603
|
-
useAppStatusStore.subscribe(syncRole);
|
|
4604
|
-
syncRole();
|
|
4605
|
-
}
|
|
4606
|
-
/**
|
|
4607
|
-
* Recompute who holds the dashboard role (ADR-0009). The previous holder
|
|
4608
|
-
* gives up the slot first, so it hears the view change while it is still
|
|
4609
|
-
* the overlay app; then every app sees its views again.
|
|
4610
|
-
*/
|
|
4611
|
-
syncActiveDashboard() {
|
|
4612
|
-
const candidates = [...useAppStatusStore.getState().apps];
|
|
4613
|
-
// A dashboard can connect at launch before the apps store has listed it.
|
|
4614
|
-
for (const [packageName, app] of this.connectedApps) {
|
|
4615
|
-
if (candidates.some((candidate) => candidate.packageName === packageName))
|
|
4616
|
-
continue;
|
|
4617
|
-
candidates.push({ packageName, type: app.installedManifest?.type });
|
|
4618
|
-
}
|
|
4619
|
-
const next = activeDashboardAmong(candidates);
|
|
4620
|
-
const previous = activeDashboard();
|
|
4621
|
-
if (next === previous)
|
|
4622
|
-
return;
|
|
4623
|
-
if (previous !== null)
|
|
4624
|
-
overlayPages.hide(previous, "replaced");
|
|
4625
|
-
setActiveDashboard(next);
|
|
4626
|
-
this.broadcastCapabilities();
|
|
4627
4565
|
}
|
|
4628
4566
|
/** Capabilities as `packageName` sees them: the model profile plus the views this app may draw. */
|
|
4629
4567
|
capabilitiesFor(packageName) {
|
|
@@ -5050,16 +4988,14 @@ class LocalMiniappRuntime {
|
|
|
5050
4988
|
/* telemetry must never break an interop call */
|
|
5051
4989
|
}
|
|
5052
4990
|
}
|
|
5053
|
-
/** Reject the request unless the caller
|
|
5054
|
-
|
|
5055
|
-
if (this.
|
|
4991
|
+
/** Reject the request with NOT_PERMITTED unless the caller is a system app. */
|
|
4992
|
+
requireSystemCaller(packageName, requestId, op, target) {
|
|
4993
|
+
if (this.isSystemPackage(packageName))
|
|
5056
4994
|
return true;
|
|
5057
|
-
this.auditInterop({
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
ok: false,
|
|
5062
|
-
errorCode: MiniappErrorCode.PERMISSION_NOT_DECLARED,
|
|
4995
|
+
this.auditInterop({ caller: packageName, op, target, ok: false, errorCode: MiniappErrorCode.NOT_PERMITTED });
|
|
4996
|
+
this.sendResult(packageName, requestId, false, undefined, {
|
|
4997
|
+
code: MiniappErrorCode.NOT_PERMITTED,
|
|
4998
|
+
message: "Inter-miniapp APIs are restricted to system apps",
|
|
5063
4999
|
});
|
|
5064
5000
|
return false;
|
|
5065
5001
|
}
|
|
@@ -5077,13 +5013,12 @@ class LocalMiniappRuntime {
|
|
|
5077
5013
|
version: app.version ?? "",
|
|
5078
5014
|
running: app.running,
|
|
5079
5015
|
hidden: app.hidden === true,
|
|
5080
|
-
system: isSystemMiniapp(app),
|
|
5081
5016
|
compatibility,
|
|
5082
5017
|
actions: app.actions ?? [],
|
|
5083
5018
|
};
|
|
5084
5019
|
}
|
|
5085
5020
|
handleMiniappsList(packageName, payload, requestId) {
|
|
5086
|
-
if (!this.
|
|
5021
|
+
if (!this.requireSystemCaller(packageName, requestId, "list"))
|
|
5087
5022
|
return;
|
|
5088
5023
|
const includeIncompatible = payload.includeIncompatible === true;
|
|
5089
5024
|
const infos = this.interopApps()
|
|
@@ -5097,7 +5032,7 @@ class LocalMiniappRuntime {
|
|
|
5097
5032
|
}
|
|
5098
5033
|
async handleMiniappsStart(packageName, payload, requestId) {
|
|
5099
5034
|
const target = payload.packageName;
|
|
5100
|
-
if (!this.
|
|
5035
|
+
if (!this.requireSystemCaller(packageName, requestId, "start", target))
|
|
5101
5036
|
return;
|
|
5102
5037
|
const app = target ? this.interopApps().find((a) => a.packageName === target) : undefined;
|
|
5103
5038
|
if (!target || !app) {
|
|
@@ -5186,7 +5121,7 @@ class LocalMiniappRuntime {
|
|
|
5186
5121
|
}
|
|
5187
5122
|
async handleMiniappsStop(packageName, payload, requestId) {
|
|
5188
5123
|
const target = payload.packageName;
|
|
5189
|
-
if (!this.
|
|
5124
|
+
if (!this.requireSystemCaller(packageName, requestId, "stop", target))
|
|
5190
5125
|
return;
|
|
5191
5126
|
if (!target) {
|
|
5192
5127
|
this.sendResult(packageName, requestId, false, undefined, {
|