xcrun simctl privacyは、写真・連絡先・位置情報などのプライバシー系権限を、確認ダイアログを表示せずに操作するサブコマンドである。
基本的な使い方
privacy <device> <action> <service> [<bundle identifier>]の形式で実行する。
<action>には次の3種類を指定できる。
| action | 内容 |
|---|---|
grant | 確認なしでアクセスを許可する。<bundle identifier>が必須 |
revoke | アクセスを拒否し、そのサービスの利用を全て禁止する。<bundle identifier>が必須 |
reset | アクセス状態をリセットし、次回利用時に確認ダイアログを表示させる。<bundle identifier>は省略可能 |
<service>には次のいずれかを指定する。
| service | 内容 |
|---|---|
all | 全てのサービスを対象にする |
calendar | カレンダーへのアクセス |
contacts-limited | 連絡先の基本情報のみへのアクセス |
contacts | 連絡先の詳細情報を含む全アクセス |
location | アプリ使用中のみの位置情報アクセス |
location-always | 常時の位置情報アクセス |
photos-add | フォトライブラリへの追加のみのアクセス |
photos | フォトライブラリへの全アクセス |
media-library | メディアライブラリへのアクセス |
microphone | マイク(音声入力)へのアクセス |
motion | モーション・フィットネスデータへのアクセス |
reminders | リマインダーへのアクセス |
siri | Siriからのアプリ利用 |
$ xcrun simctl privacy "TIL Privacy Test" grant photos com.apple.mobilesafari
権限の反映状況は、シミュレータのTCC(プライバシー権限)データベースを直接確認すると分かりやすい。
$ sqlite3 ~/Library/Developer/CoreSimulator/Devices/<UUID>/data/Library/TCC/TCC.db \
"SELECT service, client, auth_value FROM access;"
kTCCServicePhotos|com.apple.mobilesafari|2
auth_valueが2のとき許可、0のとき拒否を意味する。
grant/revokeはbundle identifierが必須
grantとrevokeはアプリを一意に指定する必要があり、<bundle identifier>を省略するとエラーになる。
$ xcrun simctl privacy "TIL Privacy Test" grant photos
Bundle identifier is required for grant actions
revokeを実行すると、TCCデータベース上のauth_valueが拒否を示す0に変わる。
$ xcrun simctl privacy "TIL Privacy Test" revoke photos com.apple.mobilesafari
$ sqlite3 ~/Library/Developer/CoreSimulator/Devices/<UUID>/data/Library/TCC/TCC.db \
"SELECT service, client, auth_value FROM access WHERE service='kTCCServicePhotos';"
kTCCServicePhotos|com.apple.mobilesafari|0
reset allはbundle identifierを省略すると既存の権限に影響しない
ヘルプのExamplesにはreset all(bundle identifier省略)で全ての権限をリセットできるという例が載っているが、実際に試したところ、既にTCCデータベースに記録済みのアプリの権限には一切変化がなかった。
$ sqlite3 ~/Library/Developer/CoreSimulator/Devices/<UUID>/data/Library/TCC/TCC.db \
"SELECT service, client, auth_value FROM access WHERE client='com.apple.mobilesafari';"
kTCCServicePhotos|com.apple.mobilesafari|2
kTCCServiceAddressBook|com.apple.mobilesafari|2
$ xcrun simctl privacy "TIL Privacy Test" reset all
$ sqlite3 ~/Library/Developer/CoreSimulator/Devices/<UUID>/data/Library/TCC/TCC.db \
"SELECT service, client, auth_value FROM access WHERE client='com.apple.mobilesafari';"
kTCCServicePhotos|com.apple.mobilesafari|2
kTCCServiceAddressBook|com.apple.mobilesafari|2
一方、<bundle identifier>を指定してreset all com.apple.mobilesafariのように実行すると、そのアプリの全サービスのTCCレコードが実際に削除された(対象アプリは次に該当機能を使うときに確認ダイアログが再表示される状態になる)。
$ xcrun simctl privacy "TIL Privacy Test" reset all com.apple.mobilesafari
$ sqlite3 ~/Library/Developer/CoreSimulator/Devices/<UUID>/data/Library/TCC/TCC.db \
"SELECT count(*) FROM access WHERE client='com.apple.mobilesafari';"
0
個別のサービス・アプリを指定したreset <service> <bundle identifier>でも、該当するTCCレコードのみ削除されることを確認した。
特定のアプリの権限を確実にリセットしたい場合は、<bundle identifier>を省略せずに指定する必要がある。
活用例: UIテストで権限確認ダイアログを回避する
UIテストの実行前にあらかじめgrantで必要な権限を許可しておくと、実際のアプリ操作中に確認ダイアログが表示されず、テストが安定して進行する。
$ xcrun simctl privacy "TIL Privacy Test" grant photos com.example.app
$ xcrun simctl privacy "TIL Privacy Test" grant location com.example.app
ヘルプにも記載されているとおり、この方法はアプリ本来のInfo.plist設定やAPI呼び出しの不備を隠してしまう可能性があるため、権限リクエストの実装自体を検証したいテストでは使わない方がよい。
