diff --git a/code/code.go b/code/code.go index 54da9ae0..96ef4826 100644 --- a/code/code.go +++ b/code/code.go @@ -66,18 +66,19 @@ var ( // device related: [50, 70) var ( - DeviceConnectionError = errors.New("device general connection error") // 50 - DeviceHTTPDriverError = errors.New("device HTTP driver error") // 51 - DeviceUSBDriverError = errors.New("device USB driver error") // 52 - DeviceAppNotInstalled = errors.New("device app not installed") // 59 - DeviceGetInfoError = errors.New("device get info error") // 60 - DeviceConfigureError = errors.New("device configure error") // 61 - DeviceShellExecError = errors.New("device shell exec error") // 62 - DeviceOfflineError = errors.New("device offline") // 63 - DeviceInstallFailed = errors.New("device install app failed") // 64 - DeviceScreenShotError = errors.New("device screenshot error") // 65 - DeviceCaptureLogError = errors.New("device capture log error") // 66 - DeviceUIResponseSlow = errors.New("device UI response slow") // 67 + DeviceConnectionError = errors.New("device general connection error") // 50 + DeviceHTTPDriverError = errors.New("device HTTP driver error") // 51 + DeviceUSBDriverError = errors.New("device USB driver error") // 52 + DeviceUntrustedCertError = errors.New("device app certificate not trusted") // 53 + DeviceAppNotInstalled = errors.New("device app not installed") // 59 + DeviceGetInfoError = errors.New("device get info error") // 60 + DeviceConfigureError = errors.New("device configure error") // 61 + DeviceShellExecError = errors.New("device shell exec error") // 62 + DeviceOfflineError = errors.New("device offline") // 63 + DeviceInstallFailed = errors.New("device install app failed") // 64 + DeviceScreenShotError = errors.New("device screenshot error") // 65 + DeviceCaptureLogError = errors.New("device capture log error") // 66 + DeviceUIResponseSlow = errors.New("device UI response slow") // 67 ) // UI automation related: [70, 80) @@ -176,18 +177,20 @@ var errorsMap = map[error]int{ UploadFailed: 49, // device related - DeviceConnectionError: 50, - DeviceHTTPDriverError: 51, - DeviceUSBDriverError: 52, - DeviceAppNotInstalled: 59, - DeviceGetInfoError: 60, - DeviceConfigureError: 61, - DeviceShellExecError: 62, - DeviceOfflineError: 63, - DeviceInstallFailed: 64, - DeviceScreenShotError: 65, - DeviceCaptureLogError: 66, - DeviceUIResponseSlow: 67, + DeviceConnectionError: 50, + DeviceHTTPDriverError: 51, + DeviceUSBDriverError: 52, + DeviceUntrustedCertError: 53, + DeviceAppNotInstalled: 59, + DeviceGetInfoError: 60, + DeviceConfigureError: 61, + DeviceShellExecError: 62, + DeviceOfflineError: 63, + DeviceInstallFailed: 64, + DeviceScreenShotError: 65, + DeviceCaptureLogError: 66, + DeviceUIResponseSlow: 67, + DeviceUntrustedCertError: 68, // UI automation related MobileUIDriverAppNotInstalled: 68, diff --git a/uixt/driver_session.go b/uixt/driver_session.go index fddc04f7..10adbf60 100644 --- a/uixt/driver_session.go +++ b/uixt/driver_session.go @@ -202,8 +202,13 @@ func (s *DriverSession) RequestWithRetry(method string, urlStr string, rawBody [ synthesizeEventRetryAdded = true } - // Notice: use DeviceHTTPDriverError when request driver failed - lastError = errors.Wrap(code.DeviceHTTPDriverError, err.Error()) + // Check if it's already a DeviceOfflineError + if errors.Is(err, code.DeviceOfflineError) { + lastError = err + } else { + // Use DeviceHTTPDriverError for other errors + lastError = errors.Wrap(code.DeviceHTTPDriverError, err.Error()) + } // If this was the last attempt, break if attempt == maxRetry { @@ -294,6 +299,11 @@ func (s *DriverSession) Request(method string, urlStr string, rawBody []byte, op driverResult.RequestTime = time.Now() var resp *http.Response if resp, err = s.client.Do(req); err != nil { + // Check for connection reset or EOF errors and classify as DeviceOfflineError + if strings.Contains(err.Error(), "read: connection reset by peer") || + strings.Contains(err.Error(), "EOF") { + return nil, errors.Wrap(code.DeviceOfflineError, err.Error()) + } return nil, err } defer func() { diff --git a/uixt/ios_driver_wda.go b/uixt/ios_driver_wda.go index 283c5a92..0cb6d668 100644 --- a/uixt/ios_driver_wda.go +++ b/uixt/ios_driver_wda.go @@ -436,6 +436,13 @@ func (wd *WDADriver) AppLaunch(bundleId string) (err error) { // 超时两分钟 _, err = wd.Session.POST(data, "/wings/apps/launch", option.WithTimeout(120)) if err != nil { + // Check for untrusted certificate error + errMsg := err.Error() + if strings.Contains(errMsg, "has not been explicitly trusted by the user") || + strings.Contains(errMsg, "invalid code signature") || + strings.Contains(errMsg, "inadequate entitlements") { + return errors.Wrap(code.DeviceUntrustedCertError, "App certificate not trusted: "+bundleId) + } return errors.Wrap(err, "wda app launch failed") } return nil @@ -443,10 +450,17 @@ func (wd *WDADriver) AppLaunch(bundleId string) (err error) { func (wd *WDADriver) AppLaunchUnattached(bundleId string) (err error) { log.Info().Str("bundleId", bundleId).Msg("WDADriver.AppLaunchUnattached") - // [[FBRoute POST:@"/wda/apps/launchUnattached"].withoutSession respondWithTarget:self action:@selector(handleLaunchUnattachedApp:)] + // [[FBRoute POST:@"/wda/apps/launchUnattached"].withoutSession respondWithTarget:self action:@selector(handleLaunchUnattachedApp:)]] data := map[string]interface{}{"bundleId": bundleId} _, err = wd.Session.POST(data, "/wda/apps/launchUnattached") if err != nil { + // Check for untrusted certificate error + errMsg := err.Error() + if strings.Contains(errMsg, "has not been explicitly trusted by the user") || + strings.Contains(errMsg, "invalid code signature") || + strings.Contains(errMsg, "inadequate entitlements") { + return errors.Wrap(code.DeviceUntrustedCertError, "App certificate not trusted: "+bundleId) + } return errors.Wrap(err, "wda app launchUnattached failed") } return nil