Skip to content

Feature implementation from commits 6e856b1..88a5d3c#4

Open
codeOwlAI wants to merge 15 commits into
feature-base-branch-2from
feature-head-branch-2
Open

Feature implementation from commits 6e856b1..88a5d3c#4
codeOwlAI wants to merge 15 commits into
feature-base-branch-2from
feature-head-branch-2

Conversation

@codeOwlAI

@codeOwlAI codeOwlAI commented Jun 29, 2025

Copy link
Copy Markdown
Owner

PR Summary

Enhance File Operations Handling with Event-based Architecture

Overview

This PR improves file operations handling by introducing an event-based architecture using eventbus and channels, particularly for Android file sharing. It also refactors device unlock handling in QuickToggleService for better security.

Change Types

Type Description
Enhancement Added event-based architecture for file operations
Refactor Improved device unlock handling in QuickToggleService

Affected Modules

Module / File Change Description
src/main/java/com/tailscale/ipn/QuickToggleService.java Refactored onClick() to use unlockAndRun() for secure device unlock
backend.go Added eventbus integration, removed directFileRoot parameter, added file operations monitoring
callbacks.go Added channel variables for ShareFileHelper and SAF paths
fileops.go Added AndroidFileOps implementation wrapping ShareFileHelper
interfaces.go Added SetShareFileHelper and SetDirectFileRoot functions
tailscale.go Added backend restart channel and watchFileOpsChanges goroutine

Notes for Reviewers

  • Verify that the removal of directFileRoot parameter from newBackend() doesn't cause runtime issues
  • Confirm that synchronization primitives are correctly implemented to avoid race conditions
  • Test the device unlock handling in Android to ensure security is maintained

kari-ts and others added 15 commits April 21, 2025 10:48
Update to androidx.navigation 2.8.5: this fixes the NavHost exception per https://developer.android.com/jetpack/androidx/releases/navigation#2.8.5

Fixes tailscale/tailscale#15755

Signed-off-by: kari-ts <kari@tailscale.com>
…ation (tailscale#642)

* android/src: ktfmt

Signed-off-by: Jakub Meysner <git@jakubmeysner.com>

* android/src/main: show exit node information in the permanent notification

Displays exit node status (including the name of the exit node) in the permanent connection notification's content (moving the overall connected/disconnected status to the title).

Fixes tailscale/tailscale#14438

Signed-off-by: Jakub Meysner <git@jakubmeysner.com>

* docker: fix invalid instruction in Dockerfile not using trailing slash for files destination directory

> If the source is a file, and the destination doesn't end with a trailing slash, the source file will be written to the destination path as a file.
~ https://docs.docker.com/reference/dockerfile/#destination

Signed-off-by: Jakub Meysner <git@jakubmeysner.com>

---------

Signed-off-by: Jakub Meysner <git@jakubmeysner.com>
OSS and Version updated to 1.83.162-ta9b3e09a1-g8683c789f

Fixes a breaking change in the NetMon constructor.

Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
OSS and Version updated to 1.83.190-tfd263adc1-g5b4eff216

Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
…#622)

* android: ensure in secure state to interact with quicktile

Updates tailscale/tailscale#14628

Signed-off-by: davfsa <davfsa@gmail.com>

* Update android/src/main/java/com/tailscale/ipn/QuickToggleService.java

Signed-off-by: davfsa <davfsa@gmail.com>

---------

Signed-off-by: davfsa <davfsa@gmail.com>
Right now, we register the launcher in MainActivity.onCreate(), inject this into the ViewModel, then show the launcher in MainView.
There is no guarantee that the activity is in RESUMED when the Composable runs, showing the launcher. This can lead to a silent RESULT_CANCELED on some OEMs.
The fix is to add a lifecycle-aware wrapper that defers the launch.

Updates tailscale/tailscale#15419

Signed-off-by: kari-ts <kari@tailscale.com>
OSS and Version updated to 1.83.223-t336b3b7df-gd3f34c579

Signed-off-by: kari-ts <kari@tailscale.com>
&& takes precedence over ?:, so fix isExitNode to check both IPv4 and IPv6

Updates tailscale/tailscale#15785

Signed-off-by: kari-ts <kari@tailscale.com>
We were previously calling startService(intent), which is a direct call consumed by IPNService, but restartVPN was not working as intended because the broadcast receiver was never triggered.
Rather than use a broadcast receiver, directly start the service in restartVPN as we do in stopVPN. Also, batch changes to excluded apps so that we don't restart the VPN each time the user toggles an app.

Fixes tailscale/corp#28668

Signed-off-by: kari-ts <kari@tailscale.com>
OSS and Version updated to 1.83.237-tc4fb380f3-g7f56d0c0f

Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
OSS and Version updated to 1.83.240-t5a8b99e97-gd3f34c579

Signed-off-by: kari-ts <kari@tailscale.com>
Signed-off-by: kari-ts <135075563+kari-ts@users.noreply.github.com>
Use Android Storage Access Framework for receiving Taildropped files.

-Add a picker to allow users to select where Taildropped files go
-If no directory is selected, internal app storage is used
-Provide SAF API for Go to use when writing and renaming files
-Provide Android FileOps implementation

Updates tailscale/tailscale#15263

Signed-off-by: kari-ts <kari@tailscale.com>
OSS and Version updated to 1.85.8-t09582bdc0-gbd5191363

Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
updates tailscale/corp#29045

We ran into an issue where the current detection logic was not
sufficient to filter out mullvad nodes.  This modifies the logic so we
scan both the Name and ComputedName for the mullvad domain and
also treat all nodes with location info as mullvad nodes.  While all
of these conditions *should* be true for any mullvad node, in practice
it's possible that they aren't so we or them together for some redundancy
and define a mullvad exit node to be any node where any of these
conditions is true.

Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
}

func SetDirectFileRoot(filePath string) {
onFilePath <- filePath

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Correctness Issue

Potential Deadlock in SetDirectFileRoot.

Writing to onFilePath channel without checking if it's full can cause a deadlock if the channel is not being actively read from.

Current Code (Diff):

-	onFilePath <- filePath
+	select {
+	case onFilePath <- filePath:
+	default:
+		// Channel is full, log the issue
+		log.Printf("Unable to set file path: channel full")
+	}
📝 Committable suggestion

‼️ IMPORTANT
Trust, but verify! 🕵️ Please review this suggestion with the care of a code archaeologist - check that it perfectly replaces the highlighted code, preserves all lines, maintains proper indentation, and won't break anything in production. Your future self will thank you! 🚀

Suggested change
onFilePath <- filePath
select {
case onFilePath <- filePath:
default:
// Channel is full, log the issue
log.Printf("Unable to set file path: channel full")
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants