in src/debugger/cordovaDebugSession.ts [737:860]
private attachIos(attachArgs: ICordovaAttachRequestArgs): Promise<ICordovaAttachRequestArgs> {
let target = attachArgs.target.toLowerCase() === TargetType.Emulator ? TargetType.Emulator : attachArgs.target;
let workingDirectory = attachArgs.cwd;
const command = CordovaProjectHelper.getCliCommand(workingDirectory);
// TODO add env support for attach
const env = CordovaProjectHelper.getEnvArgument(attachArgs);
return this.checkIfTargetIsiOSSimulator(target, command, env, workingDirectory).then(() => {
attachArgs.webkitRangeMin = attachArgs.webkitRangeMin || 9223;
attachArgs.webkitRangeMax = attachArgs.webkitRangeMax || 9322;
attachArgs.attachAttempts = attachArgs.attachAttempts || 20;
attachArgs.attachDelay = attachArgs.attachDelay || 1000;
// Start the tunnel through to the webkit debugger on the device
this.outputLogger("Configuring debugging proxy");
const retry = function <T>(func, condition, retryCount, cancellationToken): Promise<T> {
return retryAsync(func, condition, retryCount, 1, attachArgs.attachDelay, localize("UnableToFindWebview", "Unable to find Webview"), cancellationToken);
};
const getBundleIdentifier = () => {
if (attachArgs.target.toLowerCase() === TargetType.Device) {
return CordovaIosDeviceLauncher.getBundleIdentifier(attachArgs.cwd)
.then(CordovaIosDeviceLauncher.getPathOnDevice);
} else {
return fs.promises.readdir(path.join(attachArgs.cwd, "platforms", "ios", "build", "emulator")).then((entries: string[]) => {
// TODO requires changes in case of implementing debugging on iOS simulators
let filtered = entries.filter((entry) => /\.app$/.test(entry));
if (filtered.length > 0) {
return filtered[0];
} else {
throw new Error(localize("UnableToFindAppFile", "Unable to find .app file"));
}
});
}
};
const getSimulatorProxyPort = (iOSAppPackagePath): Promise<{ iOSAppPackagePath: string, targetPort: number, iOSVersion: string }> => {
return promiseGet(`http://localhost:${attachArgs.port}/json`, localize("UnableToCommunicateWithiOSWebkitDebugProxy", "Unable to communicate with ios_webkit_debug_proxy")).then((response: string) => {
try {
// An example of a json response from IWDP
// [{
// "deviceId": "00008020-XXXXXXXXXXXXXXXX",
// "deviceName": "iPhone name",
// "deviceOSVersion": "13.4.1",
// "url": "localhost:9223"
// }]
let endpointsList = JSON.parse(response);
let devices = endpointsList.filter((entry) =>
attachArgs.target.toLowerCase() === TargetType.Device ? entry.deviceId !== "SIMULATOR"
: entry.deviceId === "SIMULATOR"
);
let device = devices[0];
// device.url is of the form 'localhost:port'
return {
iOSAppPackagePath,
targetPort: parseInt(device.url.split(":")[1], 10),
iOSVersion: device.deviceOSVersion,
};
} catch (e) {
throw new Error(localize("UnableToFindiOSTargetDeviceOrSimulator", "Unable to find iOS target device/simulator. Please check that \"Settings > Safari > Advanced > Web Inspector = ON\" or try specifying a different \"port\" parameter in launch.json"));
}
});
};
const getWebSocketDebuggerUrl = ({ iOSAppPackagePath, targetPort, iOSVersion }): Promise<IOSProcessedParams> => {
return retry(() =>
promiseGet(`http://localhost:${targetPort}/json`, localize("UnableToCommunicateWithTarget", "Unable to communicate with target"))
.then((response: string) => {
try {
// An example of a json response from IWDP
// [{
// "devtoolsFrontendUrl": "",
// "faviconUrl": "",
// "thumbnailUrl": "/thumb/ionic://localhost/tabs/tab1",
// "title": "Ionic App",
// "url": "ionic://localhost/tabs/tab1",
// "webSocketDebuggerUrl": "ws://localhost:9223/devtools/page/1",
// "appId": "PID:37819"
// }]
const webviewsList: Array<WebviewData> = JSON.parse(response);
if (webviewsList.length === 0) {
throw new Error(localize("UnableToFindTargetApp", "Unable to find target app"));
}
const cordovaWebview = this.getCordovaWebview(webviewsList, iOSAppPackagePath, !!attachArgs.ionicLiveReload);
if (!cordovaWebview.webSocketDebuggerUrl) {
throw new Error(localize("WebsocketDebuggerUrlIsEmpty", "WebSocket Debugger Url is empty"));
}
let ionicDevServerUrl;
if (this.ionicDevServerUrls) {
ionicDevServerUrl = this.ionicDevServerUrls.find(url => cordovaWebview.url.indexOf(url) === 0);
}
return {
webSocketDebuggerUrl: cordovaWebview.webSocketDebuggerUrl,
iOSVersion,
iOSAppPackagePath,
ionicDevServerUrl,
};
} catch (e) {
throw new Error(localize("UnableToFindTargetApp", "Unable to find target app"));
}
}),
(result) => !!result,
5,
this.cancellationTokenSource.token
);
};
const getAttachRequestArgs = (): Promise<ICordovaAttachRequestArgs> =>
CordovaIosDeviceLauncher.startWebkitDebugProxy(attachArgs.port, attachArgs.webkitRangeMin, attachArgs.webkitRangeMax)
.then(getBundleIdentifier)
.then(getSimulatorProxyPort)
.then(getWebSocketDebuggerUrl)
.then((iOSProcessedParams: IOSProcessedParams) => {
attachArgs.webSocketDebuggerUrl = iOSProcessedParams.webSocketDebuggerUrl;
attachArgs.iOSVersion = iOSProcessedParams.iOSVersion;
attachArgs.iOSAppPackagePath = iOSProcessedParams.iOSAppPackagePath;
if (iOSProcessedParams.ionicDevServerUrl) {
attachArgs.devServerAddress = url.parse(iOSProcessedParams.ionicDevServerUrl).hostname;
}
return attachArgs;
});
return retry(getAttachRequestArgs, () => true, attachArgs.attachAttempts, this.cancellationTokenSource.token);
});
}