Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Migrate to Dagger #196

Closed
wants to merge 9 commits into from
@@ -103,6 +103,8 @@ dependencies {
implementation 'com.jakewharton.threetenabp:threetenabp:' + versions.threetenabp
implementation 'com.jakewharton.timber:timber:' + versions.timber
implementation 'androidx.work:work-runtime-ktx:' + versions.work
implementation 'com.google.dagger:dagger:' + versions.dagger
kapt 'com.google.dagger:dagger-compiler:' + versions.dagger
if (!isCi()) debugImplementation 'com.squareup.leakcanary:leakcanary-android:' + versions.leakcanary
}

@@ -11,6 +11,9 @@ import android.os.Build
import android.os.StrictMode
import androidx.annotation.RequiresApi
import androidx.core.content.getSystemService
import com.wireguard.android.di.AppComponent
import com.wireguard.android.di.DaggerAppComponent
import com.wireguard.android.di.InjectorProvider
import com.wireguard.android.di.backendAsyncModule
import com.wireguard.android.di.backendModule
import com.wireguard.android.di.configStoreModule
@@ -24,7 +27,11 @@ import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin
import timber.log.Timber

class Application : android.app.Application() {
class Application : android.app.Application(), InjectorProvider {

override val component: AppComponent by lazy {
DaggerAppComponent.factory().create(applicationContext)
}

init {
weakSelf = WeakReference(this)
@@ -45,9 +52,7 @@ class Application : android.app.Application() {
notificationManager.createNotificationChannel(notificationChannel)
}

override fun onCreate() {
super.onCreate()

private fun initializeKoin() {
startKoin {
androidContext(this@Application)
modules(listOf(
@@ -58,7 +63,9 @@ class Application : android.app.Application() {
toolsInstallerModule
))
}
}

private fun initializeTimber() {
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder()
@@ -67,6 +74,13 @@ class Application : android.app.Application() {
.build()
)
}
}

override fun onCreate() {
super.onCreate()

initializeKoin()
initializeTimber()

updateAppTheme(getPrefs().useDarkTheme)

@@ -21,9 +21,10 @@ import com.wireguard.config.Config
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
import java9.util.concurrent.CompletableFuture
import javax.inject.Inject
import timber.log.Timber

class GoBackend(private val context: Context, private val prefs: ApplicationPreferences) : Backend {
class GoBackend @Inject constructor(private val context: Context, private val prefs: ApplicationPreferences) : Backend {

private var currentTunnel: Tunnel? = null
private var currentTunnelHandle = -1
@@ -24,13 +24,14 @@ import com.wireguard.config.Config
import java.io.File
import java.io.FileOutputStream
import java.nio.charset.StandardCharsets
import javax.inject.Inject
import timber.log.Timber

/**
* WireGuard backend that uses `wg-quick` to implement tunnel configuration.
*/

class WgQuickBackend(private val context: Context, private val toolsInstaller: ToolsInstaller, private val rootShell: RootShell) : Backend {
class WgQuickBackend @Inject constructor(private val context: Context, private val toolsInstaller: ToolsInstaller, private val rootShell: RootShell) : Backend {

private val localTemporaryDir: File = File(context.cacheDir, "tmp")
private var notificationManager = NotificationManagerCompat.from(context)
@@ -15,13 +15,14 @@ import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.nio.charset.StandardCharsets
import javax.inject.Inject
import timber.log.Timber

/**
* Configuration store that uses a `wg-quick`-style file for each configured tunnel.
*/

class FileConfigStore(private val context: Context) : ConfigStore {
class FileConfigStore @Inject constructor(val context: Context) : ConfigStore {

@Throws(IOException::class)
override fun create(name: String, config: Config): Config {
@@ -0,0 +1,135 @@
/*
* Copyright 漏 2017-2019 WireGuard LLC.
* Copyright 漏 2018-2019 Harsh Shandilya <msfjarvis@gmail.com>. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.wireguard.android.di

import android.content.Context
import android.os.AsyncTask
import android.os.Handler
import android.os.Looper
import com.wireguard.android.backend.Backend
import com.wireguard.android.backend.GoBackend
import com.wireguard.android.backend.WgQuickBackend
import com.wireguard.android.configStore.ConfigStore
import com.wireguard.android.configStore.FileConfigStore
import com.wireguard.android.model.TunnelManager
import com.wireguard.android.util.ApplicationPreferences
import com.wireguard.android.util.AsyncWorker
import com.wireguard.android.util.BackendAsync
import com.wireguard.android.util.RootShell
import com.wireguard.android.util.ToolsInstaller
import dagger.BindsInstance
import dagger.Component
import dagger.Module
import dagger.Provides
import dagger.Reusable
import java.io.File
import java.util.concurrent.Executor
import javax.inject.Qualifier
import javax.inject.Singleton

@Qualifier
annotation class ApplicationHandler

@Singleton
@Component(modules = [ApplicationModule::class])
interface AppComponent {

@Component.Factory
interface Factory {
fun create(@BindsInstance applicationContext: Context): AppComponent
}

val backend: Backend
val backendAsync: BackendAsync
val asyncWorker: AsyncWorker
val backendType: Class<Backend>
val toolsInstaller: ToolsInstaller
val tunnelManager: TunnelManager
val rootShell: RootShell
val preferences: ApplicationPreferences
}

@Module
object ApplicationModule {
@get:Reusable
@get:Provides
@get:JvmStatic
val executor: Executor = AsyncTask.SERIAL_EXECUTOR

@get:ApplicationHandler
@get:Reusable
@get:Provides
@get:JvmStatic
val handler: Handler = Handler(Looper.getMainLooper())

@Reusable
@Provides
@JvmStatic
fun getRootShell(context: Context): RootShell = RootShell(context)

@Reusable
@Provides
@JvmStatic
fun getToolsInstaller(
context: Context,
rootShell: RootShell
): ToolsInstaller = ToolsInstaller(context, rootShell)

@Reusable
@Provides
@JvmStatic
fun getConfigStore(context: Context): ConfigStore = FileConfigStore(context)

@Reusable
@Provides
@JvmStatic
fun getTunnelManager(
context: Context,
configStore: ConfigStore,
prefs: ApplicationPreferences
): TunnelManager = TunnelManager(context, configStore, prefs)

@Reusable
@Provides
@JvmStatic
fun getBackend(
context: Context,
rootShell: RootShell,
toolsInstaller: ToolsInstaller,
preferences: ApplicationPreferences
): Backend {
return if (File("/sys/module/wireguard").exists() && !preferences.forceUserspaceBackend) WgQuickBackend(
context,
rootShell,
toolsInstaller
) else GoBackend(context, preferences)
}

@Reusable
@Provides
@JvmStatic
fun getBackendType(backend: Backend): Class<Backend> = backend.javaClass

@Reusable
@Provides
@JvmStatic
fun getPreferences(context: Context): ApplicationPreferences = ApplicationPreferences(context)

@Reusable
@Provides
@JvmStatic
fun getAsyncWorker(executor: Executor, @ApplicationHandler handler: Handler): AsyncWorker =
AsyncWorker(executor, handler)

@Singleton
@Provides
@JvmStatic
fun getBackendAsync(backend: Backend): BackendAsync {
val backendAsync = BackendAsync()
backendAsync.complete(backend)
return backendAsync
}
}
@@ -0,0 +1,14 @@
/*
* Copyright 漏 2017-2019 WireGuard LLC.
* Copyright 漏 2018-2019 Harsh Shandilya <msfjarvis@gmail.com>. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.wireguard.android.di

import android.app.Activity

interface InjectorProvider {
val component: AppComponent
}

val Activity.injector get() = (application as InjectorProvider).component
@@ -11,11 +11,11 @@ import android.content.Intent
import android.net.Uri
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import com.wireguard.android.Application
import com.wireguard.android.BR
import com.wireguard.android.BuildConfig
import com.wireguard.android.R
import com.wireguard.android.configStore.ConfigStore
import com.wireguard.android.di.ext.getTunnelManager
import com.wireguard.android.di.ext.injectAsyncWorker
import com.wireguard.android.di.ext.injectBackend
import com.wireguard.android.model.Tunnel.Statistics
@@ -28,10 +28,11 @@ import com.wireguard.config.Config
import java9.util.Comparators
import java9.util.concurrent.CompletableFuture
import java9.util.concurrent.CompletionStage
import javax.inject.Inject
import org.koin.core.KoinComponent
import timber.log.Timber

class TunnelManager(
class TunnelManager @Inject constructor(
private val context: Context,
private val configStore: ConfigStore,
private val prefs: ApplicationPreferences
@@ -246,12 +247,13 @@ class TunnelManager(
}

class IntentReceiver : BroadcastReceiver() {

override fun onReceive(context: Context?, intent: Intent?) {
if (intent == null || intent.action == null)
return
when (intent.action) {
"com.wireguard.android.action.REFRESH_TUNNEL_STATES" -> {
getTunnelManager().refreshTunnelStates()
(context?.applicationContext as Application).component.tunnelManager.refreshTunnelStates()
return
}
else -> Timber.tag("TunnelManager").d("Invalid intent action: ${intent.action}")
@@ -16,9 +16,10 @@ import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.nio.charset.StandardCharsets
import java.util.UUID
import javax.inject.Inject
import timber.log.Timber

class RootShell(val context: Context) {
class RootShell @Inject constructor(val context: Context) {

private val deviceNotRootedMessage: String by lazy { context.getString(R.string.error_root) }
private val localBinaryDir: File = File(context.codeCacheDir, "bin")
@@ -12,14 +12,14 @@ import com.wireguard.android.util.RootShell.NoRootException
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
import org.koin.core.KoinComponent
import javax.inject.Inject
import timber.log.Timber

/**
* Helper to install WireGuard tools to the system partition.
*/

class ToolsInstaller(private val context: Context, private val rootShell: RootShell) : KoinComponent {
class ToolsInstaller @Inject constructor(private val context: Context, private val rootShell: RootShell) : KoinComponent {

private val localBinaryDir = File(context.codeCacheDir, "bin")
private val magiskDir by lazy { getMagiskDirectory() }
@@ -35,6 +35,7 @@ ext {

// Third party
barcode: '1.1.1',
dagger: '2.24',
koin: '2.0.1',
leakcanary: '2.0-beta-3',
retrofuture: '1.7.1',
ProTip! Use n and p to navigate between commits in a pull request.
You can鈥檛 perform that action at this time.