Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for iOS 12.2 #118

Merged
merged 2 commits into from
Mar 15, 2019
Merged

Add support for iOS 12.2 #118

merged 2 commits into from
Mar 15, 2019

Conversation

imurchie
Copy link
Contributor

The problem: In iOS 12.2 the remote debugger stopped working, because instead of using the entire protocol, all communication is now wrapped in Target.sendMessageToTarget commands and Target.dispatchMessageFromTarget messages (which prior to iOS 12.2 were not known at all by Safari).

This PR implements, for iOS 12.2, this protocol change.

As I worked on this I also cleaned some stuff up, which muddled the diffs a bit, for which I apologize.

Confirmation that this works through real functional tests (with some necessary changes at the driver level):

This works for simulators only. Beginning work on real device integration.

Re: appium/appium#12239 and appium/appium#12240

lib/helpers.js Outdated Show resolved Hide resolved
handleMessage (plist) {
let handlerFor = plist.__selector;
if (!handlerFor) {
async handleMessage (plist) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have you verified this method is called with await everywhere now?

let method = dataKey.method;
let params;
if (this.targetBased) {
if (method === 'Target.targetCreated') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather move this code into a separate method. The current one is already quite long

export default class RemoteDebuggerRpcClient {
constructor (opts = {}) {
const {
let {
platformVersion = {},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are currently not getting xcode version for real devices, because it might not be installed on the target machine. Do we want to change that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not want to change that. It limits how iOS real device testing can be done.

But in any case we will have a platformVersion, which is what we depend on (since iOS below 12.2, but still Xcode 10.2, continues to use the old mechanism).

data.__argument.WIRSocketDataKey.id = this.curMsgId;
data.__argument.WIRSocketDataKey =
Buffer.from(JSON.stringify(data.__argument.WIRSocketDataKey));
if (cmd.__argument.WIRSocketDataKey.params) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hell it's full of magic

return command('Page.navigate', {url}, appIdKey, connId,
senderId, pageIdKey, debuggerType);
}
indicateWebView (connId, appIdKey, pageIdKey, opts) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opts = {}

*/

command (method, params, appIdKey, connId, senderId, pageIdKey, debuggerType) {
if (debuggerType !== null && debuggerType === DEBUGGER_TYPES.webkit) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debuggerType !== null might be skipped

command (method, params, appIdKey, connId, senderId, pageIdKey, debuggerType) {
if (debuggerType !== null && debuggerType === DEBUGGER_TYPES.webkit) {
return this.commandWebKit(method, params);
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else is redundant

}

return cmd;
getRemoteCommand (command, opts) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opts = {}

case 'indicateWebView':
cmd = this.indicateWebView(connId, appIdKey, pageIdKey, opts);
break;
case 'sendJSCommand':
Copy link
Contributor

@mykola-mokhnach mykola-mokhnach Mar 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cannot we simply call this[command](...) for all the other commands with equal arguments?

@mykola-mokhnach
Copy link
Contributor

it might be a good idea to add iOS 12.2 to Travis

@imurchie
Copy link
Contributor Author

The build for this package does not actually depend on Xcode at all. It is entirely through a test server we built. This should be changed, but it outside the scope of this work (mostly because it is a huge task).

// pageDict is a promise, so resolve
this.appDict[appIdKey].pageDict.resolve(pageArray);
if (this.appDict[appIdKey].pageArray) {
if (this.appDict[appIdKey].pageArray.resolve) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isFunction ?

if (result.result && result.result.value) {
result = result.result.value;
}
this.dataHandlers[msgId](result);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are always regular functions.

logFullMessage (plist) {
// Buffers cannot be serialized in a readable way
const bufferToJSON = Buffer.prototype.toJSON;
delete Buffer.prototype.toJSON;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting hack %)

if (this.appDict[appIdKey].pageArray) {
if (this.appDict[appIdKey].pageArray.resolve) {
// pageDict is a pending promise, so resolve
this.appDict[appIdKey].pageArray.resolve();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolve is just a function. The promise itself it awaited elsewhere (or has already timed out).

@imurchie imurchie merged commit 31739b4 into master Mar 15, 2019
@imurchie imurchie deleted the isaac-12.2 branch March 15, 2019 11:49
Copy link
Member

@jlipps jlipps left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is pretty massive, thanks @imurchie!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants