dsh-mobile 0.6.6 → 0.6.8
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/CHANGELOG.md +20 -0
- package/CONTRIBUTORS.md +11 -1
- package/README.en.md +21 -13
- package/README.md +21 -13
- package/SECURITY.md +9 -0
- package/docs/CPOLAR_SUBDOMAIN.en.md +81 -0
- package/docs/CPOLAR_SUBDOMAIN.md +81 -0
- package/docs/README.md +1 -0
- package/docs/SKIN_COMPATIBILITY.en.md +1 -1
- package/docs/SKIN_COMPATIBILITY.md +1 -1
- package/lib/cli.js +2 -0
- package/lib/cli.js.map +1 -1
- package/lib/client.js +240 -25
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +31 -4
- package/lib/index.mjs +202 -95
- package/lib/index.mjs.map +1 -1
- package/package.json +6 -1
- package/packages/question-fixes/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -3397,6 +3397,13 @@ window.__ModuleLoader__.load({
|
|
|
3397
3397
|
html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*="_sessionRow"] [class*="_pinIndicator"] { display:none !important; }
|
|
3398
3398
|
html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*="_rowActions"] button { box-sizing:border-box !important; width:32px !important; min-width:32px !important; height:32px !important; min-height:32px !important; }
|
|
3399
3399
|
[data-dsh-mobile-frame] { grid-template-columns:0 minmax(0,1fr) 0 !important; width:100% !important; height:100dvh !important; overflow:hidden !important; }
|
|
3400
|
+
/* The stock frame owns layout, not a tap target. Restore only its content
|
|
3401
|
+
columns; the stock shell-overlay retains its own descendant hit policy. */
|
|
3402
|
+
html.dsh-native-mobile-active [data-dsh-mobile-frame] { pointer-events:none !important; }
|
|
3403
|
+
html.dsh-native-mobile-active [data-dsh-mobile-frame] > :is([data-dsh-mobile-sidebar],[data-dsh-mobile-center],[class*="_rightbarCol"]) { pointer-events:auto !important; }
|
|
3404
|
+
/* Floating slot surfaces paint above mobile drawers; their empty layer
|
|
3405
|
+
stays click-through and each stock occupant retains its own hit policy. */
|
|
3406
|
+
html.dsh-native-mobile-active [data-shell-overlay] { z-index:300 !important; pointer-events:none !important; }
|
|
3400
3407
|
[data-dsh-mobile-center] { grid-column:2 !important; width:100vw !important; min-width:0 !important; }
|
|
3401
3408
|
[data-dsh-mobile-center] > * { min-width:0 !important; }
|
|
3402
3409
|
[data-dsh-mobile-header] { box-sizing:border-box !important; width:calc(100% - 16px) !important; margin:0 8px !important; min-width:0; padding-top:max(4px,env(safe-area-inset-top)) !important; padding-right:8px !important; padding-left:42px !important; }
|
|
@@ -3418,6 +3425,10 @@ window.__ModuleLoader__.load({
|
|
|
3418
3425
|
[data-dsh-mobile-sidebar] { position:fixed !important; z-index:240 !important; inset:0 auto 0 0 !important; width:0 !important; overflow:visible !important; }
|
|
3419
3426
|
[data-dsh-mobile-sidebar-root] { position:fixed !important; z-index:241 !important; inset:max(env(safe-area-inset-top),0px) auto 0 0 !important; height:auto !important; transition:width 180ms var(--dsh-mobile-motion-ease),box-shadow 180ms ease !important; }
|
|
3420
3427
|
[data-dsh-mobile-sidebar][data-open="true"] [data-dsh-mobile-sidebar-root] { width:min(88vw,340px) !important; padding-top:0 !important; box-shadow:18px 0 46px rgb(15 23 42 / 18%); }
|
|
3428
|
+
/* Extra panel/footer seats may exceed a short drawer. Keep a bounded
|
|
3429
|
+
workspace scrollport and let the drawer scroll to the remaining seats. */
|
|
3430
|
+
[data-dsh-mobile-sidebar][data-open="true"]:not(:has([data-dsh-mobile-settings])) [data-dsh-mobile-sidebar-root] { overflow-y:auto !important; overscroll-behavior-y:contain; }
|
|
3431
|
+
[data-dsh-mobile-sidebar][data-open="true"]:not(:has([data-dsh-mobile-settings])) [data-dsh-mobile-sidebar-root] > [class*="_regionArea"] { flex:1 0 50% !important; }
|
|
3421
3432
|
[data-dsh-mobile-sidebar][data-open="true"] [data-dsh-mobile-sidebar-root] [class*="_logoRow"] { height:52px !important; padding:4px 0 4px 4px !important; margin-bottom:4px !important; }
|
|
3422
3433
|
[data-dsh-mobile-sidebar][data-open="false"] [data-dsh-mobile-sidebar-root] { width:0 !important; border:0 !important; background:transparent !important; box-shadow:none !important; overflow:visible !important; }
|
|
3423
3434
|
[data-dsh-mobile-sidebar][data-open="false"] [data-dsh-mobile-sidebar-root] > :not(:has([data-dsh-mobile-toggle])) { display:none !important; }
|
|
@@ -6807,6 +6818,122 @@ window.__ModuleLoader__.load({
|
|
|
6807
6818
|
});
|
|
6808
6819
|
}
|
|
6809
6820
|
//#endregion
|
|
6821
|
+
//#region src/mobile-custom-assets.ts
|
|
6822
|
+
const COPY = {
|
|
6823
|
+
en: {
|
|
6824
|
+
gateway_required: "Custom mobile CSS, scripts and extensions require a paired DSH Mobile access entry. This page is not using the Mobile gateway.",
|
|
6825
|
+
authentication_required: "Mobile customization was not refreshed because device authentication is unavailable. Reconnect through the current Mobile access entry.",
|
|
6826
|
+
manifest_unavailable: "The mobile extension manifest is unavailable. Check the plugin version and proxy routing; legacy custom files can still load when authorized.",
|
|
6827
|
+
manifest_invalid: "The mobile extension manifest is invalid. Existing customization is retained; check the plugin version and proxy routing.",
|
|
6828
|
+
resource_unavailable: "A mobile customization resource could not be loaded or activated. Check the custom files and current Mobile access entry.",
|
|
6829
|
+
refresh_failed: "Mobile customization could not be refreshed. Check the connection and current Mobile access entry.",
|
|
6830
|
+
recovered: "Mobile customization is available again."
|
|
6831
|
+
},
|
|
6832
|
+
it: {
|
|
6833
|
+
gateway_required: "CSS, script ed estensioni mobili personalizzati richiedono un accesso DSH Mobile abbinato. Questa pagina non usa il gateway Mobile.",
|
|
6834
|
+
authentication_required: "La personalizzazione mobile non è stata aggiornata perché l’autenticazione del dispositivo non è disponibile. Riconnettiti tramite l’accesso Mobile attuale.",
|
|
6835
|
+
manifest_unavailable: "Il manifest delle estensioni mobili non è disponibile. Controlla la versione del plugin e le route del proxy; i file personalizzati legacy possono essere caricati se autorizzati.",
|
|
6836
|
+
manifest_invalid: "Il manifest delle estensioni mobili non è valido. La personalizzazione esistente viene mantenuta; controlla la versione del plugin e le route del proxy.",
|
|
6837
|
+
resource_unavailable: "Una risorsa mobile personalizzata non è stata caricata o attivata. Controlla i file personalizzati e l’accesso Mobile attuale.",
|
|
6838
|
+
refresh_failed: "Impossibile aggiornare la personalizzazione mobile. Controlla la connessione e l’accesso Mobile attuale.",
|
|
6839
|
+
recovered: "La personalizzazione mobile è di nuovo disponibile."
|
|
6840
|
+
},
|
|
6841
|
+
zh: {
|
|
6842
|
+
gateway_required: "自定义移动样式、脚本与扩展需要通过已配对的 DSH Mobile 入口访问;当前页面不是移动网关页面。",
|
|
6843
|
+
authentication_required: "设备认证不可用,移动定制暂未刷新;请通过当前移动访问入口重新连接。",
|
|
6844
|
+
manifest_unavailable: "移动扩展清单不可用;请检查插件版本及反向代理路由。通过认证时,旧版自定义文件仍可加载。",
|
|
6845
|
+
manifest_invalid: "移动扩展清单无效,保留现有定制;请检查插件版本及反向代理路由。",
|
|
6846
|
+
resource_unavailable: "移动定制资源加载或激活失败;请检查定制文件及当前移动访问入口。",
|
|
6847
|
+
refresh_failed: "移动定制暂未刷新;请检查网络及当前移动访问入口。",
|
|
6848
|
+
recovered: "移动定制已恢复加载。"
|
|
6849
|
+
}
|
|
6850
|
+
};
|
|
6851
|
+
/** Only the authenticated Gateway owns customization APIs; the older dedicated marker remains supported. */
|
|
6852
|
+
function ownsMobileCustomization(gateway, frontend) {
|
|
6853
|
+
return gateway === true || frontend === "dedicated";
|
|
6854
|
+
}
|
|
6855
|
+
/** Emit each safe failure once until recovery, and ignore work after cancellation or disposal. */
|
|
6856
|
+
function createMobileAssetLoadReporter(locale, output = console) {
|
|
6857
|
+
const reported = /* @__PURE__ */ new Set();
|
|
6858
|
+
let disposed = false;
|
|
6859
|
+
return {
|
|
6860
|
+
fail(reason, signal) {
|
|
6861
|
+
if (disposed || signal?.aborted === true || reported.has(reason)) return;
|
|
6862
|
+
if (reason === "resource_unavailable" && reported.has("authentication_required")) return;
|
|
6863
|
+
reported.add(reason);
|
|
6864
|
+
output.warn(`[DSH Mobile] ${COPY[locale()][reason]}`);
|
|
6865
|
+
},
|
|
6866
|
+
recover(signal) {
|
|
6867
|
+
if (disposed || signal.aborted || reported.size === 0) return;
|
|
6868
|
+
reported.clear();
|
|
6869
|
+
output.info(`[DSH Mobile] ${COPY[locale()].recovered}`);
|
|
6870
|
+
},
|
|
6871
|
+
dispose() {
|
|
6872
|
+
disposed = true;
|
|
6873
|
+
reported.clear();
|
|
6874
|
+
}
|
|
6875
|
+
};
|
|
6876
|
+
}
|
|
6877
|
+
/** Read customization text within its file budget; the aggregate manifest has no existing byte cap. */
|
|
6878
|
+
async function readMobileAssetText(response, signal, maxBytes) {
|
|
6879
|
+
const assertActive = () => {
|
|
6880
|
+
if (signal.aborted) throw signal.reason ?? new DOMException("mobile customization cancelled", "AbortError");
|
|
6881
|
+
};
|
|
6882
|
+
if (response.body === null) {
|
|
6883
|
+
assertActive();
|
|
6884
|
+
return "";
|
|
6885
|
+
}
|
|
6886
|
+
const reader = response.body.getReader();
|
|
6887
|
+
let cancelled;
|
|
6888
|
+
const cancel = () => cancelled ??= reader.cancel().catch((error) => {});
|
|
6889
|
+
const aborted = () => {
|
|
6890
|
+
cancel();
|
|
6891
|
+
};
|
|
6892
|
+
signal.addEventListener("abort", aborted, { once: true });
|
|
6893
|
+
let completed = false;
|
|
6894
|
+
try {
|
|
6895
|
+
assertActive();
|
|
6896
|
+
const chunks = [];
|
|
6897
|
+
let bytes = 0;
|
|
6898
|
+
while (true) {
|
|
6899
|
+
const next = await reader.read();
|
|
6900
|
+
assertActive();
|
|
6901
|
+
if (next.done) {
|
|
6902
|
+
completed = true;
|
|
6903
|
+
break;
|
|
6904
|
+
}
|
|
6905
|
+
bytes += next.value.byteLength;
|
|
6906
|
+
if (maxBytes !== void 0 && bytes > maxBytes) throw new Error("mobile customization resource is too large");
|
|
6907
|
+
chunks.push(next.value);
|
|
6908
|
+
}
|
|
6909
|
+
const body = new Uint8Array(bytes);
|
|
6910
|
+
let offset = 0;
|
|
6911
|
+
for (const chunk of chunks) {
|
|
6912
|
+
body.set(chunk, offset);
|
|
6913
|
+
offset += chunk.byteLength;
|
|
6914
|
+
}
|
|
6915
|
+
return new TextDecoder().decode(body);
|
|
6916
|
+
} finally {
|
|
6917
|
+
signal.removeEventListener("abort", aborted);
|
|
6918
|
+
if (!completed) await cancel();
|
|
6919
|
+
reader.releaseLock();
|
|
6920
|
+
}
|
|
6921
|
+
}
|
|
6922
|
+
//#endregion
|
|
6923
|
+
//#region src/extension-limits.ts
|
|
6924
|
+
/** Maximum sizes accepted for legacy mobile customization resources. */
|
|
6925
|
+
const LEGACY_CUSTOM_ASSET_LIMIT = 262144;
|
|
6926
|
+
/** Maximum sizes enforced when reading local extension files. */
|
|
6927
|
+
const EXTENSION_LIMITS = Object.freeze({
|
|
6928
|
+
manifest: 65536,
|
|
6929
|
+
script: 1048576,
|
|
6930
|
+
css: 524288,
|
|
6931
|
+
asset: 8388608,
|
|
6932
|
+
assetFiles: 256,
|
|
6933
|
+
assetBytes: 33554432,
|
|
6934
|
+
assetDepth: 8
|
|
6935
|
+
});
|
|
6936
|
+
//#endregion
|
|
6810
6937
|
//#region src/client.ts
|
|
6811
6938
|
/** Map a host-reported provider onto the UI union, defaulting to the built-in one. */
|
|
6812
6939
|
function parseMobileRemoteProvider(value) {
|
|
@@ -11087,6 +11214,7 @@ window.__ModuleLoader__.load({
|
|
|
11087
11214
|
}
|
|
11088
11215
|
/** A missing manifest is authoritative before optional legacy resources finish refreshing. */
|
|
11089
11216
|
async function handleMissingExtensionManifest(clearManifestResources, refreshLegacyResources, signal) {
|
|
11217
|
+
if (signal.aborted) return false;
|
|
11090
11218
|
clearManifestResources();
|
|
11091
11219
|
const results = await refreshLegacyResources();
|
|
11092
11220
|
return !signal.aborted && results.every(Boolean);
|
|
@@ -11179,10 +11307,11 @@ window.__ModuleLoader__.load({
|
|
|
11179
11307
|
function startExtensionChangeStream(changed, runtime = {
|
|
11180
11308
|
window,
|
|
11181
11309
|
create: (url) => new EventSource(url, { withCredentials: true })
|
|
11182
|
-
}, onTaskEvent, onDeviceRevoked) {
|
|
11310
|
+
}, onTaskEvent, onDeviceRevoked, initiallyEnabled = true) {
|
|
11183
11311
|
let source;
|
|
11184
11312
|
let timer;
|
|
11185
11313
|
let disposed = false;
|
|
11314
|
+
let enabled = initiallyEnabled;
|
|
11186
11315
|
let retryMs = 1e3;
|
|
11187
11316
|
const clearTimer = () => {
|
|
11188
11317
|
if (timer === void 0) return;
|
|
@@ -11190,19 +11319,24 @@ window.__ModuleLoader__.load({
|
|
|
11190
11319
|
timer = void 0;
|
|
11191
11320
|
};
|
|
11192
11321
|
const connect = () => {
|
|
11193
|
-
if (disposed || source !== void 0) return;
|
|
11322
|
+
if (disposed || !enabled || source !== void 0) return;
|
|
11194
11323
|
clearTimer();
|
|
11195
11324
|
const next = runtime.create("/mobile-access/extensions/events");
|
|
11196
11325
|
source = next;
|
|
11326
|
+
const current = () => !disposed && enabled && source === next;
|
|
11197
11327
|
next.onopen = () => {
|
|
11198
|
-
retryMs = 1e3;
|
|
11328
|
+
if (current()) retryMs = 1e3;
|
|
11199
11329
|
};
|
|
11200
|
-
next.addEventListener("extensions-changed",
|
|
11330
|
+
next.addEventListener("extensions-changed", () => {
|
|
11331
|
+
if (current()) changed();
|
|
11332
|
+
});
|
|
11201
11333
|
if (onTaskEvent !== void 0) next.addEventListener("task-notify", (message) => {
|
|
11334
|
+
if (!current()) return;
|
|
11202
11335
|
const data = message.data;
|
|
11203
11336
|
onTaskEvent(data);
|
|
11204
11337
|
});
|
|
11205
11338
|
if (onDeviceRevoked !== void 0) next.addEventListener("device-revoked", (message) => {
|
|
11339
|
+
if (!current()) return;
|
|
11206
11340
|
const data = message.data;
|
|
11207
11341
|
if (isDeviceRevokedPayload(data)) onDeviceRevoked();
|
|
11208
11342
|
});
|
|
@@ -11210,14 +11344,14 @@ window.__ModuleLoader__.load({
|
|
|
11210
11344
|
if (source !== next) return;
|
|
11211
11345
|
next.close();
|
|
11212
11346
|
source = void 0;
|
|
11213
|
-
if (disposed) return;
|
|
11347
|
+
if (disposed || !enabled) return;
|
|
11214
11348
|
const delay = retryMs;
|
|
11215
11349
|
retryMs = Math.min(3e4, retryMs * 2);
|
|
11216
11350
|
timer = runtime.window.setTimeout(connect, delay);
|
|
11217
11351
|
};
|
|
11218
11352
|
};
|
|
11219
11353
|
const reconnectNow = () => {
|
|
11220
|
-
if (disposed) return;
|
|
11354
|
+
if (disposed || !enabled) return;
|
|
11221
11355
|
source?.close();
|
|
11222
11356
|
source = void 0;
|
|
11223
11357
|
retryMs = 1e3;
|
|
@@ -11225,13 +11359,23 @@ window.__ModuleLoader__.load({
|
|
|
11225
11359
|
};
|
|
11226
11360
|
runtime.window.addEventListener("online", reconnectNow);
|
|
11227
11361
|
connect();
|
|
11228
|
-
|
|
11362
|
+
const stop = () => {
|
|
11229
11363
|
disposed = true;
|
|
11230
11364
|
clearTimer();
|
|
11231
11365
|
source?.close();
|
|
11232
11366
|
source = void 0;
|
|
11233
11367
|
runtime.window.removeEventListener("online", reconnectNow);
|
|
11234
11368
|
};
|
|
11369
|
+
return Object.assign(stop, { setEnabled(value) {
|
|
11370
|
+
if (disposed || value === enabled) return;
|
|
11371
|
+
enabled = value;
|
|
11372
|
+
if (value) connect();
|
|
11373
|
+
else {
|
|
11374
|
+
clearTimer();
|
|
11375
|
+
source?.close();
|
|
11376
|
+
source = void 0;
|
|
11377
|
+
}
|
|
11378
|
+
} });
|
|
11235
11379
|
}
|
|
11236
11380
|
/** Keep at most one activation in flight per id and commit only its latest generation. */
|
|
11237
11381
|
var PerIdActivationLifecycle = class {
|
|
@@ -11359,7 +11503,10 @@ window.__ModuleLoader__.load({
|
|
|
11359
11503
|
});
|
|
11360
11504
|
}
|
|
11361
11505
|
};
|
|
11506
|
+
/** Install authenticated mobile customization refresh, retaining loaded legacy assets through temporary failures. */
|
|
11362
11507
|
function installCustomAssets() {
|
|
11508
|
+
const reporter = createMobileAssetLoadReporter(selectedMobileControlLocale);
|
|
11509
|
+
const customizationOwner = ownsMobileCustomization(document.querySelector("meta[name=\"dsh-mobile-gateway\"][content=\"authenticated\"]") !== null, window.__DSH_MOBILE_FRONTEND__);
|
|
11363
11510
|
const legacyStyle = element("style");
|
|
11364
11511
|
legacyStyle.dataset.plugin = "dsh-mobile-custom";
|
|
11365
11512
|
document.head.append(legacyStyle);
|
|
@@ -11384,6 +11531,16 @@ window.__ModuleLoader__.load({
|
|
|
11384
11531
|
const managedDefinitionIds = /* @__PURE__ */ new Set();
|
|
11385
11532
|
let manifestEtag = "";
|
|
11386
11533
|
let disposed = false;
|
|
11534
|
+
let events;
|
|
11535
|
+
const failed = (reason, signal) => {
|
|
11536
|
+
if (disposed || signal.aborted) return;
|
|
11537
|
+
reporter.fail(reason, signal);
|
|
11538
|
+
if (reason === "authentication_required") events?.setEnabled(false);
|
|
11539
|
+
};
|
|
11540
|
+
const unavailable = (response, signal, fallback) => {
|
|
11541
|
+
failed(response.status === 401 || response.status === 403 ? "authentication_required" : fallback, signal);
|
|
11542
|
+
response.body?.cancel().catch((error) => {});
|
|
11543
|
+
};
|
|
11387
11544
|
let expectedDefinitionId;
|
|
11388
11545
|
const SURFACE_HOST_STYLES = {
|
|
11389
11546
|
"sidebar-action": "position:fixed;z-index:1100;top:calc(env(safe-area-inset-top) + 8px);left:8px;display:flex;flex-direction:column;gap:6px;pointer-events:none",
|
|
@@ -11421,6 +11578,16 @@ window.__ModuleLoader__.load({
|
|
|
11421
11578
|
const stopNativeBack = installMobileNativeBack(window, document, () => {
|
|
11422
11579
|
toast(mobileBackBlockedMessage(selectedMobileControlLocale()));
|
|
11423
11580
|
});
|
|
11581
|
+
if (!customizationOwner) {
|
|
11582
|
+
reporter.fail("gateway_required");
|
|
11583
|
+
return () => {
|
|
11584
|
+
disposed = true;
|
|
11585
|
+
reporter.dispose();
|
|
11586
|
+
stopNativeBack();
|
|
11587
|
+
legacyStyle.remove();
|
|
11588
|
+
document.querySelector("[data-dsh-mobile-extension-layer]")?.remove();
|
|
11589
|
+
};
|
|
11590
|
+
}
|
|
11424
11591
|
const materializeNativeFile = (value) => {
|
|
11425
11592
|
if (typeof value !== "object" || value === null || !("base64" in value) || !("name" in value)) return value;
|
|
11426
11593
|
const candidate = value;
|
|
@@ -11627,10 +11794,13 @@ window.__ModuleLoader__.load({
|
|
|
11627
11794
|
signal
|
|
11628
11795
|
});
|
|
11629
11796
|
if (response.status === 304) return true;
|
|
11630
|
-
if (!response.ok)
|
|
11797
|
+
if (!response.ok) {
|
|
11798
|
+
unavailable(response, signal, "resource_unavailable");
|
|
11799
|
+
return false;
|
|
11800
|
+
}
|
|
11631
11801
|
const nextEtag = response.headers.get("etag") ?? "";
|
|
11632
11802
|
const nextModified = response.headers.get("last-modified") ?? "";
|
|
11633
|
-
const next = await response
|
|
11803
|
+
const next = await readMobileAssetText(response, signal, LEGACY_CUSTOM_ASSET_LIMIT);
|
|
11634
11804
|
if (refreshAborted(signal)) return false;
|
|
11635
11805
|
if (next === legacySource) {
|
|
11636
11806
|
legacyJsEtag = nextEtag;
|
|
@@ -11686,6 +11856,7 @@ window.__ModuleLoader__.load({
|
|
|
11686
11856
|
} catch {
|
|
11687
11857
|
pendingRoot?.remove();
|
|
11688
11858
|
legacyMount = previousMount;
|
|
11859
|
+
failed("resource_unavailable", signal);
|
|
11689
11860
|
return false;
|
|
11690
11861
|
}
|
|
11691
11862
|
};
|
|
@@ -11723,16 +11894,40 @@ window.__ModuleLoader__.load({
|
|
|
11723
11894
|
headers,
|
|
11724
11895
|
signal
|
|
11725
11896
|
});
|
|
11897
|
+
if (disposed || signal.aborted) {
|
|
11898
|
+
response.body?.cancel().catch((error) => {});
|
|
11899
|
+
return false;
|
|
11900
|
+
}
|
|
11726
11901
|
if (response.status === 404) {
|
|
11902
|
+
unavailable(response, signal, "manifest_unavailable");
|
|
11727
11903
|
legacyScriptRevision = "";
|
|
11728
11904
|
legacyStyleRevision = "";
|
|
11729
|
-
|
|
11905
|
+
if (!await handleMissingExtensionManifest(clearManifestExtensions, () => Promise.all([refreshLegacy(signal), refreshCssLegacy(legacyStyle, signal, legacyCssState, unavailable)]), signal)) failed("resource_unavailable", signal);
|
|
11906
|
+
return false;
|
|
11907
|
+
}
|
|
11908
|
+
if (response.status === 304) {
|
|
11909
|
+
if (!signal.aborted) events?.setEnabled(true);
|
|
11910
|
+
return true;
|
|
11911
|
+
}
|
|
11912
|
+
if (!response.ok) {
|
|
11913
|
+
unavailable(response, signal, "manifest_unavailable");
|
|
11914
|
+
return false;
|
|
11730
11915
|
}
|
|
11731
|
-
if (response.status === 304) return true;
|
|
11732
|
-
if (!response.ok) return false;
|
|
11733
11916
|
const nextManifestEtag = response.headers.get("etag") ?? "";
|
|
11734
|
-
const
|
|
11735
|
-
|
|
11917
|
+
const manifestSource = await readMobileAssetText(response, signal, void 0);
|
|
11918
|
+
let payload;
|
|
11919
|
+
try {
|
|
11920
|
+
payload = parseMobileExtensionManifest(JSON.parse(manifestSource));
|
|
11921
|
+
} catch {
|
|
11922
|
+
failed("manifest_invalid", signal);
|
|
11923
|
+
return false;
|
|
11924
|
+
}
|
|
11925
|
+
if (refreshAborted(signal)) return false;
|
|
11926
|
+
if (payload === void 0) {
|
|
11927
|
+
failed("manifest_invalid", signal);
|
|
11928
|
+
return false;
|
|
11929
|
+
}
|
|
11930
|
+
events?.setEnabled(true);
|
|
11736
11931
|
const entries = payload.extensions;
|
|
11737
11932
|
const seen = new Set(entries.map((entry) => entry.id));
|
|
11738
11933
|
const scriptRevision = payload.legacy.scriptRevision;
|
|
@@ -11743,8 +11938,11 @@ window.__ModuleLoader__.load({
|
|
|
11743
11938
|
else refreshComplete = false;
|
|
11744
11939
|
}
|
|
11745
11940
|
if (styleRevision === "" || styleRevision !== legacyStyleRevision) {
|
|
11746
|
-
if (await refreshCssLegacy(legacyStyle, signal, legacyCssState)) legacyStyleRevision = styleRevision;
|
|
11747
|
-
else
|
|
11941
|
+
if (await refreshCssLegacy(legacyStyle, signal, legacyCssState, unavailable)) legacyStyleRevision = styleRevision;
|
|
11942
|
+
else {
|
|
11943
|
+
failed("resource_unavailable", signal);
|
|
11944
|
+
refreshComplete = false;
|
|
11945
|
+
}
|
|
11748
11946
|
}
|
|
11749
11947
|
const commitStyle = (id, change, css, etag) => {
|
|
11750
11948
|
if (change === "retain") return;
|
|
@@ -11786,9 +11984,12 @@ window.__ModuleLoader__.load({
|
|
|
11786
11984
|
signal
|
|
11787
11985
|
});
|
|
11788
11986
|
if (cssResponse.status !== 304) {
|
|
11789
|
-
if (!cssResponse.ok)
|
|
11987
|
+
if (!cssResponse.ok) {
|
|
11988
|
+
unavailable(cssResponse, signal, "resource_unavailable");
|
|
11989
|
+
throw new Error("mobile extension style failed to load");
|
|
11990
|
+
}
|
|
11790
11991
|
pendingStyleEtag = cssResponse.headers.get("etag") ?? void 0;
|
|
11791
|
-
pendingCss = await cssResponse.
|
|
11992
|
+
pendingCss = await readMobileAssetText(cssResponse, signal, EXTENSION_LIMITS.css);
|
|
11792
11993
|
styleChange = "replace";
|
|
11793
11994
|
if (refreshAborted(signal)) return false;
|
|
11794
11995
|
}
|
|
@@ -11815,9 +12016,12 @@ window.__ModuleLoader__.load({
|
|
|
11815
12016
|
let nextDigest;
|
|
11816
12017
|
let nextEtag;
|
|
11817
12018
|
if (scriptResponse.status !== 304) {
|
|
11818
|
-
if (!scriptResponse.ok)
|
|
12019
|
+
if (!scriptResponse.ok) {
|
|
12020
|
+
unavailable(scriptResponse, signal, "resource_unavailable");
|
|
12021
|
+
throw new Error("mobile extension script failed to load");
|
|
12022
|
+
}
|
|
11819
12023
|
nextEtag = scriptResponse.headers.get("etag") ?? void 0;
|
|
11820
|
-
const source = await scriptResponse.
|
|
12024
|
+
const source = await readMobileAssetText(scriptResponse, signal, EXTENSION_LIMITS.script);
|
|
11821
12025
|
if (refreshAborted(signal)) return false;
|
|
11822
12026
|
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(source));
|
|
11823
12027
|
if (refreshAborted(signal)) return false;
|
|
@@ -11871,6 +12075,7 @@ window.__ModuleLoader__.load({
|
|
|
11871
12075
|
failClosedExtensionGenerationReplacement(hadActiveGeneration, previousHostGeneration, entry.generation, () => {
|
|
11872
12076
|
disposeManifestExtension(entry.id);
|
|
11873
12077
|
});
|
|
12078
|
+
failed("resource_unavailable", signal);
|
|
11874
12079
|
refreshComplete = false;
|
|
11875
12080
|
}
|
|
11876
12081
|
}
|
|
@@ -11881,13 +12086,17 @@ window.__ModuleLoader__.load({
|
|
|
11881
12086
|
} else manifestEtag = "";
|
|
11882
12087
|
return refreshComplete;
|
|
11883
12088
|
} catch {
|
|
12089
|
+
failed("refresh_failed", signal);
|
|
11884
12090
|
return false;
|
|
11885
12091
|
}
|
|
11886
12092
|
};
|
|
11887
12093
|
started = true;
|
|
11888
12094
|
for (const definition of definitions.values()) activateDefinition(definition);
|
|
11889
12095
|
const stopRefresh = startLifecycleRefreshScheduler(async (signal) => {
|
|
11890
|
-
await refreshExtensions(signal)
|
|
12096
|
+
if (await refreshExtensions(signal) && !disposed && !signal.aborted) {
|
|
12097
|
+
reporter.recover(signal);
|
|
12098
|
+
events?.setEnabled(true);
|
|
12099
|
+
}
|
|
11891
12100
|
});
|
|
11892
12101
|
const stopEvents = startExtensionChangeStream(() => {
|
|
11893
12102
|
stopRefresh.refresh();
|
|
@@ -11905,9 +12114,11 @@ window.__ModuleLoader__.load({
|
|
|
11905
12114
|
});
|
|
11906
12115
|
}, () => {
|
|
11907
12116
|
fireDeviceRevoked();
|
|
11908
|
-
});
|
|
12117
|
+
}, false);
|
|
12118
|
+
events = stopEvents;
|
|
11909
12119
|
return () => {
|
|
11910
12120
|
disposed = true;
|
|
12121
|
+
reporter.dispose();
|
|
11911
12122
|
stopNativeBack();
|
|
11912
12123
|
stopEvents();
|
|
11913
12124
|
stopRefresh();
|
|
@@ -11926,7 +12137,7 @@ window.__ModuleLoader__.load({
|
|
|
11926
12137
|
else window.dshMobile = previous;
|
|
11927
12138
|
};
|
|
11928
12139
|
}
|
|
11929
|
-
async function refreshCssLegacy(style, signal, state) {
|
|
12140
|
+
async function refreshCssLegacy(style, signal, state, unavailable) {
|
|
11930
12141
|
try {
|
|
11931
12142
|
const headers = {};
|
|
11932
12143
|
if (state.etag !== "") headers["if-none-match"] = state.etag;
|
|
@@ -11950,13 +12161,14 @@ window.__ModuleLoader__.load({
|
|
|
11950
12161
|
if (response.ok) {
|
|
11951
12162
|
const nextEtag = response.headers.get("etag") ?? "";
|
|
11952
12163
|
const nextModified = response.headers.get("last-modified") ?? "";
|
|
11953
|
-
const css = await response
|
|
12164
|
+
const css = await readMobileAssetText(response, signal, LEGACY_CUSTOM_ASSET_LIMIT);
|
|
11954
12165
|
if (refreshAborted(signal)) return false;
|
|
11955
12166
|
style.textContent = css;
|
|
11956
12167
|
state.etag = nextEtag;
|
|
11957
12168
|
state.modified = nextModified;
|
|
11958
12169
|
return true;
|
|
11959
12170
|
}
|
|
12171
|
+
unavailable(response, signal, "resource_unavailable");
|
|
11960
12172
|
return false;
|
|
11961
12173
|
} catch {
|
|
11962
12174
|
return false;
|
|
@@ -12010,11 +12222,13 @@ window.__ModuleLoader__.load({
|
|
|
12010
12222
|
}, "dsh-mobile: authenticated gateway client trust");
|
|
12011
12223
|
ctx.effect(() => {
|
|
12012
12224
|
const desktopAdmin = isDesktopAdminSurface(location.hostname, location.search, window.__DSH_MOBILE_FRONTEND__, location.protocol);
|
|
12225
|
+
const gatewayCustomization = ownsMobileCustomization(document.querySelector("meta[name=\"dsh-mobile-gateway\"][content=\"authenticated\"]") !== null, window.__DSH_MOBILE_FRONTEND__);
|
|
12013
12226
|
const style = element("style");
|
|
12014
12227
|
style.dataset.plugin = "dsh-mobile";
|
|
12015
12228
|
style.textContent = desktopAdmin ? CONTROL_STYLES : NATIVE_MOBILE_STYLES;
|
|
12016
12229
|
style.textContent += CLIENT_MODULE_STYLES;
|
|
12017
12230
|
document.head.append(style);
|
|
12231
|
+
const removeCustom = !desktopAdmin || gatewayCustomization ? installCustomAssets() : () => void 0;
|
|
12018
12232
|
const removeVoiceSession = installVoiceSession(!desktopAdmin);
|
|
12019
12233
|
const removeModuleSettings = ctx.slots.inject("settings.general.item", () => ctx.slots.register({
|
|
12020
12234
|
name: "settings.general.item",
|
|
@@ -12058,7 +12272,6 @@ window.__ModuleLoader__.load({
|
|
|
12058
12272
|
removeFontSize();
|
|
12059
12273
|
};
|
|
12060
12274
|
});
|
|
12061
|
-
const removeCustom = installCustomAssets();
|
|
12062
12275
|
const removeSurface = installDshLanguageBoundSurface(() => installNativeMobileSurface({
|
|
12063
12276
|
getLayout: () => ctx.get("layout"),
|
|
12064
12277
|
getSidebarRight: () => ctx.get("sidebarRight")
|
|
@@ -12118,6 +12331,7 @@ window.__ModuleLoader__.load({
|
|
|
12118
12331
|
disposeClientModuleDialogs();
|
|
12119
12332
|
removeModuleSettings();
|
|
12120
12333
|
removeControl();
|
|
12334
|
+
removeCustom();
|
|
12121
12335
|
removeVoiceSession();
|
|
12122
12336
|
style.remove();
|
|
12123
12337
|
};
|
|
@@ -12151,6 +12365,7 @@ window.__ModuleLoader__.load({
|
|
|
12151
12365
|
exports.frpAttachFormErrorCode = frpAttachFormErrorCode;
|
|
12152
12366
|
exports.handleMissingExtensionManifest = handleMissingExtensionManifest;
|
|
12153
12367
|
exports.inject = inject;
|
|
12368
|
+
exports.installCustomAssets = installCustomAssets;
|
|
12154
12369
|
exports.installDshLanguageBoundSurface = installDshLanguageBoundSurface;
|
|
12155
12370
|
exports.installMobileNativeBack = installMobileNativeBack;
|
|
12156
12371
|
exports.mobileBackBlockedMessage = mobileBackBlockedMessage;
|