Skip to content

Commit

Permalink
add launch and kill endpoints (#191)
Browse files Browse the repository at this point in the history
  • Loading branch information
shamanec authored Oct 30, 2022
1 parent 3507f94 commit 2df8627
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 4 deletions.
2 changes: 1 addition & 1 deletion restapi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## getting started:
- go install github.com/swaggo/swag/cmd/swag@latest
- swag init
- swag init --parseDependency
- go run main.go

plug an ios device into your machine and test on localhost:8080
Expand Down
124 changes: 122 additions & 2 deletions restapi/api/app_endpoints.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,140 @@
package api

import (
"net/http"

"github.com/danielpaulus/go-ios/ios"
"github.com/danielpaulus/go-ios/ios/installationproxy"
"github.com/danielpaulus/go-ios/ios/instruments"
"github.com/gin-gonic/gin"
"net/http"
)

// List apps on a device
// @Summary List apps on a device
// @Description List the installed apps on a device
// @Tags apps
// @Produce json
// @Success 200 {object} []installationproxy.AppInfo
// @Failure 500 {object} GenericResponse
// @Router /device/{udid}/apps [post]
func ListApps(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)
svc, _ := installationproxy.New(device)
var err error
var response []installationproxy.AppInfo
response, err = svc.BrowseAllApps()
if err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err})
c.JSON(http.StatusInternalServerError, GenericResponse{Error: err.Error()})
}
c.IndentedJSON(http.StatusOK, response)
}

// Launch app on a device
// @Summary Launch app on a device
// @Description Launch app on a device by provided bundleID
// @Tags apps
// @Produce json
// @Param bundleID query string true "bundle identifier of the targeted app"
// @Success 200 {object} GenericResponse
// @Failure 500 {object} GenericResponse
// @Router /device/{udid}/apps/launch [post]
func LaunchApp(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)

bundleID := c.Query("bundleID")
if bundleID == "" {
c.JSON(http.StatusUnprocessableEntity, GenericResponse{Error: "bundleID query param is missing"})
return
}

pControl, err := instruments.NewProcessControl(device)
if err != nil {
c.JSON(http.StatusInternalServerError, GenericResponse{Error: err.Error()})
return
}

_, err = pControl.LaunchApp(bundleID)
if err != nil {
c.JSON(http.StatusInternalServerError, GenericResponse{Error: err.Error()})
return
}

c.JSON(http.StatusOK, GenericResponse{Message: bundleID + " launched successfully"})
}

// Kill running app on a device
// @Summary Kill running app on a device
// @Description Kill running app on a device by provided bundleID
// @Tags apps
// @Produce json
// @Param bundleID query string true "bundle identifier of the targeted app"
// @Success 200 {object} GenericResponse
// @Failure 500 {object} GenericResponse
// @Router /device/{udid}/apps/kill [post]
func KillApp(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)
var processName = ""

bundleID := c.Query("bundleID")
if bundleID == "" {
c.JSON(http.StatusUnprocessableEntity, GenericResponse{Error: "bundleID query param is missing"})
return
}

pControl, err := instruments.NewProcessControl(device)
if err != nil {
c.JSON(http.StatusInternalServerError, GenericResponse{Error: err.Error()})
return
}

svc, err := installationproxy.New(device)
if err != nil {
c.JSON(http.StatusInternalServerError, GenericResponse{Error: err.Error()})
return
}

response, err := svc.BrowseAllApps()
if err != nil {
c.JSON(http.StatusInternalServerError, GenericResponse{Error: err.Error()})
return
}

for _, app := range response {
if app.CFBundleIdentifier == bundleID {
processName = app.CFBundleExecutable
break
}
}

if processName == "" {
c.JSON(http.StatusNotFound, GenericResponse{Message: bundleID + " is not installed"})
return
}

service, err := instruments.NewDeviceInfoService(device)
if err != nil {
c.JSON(http.StatusInternalServerError, GenericResponse{Error: err.Error()})
return
}
defer service.Close()

processList, err := service.ProcessList()
if err != nil {
c.JSON(http.StatusInternalServerError, GenericResponse{Error: err.Error()})
return
}

for _, p := range processList {
if p.Name == processName {
err = pControl.KillProcess(p.Pid)
if err != nil {
c.JSON(http.StatusInternalServerError, GenericResponse{Error: err.Error()})
return
}
c.JSON(http.StatusOK, GenericResponse{Message: bundleID + " successfully killed"})
return
}
}

c.JSON(http.StatusOK, GenericResponse{Message: bundleID + " is not running"})
}
5 changes: 4 additions & 1 deletion restapi/api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ func registerRoutes(router *gin.RouterGroup) {
go reservation.CleanReservationsCRON()
}
func initAppRoutes(group *gin.RouterGroup) {
router := group.Group("/app")
router := group.Group("/apps")
router.GET("/", ListApps)
router.POST("/launch", LaunchApp)
router.POST("/kill", KillApp)
router.Use(LimitNumClientsUDID())
}

func initStreamingResponseRoutes(device *gin.RouterGroup, router *gin.RouterGroup) {
Expand Down

0 comments on commit 2df8627

Please sign in to comment.