You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
7.9 KiB

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getConnectedDevices = getConnectedDevices;
exports.isEnabled = isEnabled;
exports.runOnDevice = runOnDevice;
function _debug() {
const data = _interopRequireDefault(require("debug"));
_debug = function () {
return data;
};
return data;
}
function _fs() {
const data = require("fs");
_fs = function () {
return data;
};
return data;
}
function _getenv() {
const data = require("getenv");
_getenv = function () {
return data;
};
return data;
}
function path() {
const data = _interopRequireWildcard(require("path"));
path = function () {
return data;
};
return data;
}
function _lib() {
const data = require("./native-run/ios/lib");
_lib = function () {
return data;
};
return data;
}
function _xcode() {
const data = require("./native-run/ios/utils/xcode");
_xcode = function () {
return data;
};
return data;
}
function _process() {
const data = require("./native-run/utils/process");
_process = function () {
return data;
};
return data;
}
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const EXPO_USE_APPLE_DEVICE = (0, _getenv().boolish)('EXPO_USE_APPLE_DEVICE', false);
const debug = (0, _debug().default)('expo:xdl:ios:utils:device');
function isEnabled() {
return EXPO_USE_APPLE_DEVICE;
}
async function getConnectedDevices() {
const usbmuxClient = new (_lib().UsbmuxdClient)(_lib().UsbmuxdClient.connectUsbmuxdSocket());
const usbmuxDevices = await usbmuxClient.getDevices();
usbmuxClient.socket.end();
return Promise.all(usbmuxDevices.map(async d => {
const socket = await new (_lib().UsbmuxdClient)(_lib().UsbmuxdClient.connectUsbmuxdSocket()).connect(d, 62078);
const device = await new (_lib().LockdowndClient)(socket).getAllValues();
socket.end();
return device;
}));
}
async function runOnDevice({
udid,
appPath,
bundleId,
waitForApp,
deltaPath,
onProgress
}) {
const clientManager = await _lib().ClientManager.create(udid);
try {
await mountDeveloperDiskImage(clientManager);
const packageName = path().basename(appPath);
const destPackagePath = path().join('PublicStaging', packageName);
await uploadApp(clientManager, appPath, destPackagePath);
const installer = await clientManager.getInstallationProxyClient();
await installer.installApp(destPackagePath, bundleId, {
// https://github.com/ios-control/ios-deploy/blob/0f2ffb1e564aa67a2dfca7cdf13de47ce489d835/src/ios-deploy/ios-deploy.m#L2491-L2508
ApplicationsType: 'Any',
CFBundleIdentifier: bundleId,
CloseOnInvalidate: '1',
InvalidateOnDetach: '1',
IsUserInitiated: '1',
// Disable checking for wifi devices, this is nominally faster.
PreferWifi: '0',
// Only info I could find on these:
// https://github.com/wwxxyx/Quectel_BG96/blob/310876f90fc1093a59e45e381160eddcc31697d0/Apple_Homekit/homekit_certification_tools/ATS%206/ATS%206/ATS.app/Contents/Frameworks/CaptureKit.framework/Versions/A/Resources/MobileDevice/MobileInstallation.h#L112-L121
PackageType: 'Developer',
ShadowParentKey: deltaPath
// SkipUninstall: '1'
}, onProgress);
const {
[bundleId]: appInfo
} = await installer.lookupApp([bundleId]);
// launch fails with EBusy or ENotFound if you try to launch immediately after install
await (0, _process().wait)(200);
const debugServerClient = await launchApp(clientManager, {
appInfo,
detach: !waitForApp
});
if (waitForApp) {
(0, _process().onBeforeExit)(async () => {
// causes continue() to return
debugServerClient.halt();
// give continue() time to return response
await (0, _process().wait)(64);
});
debug(`Waiting for app to close...\n`);
const result = await debugServerClient.continue();
// TODO: I have no idea what this packet means yet (successful close?)
// if not a close (ie, most likely due to halt from onBeforeExit), then kill the app
if (result !== 'W00') {
await debugServerClient.kill();
}
}
} finally {
clientManager.end();
}
}
async function mountDeveloperDiskImage(clientManager) {
const imageMounter = await clientManager.getMobileImageMounterClient();
// Check if already mounted. If not, mount.
if (!(await imageMounter.lookupImage()).ImageSignature) {
// verify DeveloperDiskImage exists (TODO: how does this work on Windows/Linux?)
// TODO: if windows/linux, download?
const version = await (await clientManager.getLockdowndClient()).getValue('ProductVersion');
const developerDiskImagePath = await (0, _xcode().getDeveloperDiskImagePath)(version);
const developerDiskImageSig = (0, _fs().readFileSync)(`${developerDiskImagePath}.signature`);
await imageMounter.uploadImage(developerDiskImagePath, developerDiskImageSig);
await imageMounter.mountImage(developerDiskImagePath, developerDiskImageSig);
}
}
async function uploadApp(clientManager, srcPath, destinationPath) {
const afcClient = await clientManager.getAFCClient();
try {
await afcClient.getFileInfo('PublicStaging');
} catch (err) {
if (err instanceof _lib().AFCError && err.status === _lib().AFC_STATUS.OBJECT_NOT_FOUND) {
await afcClient.makeDirectory('PublicStaging');
} else {
throw err;
}
}
await afcClient.uploadDirectory(srcPath, destinationPath);
}
async function launchApp(clientManager, {
appInfo,
detach
}) {
let tries = 0;
while (tries < 3) {
const debugServerClient = await clientManager.getDebugserverClient();
await debugServerClient.setMaxPacketSize(1024);
await debugServerClient.setWorkingDir(appInfo.Container);
await debugServerClient.launchApp(appInfo.Path, appInfo.CFBundleExecutable);
const result = await debugServerClient.checkLaunchSuccess();
if (result === 'OK') {
if (detach) {
// https://github.com/libimobiledevice/libimobiledevice/blob/25059d4c7d75e03aab516af2929d7c6e6d4c17de/tools/idevicedebug.c#L455-L464
const res = await debugServerClient.sendCommand('D', []);
debug('Disconnect from debug server request:', res);
if (res !== 'OK') {
console.warn('Something went wrong while attempting to disconnect from iOS debug server, you may need to reopen the app manually.');
}
}
return debugServerClient;
} else if (result === 'EBusy' || result === 'ENotFound') {
debug('Device busy or app not found, trying to launch again in .5s...');
tries++;
debugServerClient.socket.end();
await (0, _process().wait)(500);
} else {
throw new Error(`There was an error launching app: ${result}`);
}
}
throw new Error('Unable to launch app, number of tries exceeded');
}
//# sourceMappingURL=AppleDevice.js.map