From 26293ae3c2a76ac8836bed60c0f4a00820abdbbc Mon Sep 17 00:00:00 2001 From: PJ Date: Mon, 1 Jun 2026 22:38:26 +0530 Subject: [PATCH] refactor(permissions): delete dead internal/permissions package --- internal/permissions/permissions.go | 125 ---------------------- internal/permissions/permissions_test.go | 127 ----------------------- 2 files changed, 252 deletions(-) delete mode 100644 internal/permissions/permissions.go delete mode 100644 internal/permissions/permissions_test.go diff --git a/internal/permissions/permissions.go b/internal/permissions/permissions.go deleted file mode 100644 index dc7c69d..0000000 --- a/internal/permissions/permissions.go +++ /dev/null @@ -1,125 +0,0 @@ -package permissions - -import ( - "context" - "fmt" - "os/exec" - "regexp" - "strings" -) - -// Inspector returns the list of uses-permission entries declared by the APK. -type Inspector func(ctx context.Context, apkPath string) ([]string, error) - -// Granter grants a single permission to the given package on the connected -// device. Implementations typically wrap `adb shell pm grant`. -type Granter func(ctx context.Context, packageName, permission string) error - -// GrantDangerous filters declared permissions to the dangerous set and grants -// each one via the supplied granter. Errors from individual grants are -// collected as warnings rather than aborting — Android refuses to grant -// non-runtime permissions and we prefer to soldier on. -func GrantDangerous( - ctx context.Context, - apkPath, packageName string, - inspector Inspector, - granter Granter, -) (granted []string, warnings []string, err error) { - declared, err := inspector(ctx, apkPath) - if err != nil { - return nil, nil, fmt.Errorf("inspect permissions: %w", err) - } - for _, permission := range declared { - if !IsDangerous(permission) { - continue - } - if err := granter(ctx, packageName, permission); err != nil { - warnings = append(warnings, fmt.Sprintf("%s: %v", permission, err)) - continue - } - granted = append(granted, permission) - } - return granted, warnings, nil -} - -var aaptPermissionPattern = regexp.MustCompile(`uses-permission:\s+name='([^']+)'`) - -// AaptInspector shells out to `aapt dump permissions` to list permissions. -func AaptInspector(ctx context.Context, apkPath string) ([]string, error) { - output, err := exec.CommandContext(ctx, "aapt", "dump", "permissions", apkPath).Output() - if err != nil { - return nil, fmt.Errorf("aapt dump permissions: %w", err) - } - var permissions []string - for _, match := range aaptPermissionPattern.FindAllStringSubmatch(string(output), -1) { - permissions = append(permissions, match[1]) - } - return permissions, nil -} - -// AdbGranter returns a Granter that runs `adb shell pm grant` against the -// supplied device serial (empty = default device). -func AdbGranter(adbPath, deviceSerial string) Granter { - return func(ctx context.Context, packageName, permission string) error { - arguments := []string{"shell", "pm", "grant", packageName, permission} - if deviceSerial != "" { - arguments = append([]string{"-s", deviceSerial}, arguments...) - } - command := exec.CommandContext(ctx, adbPath, arguments...) - output, err := command.CombinedOutput() - if err != nil { - return fmt.Errorf("adb pm grant %s: %w (%s)", permission, err, strings.TrimSpace(string(output))) - } - return nil - } -} - -// dangerousPermissions captures Android's PROTECTION_DANGEROUS set as of -// API 34. New runtime permissions added in later releases should be appended -// here when needed. -var dangerousPermissions = map[string]bool{ - "android.permission.READ_CALENDAR": true, - "android.permission.WRITE_CALENDAR": true, - "android.permission.CAMERA": true, - "android.permission.READ_CONTACTS": true, - "android.permission.WRITE_CONTACTS": true, - "android.permission.GET_ACCOUNTS": true, - "android.permission.ACCESS_FINE_LOCATION": true, - "android.permission.ACCESS_COARSE_LOCATION": true, - "android.permission.ACCESS_BACKGROUND_LOCATION": true, - "android.permission.RECORD_AUDIO": true, - "android.permission.READ_PHONE_STATE": true, - "android.permission.READ_PHONE_NUMBERS": true, - "android.permission.CALL_PHONE": true, - "android.permission.ANSWER_PHONE_CALLS": true, - "android.permission.READ_CALL_LOG": true, - "android.permission.WRITE_CALL_LOG": true, - "android.permission.ADD_VOICEMAIL": true, - "android.permission.USE_SIP": true, - "android.permission.PROCESS_OUTGOING_CALLS": true, - "android.permission.BODY_SENSORS": true, - "android.permission.SEND_SMS": true, - "android.permission.RECEIVE_SMS": true, - "android.permission.READ_SMS": true, - "android.permission.RECEIVE_WAP_PUSH": true, - "android.permission.RECEIVE_MMS": true, - "android.permission.READ_EXTERNAL_STORAGE": true, - "android.permission.WRITE_EXTERNAL_STORAGE": true, - "android.permission.ACCESS_MEDIA_LOCATION": true, - "android.permission.ACTIVITY_RECOGNITION": true, - "android.permission.POST_NOTIFICATIONS": true, - "android.permission.NEARBY_WIFI_DEVICES": true, - "android.permission.READ_MEDIA_IMAGES": true, - "android.permission.READ_MEDIA_VIDEO": true, - "android.permission.READ_MEDIA_AUDIO": true, - "android.permission.READ_MEDIA_VISUAL_USER_SELECTED": true, - "android.permission.BLUETOOTH_CONNECT": true, - "android.permission.BLUETOOTH_ADVERTISE": true, - "android.permission.BLUETOOTH_SCAN": true, - "android.permission.UWB_RANGING": true, - "android.permission.BODY_SENSORS_BACKGROUND": true, -} - -func IsDangerous(permission string) bool { - return dangerousPermissions[permission] -} diff --git a/internal/permissions/permissions_test.go b/internal/permissions/permissions_test.go deleted file mode 100644 index 907895b..0000000 --- a/internal/permissions/permissions_test.go +++ /dev/null @@ -1,127 +0,0 @@ -package permissions - -import ( - "context" - "errors" - "slices" - "testing" -) - -func TestGrantDangerous_FiltersAndCallsGranter(t *testing.T) { - declared := []string{ - "android.permission.INTERNET", // not dangerous - "android.permission.CAMERA", // dangerous - "android.permission.WAKE_LOCK", // not dangerous - "android.permission.ACCESS_FINE_LOCATION", // dangerous - "android.permission.READ_EXTERNAL_STORAGE", // dangerous - "android.permission.SYSTEM_ALERT_WINDOW", // not dangerous - } - inspector := func(_ context.Context, _ string) ([]string, error) { return declared, nil } - var requested []string - granter := func(_ context.Context, packageName, permission string) error { - if packageName != "com.example" { - t.Errorf("granter received wrong package: %q", packageName) - } - requested = append(requested, permission) - return nil - } - - granted, warnings, err := GrantDangerous(context.Background(), "/path/to/apk", "com.example", inspector, granter) - if err != nil { - t.Fatal(err) - } - want := []string{ - "android.permission.CAMERA", - "android.permission.ACCESS_FINE_LOCATION", - "android.permission.READ_EXTERNAL_STORAGE", - } - if !slices.Equal(granted, want) { - t.Errorf("granted permissions: got %v, want %v", granted, want) - } - if !slices.Equal(requested, want) { - t.Errorf("granter calls: got %v, want %v", requested, want) - } - if len(warnings) != 0 { - t.Errorf("expected no warnings, got %v", warnings) - } -} - -func TestGrantDangerous_CollectsGranterFailuresAsWarnings(t *testing.T) { - declared := []string{"android.permission.CAMERA", "android.permission.RECORD_AUDIO"} - inspector := func(_ context.Context, _ string) ([]string, error) { return declared, nil } - granter := func(_ context.Context, _, permission string) error { - if permission == "android.permission.CAMERA" { - return errors.New("device denied") - } - return nil - } - - granted, warnings, err := GrantDangerous(context.Background(), "/x", "com.example", inspector, granter) - if err != nil { - t.Fatal(err) - } - if !slices.Equal(granted, []string{"android.permission.RECORD_AUDIO"}) { - t.Errorf("granted: %v", granted) - } - if len(warnings) != 1 || warnings[0] != "android.permission.CAMERA: device denied" { - t.Errorf("warnings: %v", warnings) - } -} - -func TestGrantDangerous_InspectorErrorBubbles(t *testing.T) { - inspector := func(_ context.Context, _ string) ([]string, error) { - return nil, errors.New("aapt missing") - } - _, _, err := GrantDangerous(context.Background(), "/x", "com.example", inspector, nil) - if err == nil || err.Error() == "" { - t.Errorf("expected wrapped inspector error, got %v", err) - } -} - -func TestIsDangerous_KnownPermissions(t *testing.T) { - dangerous := []string{ - "android.permission.CAMERA", - "android.permission.RECORD_AUDIO", - "android.permission.POST_NOTIFICATIONS", - } - for _, permission := range dangerous { - if !IsDangerous(permission) { - t.Errorf("expected %q to be dangerous", permission) - } - } - - normal := []string{ - "android.permission.INTERNET", - "android.permission.WAKE_LOCK", - "android.permission.SYSTEM_ALERT_WINDOW", - } - for _, permission := range normal { - if IsDangerous(permission) { - t.Errorf("expected %q not to be dangerous", permission) - } - } -} - -func TestAaptInspector_ParsesFixtureOutput(t *testing.T) { - // Direct test of the regex; avoids spawning aapt. - output := ` -package: com.example -sdkVersion:'24' -uses-permission: name='android.permission.INTERNET' -uses-permission: name='android.permission.CAMERA' -uses-permission: name='android.permission.WAKE_LOCK' -` - matches := aaptPermissionPattern.FindAllStringSubmatch(output, -1) - got := make([]string, 0, len(matches)) - for _, match := range matches { - got = append(got, match[1]) - } - want := []string{ - "android.permission.INTERNET", - "android.permission.CAMERA", - "android.permission.WAKE_LOCK", - } - if !slices.Equal(got, want) { - t.Errorf("got %v, want %v", got, want) - } -}