(function () { 'use strict'; /** Orchestration default channel; stable is fallback for promoted releases. */ var OTA_CHANNELS = ['staging', 'stable']; function setStatus(msg) { var el = document.getElementById('hub-download-apk-status'); if (el) { el.textContent = msg; } } function fetchJson(url) { return fetch(url, { cache: 'no-store' }).then(function (r) { if (!r.ok) { throw new Error('HTTP ' + r.status + ' for ' + url); } return r.json(); }); } function resolveApkFromChannel(channelName) { return fetchJson('/v0/ota/channel/' + encodeURIComponent(channelName) + '.json') .then(function (channel) { var manifestUrl = channel && channel.manifestUrl; if (!manifestUrl) { throw new Error(channelName + ' missing manifestUrl'); } return fetchJson(manifestUrl); }) .then(function (manifest) { var url = (manifest && (manifest.browserApkUrl || manifest.apkUrl)) || ''; if (!url) { throw new Error('manifest missing browserApkUrl/apkUrl'); } if (!manifest.browserApkUrl && /\.otapkg(\?|$)/.test(url)) { url = url.replace(/\.otapkg(\?|$)/, '.apk$1'); } var nameMatch = url.match(/\/([^/?#]+\.apk)(?:\?|$)/i); var filename = nameMatch ? nameMatch[1] : 'android_cast-latest.apk'; return { url: url, filename: filename, channel: channelName }; }); } function resolveApkUrl() { var chain = Promise.reject(new Error('no channel')); OTA_CHANNELS.forEach(function (ch) { chain = chain.catch(function () { return resolveApkFromChannel(ch); }); }); return chain; } function triggerDownload(url, filename) { if (/\.apk(\?|$)/i.test(url)) { var a = document.createElement('a'); a.href = url; a.download = filename; a.rel = 'noopener'; document.body.appendChild(a); a.click(); a.remove(); return Promise.resolve(); } return fetch(url, { cache: 'no-store' }) .then(function (r) { if (!r.ok) { throw new Error('download HTTP ' + r.status); } return r.blob(); }) .then(function (blob) { var blobUrl = URL.createObjectURL(blob); var link = document.createElement('a'); link.href = blobUrl; link.download = filename; link.rel = 'noopener'; document.body.appendChild(link); link.click(); link.remove(); setTimeout(function () { URL.revokeObjectURL(blobUrl); }, 60000); }); } function wireApkButton() { var btn = document.getElementById('hub-download-apk'); if (!btn) { return; } btn.addEventListener('click', function () { btn.disabled = true; setStatus('Resolving OTA channel…'); resolveApkUrl() .then(function (resolved) { setStatus('Downloading ' + resolved.filename + ' (' + resolved.channel + ')…'); return triggerDownload(resolved.url, resolved.filename); }) .catch(function (err) { setStatus( 'APK unavailable — run builder with OTA publish (staging). ' + (err.message || err) ); }) .finally(function () { btn.disabled = false; }); }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', wireApkButton); } else { wireApkButton(); } })();