@@ -142,10 +142,16 @@ class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {
142
142
143
143
app.trackEvent(" Setup" , " action-view" )
144
144
145
- when (intent.action) {
145
+ // RC intents are intents that have passed the RC permission requirement in the manifest.
146
+ // Implicit intents with the matching actions will always use the RC activity, this check
147
+ // protects against explicit intents targeting MainActivity. RC intents are known to be
148
+ // trustworthy, so are allowed to silently activate/deactivate the VPN connection.
149
+ val isRCIntent = intent.component?.className == " tech.httptoolkit.android.RemoteControlMainActivity"
150
+
151
+ when {
146
152
// ACTION_VIEW means that somebody had the app installed, and scanned the barcode with
147
153
// a separate barcode app anyway (or opened the QR code URL in a browser)
148
- Intent .ACTION_VIEW -> {
154
+ intent.action == Intent .ACTION_VIEW -> {
149
155
if (app.lastProxy != null && isVpnConfigured()) {
150
156
Log .i(TAG , " Showing prompt for ACTION_VIEW intent" )
151
157
@@ -174,16 +180,22 @@ class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {
174
180
}
175
181
}
176
182
177
- // RPC setup API, used by ADB to enable/disable without prompts.
183
+ // RC setup API, used by ADB to enable/disable without prompts.
178
184
// Permission required, checked for via activity-alias in the manifest
179
- ACTIVATE_INTENT -> {
185
+ isRCIntent && intent.action == ACTIVATE_INTENT -> {
180
186
launch { connectToVpnFromUrl(intent.data!! ) }
181
187
}
182
- DEACTIVATE_INTENT -> {
188
+ isRCIntent && intent.action == DEACTIVATE_INTENT -> {
183
189
disconnect()
184
190
}
185
191
186
- else -> Log .w(TAG , " Unknown intent. Action ${intent.action} , data: ${intent.data} " )
192
+ else -> Log .w(TAG , " Unknown intent. Action ${
193
+ intent.action
194
+ } , data: ${
195
+ intent.data
196
+ } , ${
197
+ if (isRCIntent) " sent as RC intent" else " non-RC"
198
+ } " )
187
199
}
188
200
}
189
201
0 commit comments