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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to gRPC #6272

Merged
merged 2 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .github/workflows/android-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ jobs:
:app:testOssProdDebugUnitTest
:service:testOssProdDebugUnitTest
:lib:billing:testDebugUnitTest
:lib:daemon-grpc:testDebugUnitTest
:lib:shared:testDebugUnitTest
- gradle-task: :test:arch:test --rerun-tasks
- gradle-task: detekt
- gradle-task: lint
Expand Down
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ Line wrap the file at 100 chars. Th
* **Security**: in case of vulnerabilities.

## [Unreleased]
### Changed
- Migrate underlaying communication wtih daemon to gRPC. This also implies major changes and
improvements throughout the app.

### Security
- Fix DNS leaks in blocking states or when no valid DNS has been configured due to an underlying OS
issue. In these cases a dummy DNS will be set to prevent leaks.
Expand Down
25 changes: 14 additions & 11 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -174,22 +174,23 @@ android {
"META-INF/LGPL2.1",
// Fixes packaging error caused by: jetified-junit-*
"META-INF/LICENSE.md",
"META-INF/LICENSE-notice.md"
"META-INF/LICENSE-notice.md",
"META-INF/io.netty.versions.properties",
"META-INF/INDEX.LIST"
)
}
}

applicationVariants.configureEach {
val alwaysShowChangelog =
gradleLocalProperties(rootProject.projectDir, providers).getProperty("ALWAYS_SHOW_CHANGELOG")
?: "false"
gradleLocalProperties(rootProject.projectDir, providers)
.getProperty("ALWAYS_SHOW_CHANGELOG") ?: "false"

buildConfigField("boolean", "ALWAYS_SHOW_CHANGELOG", alwaysShowChangelog)

val enableInAppVersionNotifications =
gradleLocalProperties(rootProject.projectDir, providers)
.getProperty("ENABLE_IN_APP_VERSION_NOTIFICATIONS")
?: "true"
.getProperty("ENABLE_IN_APP_VERSION_NOTIFICATIONS") ?: "true"

buildConfigField(
"boolean",
Expand Down Expand Up @@ -305,18 +306,19 @@ afterEvaluate {
play { serviceAccountCredentials.set(file("play-api-key.json")) }

dependencies {
implementation(project(Dependencies.Mullvad.vpnService))
implementation(project(Dependencies.Mullvad.tileService))

implementation(project(Dependencies.Mullvad.commonLib))
implementation(project(Dependencies.Mullvad.daemonGrpc))
implementation(project(Dependencies.Mullvad.endpointLib))
implementation(project(Dependencies.Mullvad.ipcLib))
implementation(project(Dependencies.Mullvad.intentLib))
implementation(project(Dependencies.Mullvad.mapLib))
implementation(project(Dependencies.Mullvad.modelLib))
implementation(project(Dependencies.Mullvad.paymentLib))
implementation(project(Dependencies.Mullvad.resourceLib))
implementation(project(Dependencies.Mullvad.sharedLib))
implementation(project(Dependencies.Mullvad.talpidLib))
implementation(project(Dependencies.Mullvad.tileService))
implementation(project(Dependencies.Mullvad.themeLib))
implementation(project(Dependencies.Mullvad.paymentLib))
implementation(project(Dependencies.Mullvad.mapLib))
implementation(project(Dependencies.Mullvad.vpnService))

// Play implementation
playImplementation(project(Dependencies.Mullvad.billingLib))
Expand All @@ -326,6 +328,7 @@ dependencies {
implementation(Dependencies.AndroidX.lifecycleRuntimeKtx)
implementation(Dependencies.AndroidX.lifecycleViewmodelKtx)
implementation(Dependencies.AndroidX.lifecycleRuntimeCompose)
implementation(Dependencies.Arrow.core)
implementation(Dependencies.Compose.constrainLayout)
implementation(Dependencies.Compose.foundation)
implementation(Dependencies.Compose.material3)
Expand Down
15 changes: 2 additions & 13 deletions android/app/lint-baseline.xml
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 8.1.4" type="baseline" client="gradle" dependencies="false" name="AGP (8.1.4)" variant="all" version="8.1.4">

<issue
id="MissingSuperCall"
message="Overriding method should call `super.onActivityResult`"
errorLine1=" override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {"
errorLine2=" ~~~~~~~~~~~~~~~~">
<location
file="src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt"
line="70"
column="18"/>
</issue>
<issues format="6" by="lint 8.3.0" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0)" variant="all" version="8.3.0">

<issue
id="UseCheckPermission"
Expand All @@ -30,7 +19,7 @@
errorLine2=" ~~~~~">
<location
file="src/main/AndroidManifest.xml"
line="25"
line="23"
column="39"/>
</issue>

Expand Down
13 changes: 13 additions & 0 deletions android/app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,16 @@
-dontwarn org.joda.time.**
-keep class org.joda.time.** { *; }
-keep interface org.joda.time.** { *; }

# grpc
-keep class io.grpc.okhttp.OkHttpChannelBuilder { *; }
-keep class mullvad_daemon.management_interface.** { *; }
-keep class com.google.protobuf.Timestamp { *; }
-keepnames class com.google.protobuf.** { *; }
-dontwarn com.google.j2objc.annotations.ReflectionSupport
-dontwarn com.google.j2objc.annotations.RetainedWith
-dontwarn com.squareup.okhttp.CipherSuite
-dontwarn com.squareup.okhttp.ConnectionSpec
-dontwarn com.squareup.okhttp.TlsVersion


Original file line number Diff line number Diff line change
@@ -1,61 +1,108 @@
package net.mullvad.mullvadvpn.compose.data

import net.mullvad.mullvadvpn.model.CustomListName
import net.mullvad.mullvadvpn.model.PortRange
import net.mullvad.mullvadvpn.model.RelayEndpointData
import net.mullvad.mullvadvpn.model.RelayList
import net.mullvad.mullvadvpn.model.RelayListCity
import net.mullvad.mullvadvpn.model.RelayListCountry
import net.mullvad.mullvadvpn.model.WireguardEndpointData
import net.mullvad.mullvadvpn.model.WireguardRelayEndpointData
import net.mullvad.mullvadvpn.relaylist.RelayItem
import net.mullvad.mullvadvpn.relaylist.toRelayCountries
import net.mullvad.mullvadvpn.lib.model.CustomList
import net.mullvad.mullvadvpn.lib.model.CustomListId
import net.mullvad.mullvadvpn.lib.model.CustomListName
import net.mullvad.mullvadvpn.lib.model.GeoLocationId
import net.mullvad.mullvadvpn.lib.model.Ownership
import net.mullvad.mullvadvpn.lib.model.PortRange
import net.mullvad.mullvadvpn.lib.model.Provider
import net.mullvad.mullvadvpn.lib.model.ProviderId
import net.mullvad.mullvadvpn.lib.model.RelayItem
import net.mullvad.mullvadvpn.lib.model.RelayList
import net.mullvad.mullvadvpn.lib.model.WireguardEndpointData

private val DUMMY_RELAY_1 =
net.mullvad.mullvadvpn.model.Relay(
hostname = "Relay host 1",
RelayItem.Location.Relay(
id =
GeoLocationId.Hostname(
city = GeoLocationId.City(GeoLocationId.Country("RCo1"), "Relay City 1"),
"Relay host 1"
),
active = true,
endpointData = RelayEndpointData.Wireguard(WireguardRelayEndpointData),
owned = true,
provider = "PROVIDER"
provider =
Provider(
providerId = ProviderId("PROVIDER RENTED"),
ownership = Ownership.Rented,
)
)
private val DUMMY_RELAY_2 =
net.mullvad.mullvadvpn.model.Relay(
hostname = "Relay host 2",
RelayItem.Location.Relay(
id =
GeoLocationId.Hostname(
city = GeoLocationId.City(GeoLocationId.Country("RCo2"), "Relay City 2"),
"Relay host 2"
),
active = true,
endpointData = RelayEndpointData.Wireguard(WireguardRelayEndpointData),
owned = true,
provider = "PROVIDER"
provider =
Provider(providerId = ProviderId("PROVIDER OWNED"), ownership = Ownership.MullvadOwned)
)
private val DUMMY_RELAY_CITY_1 =
RelayItem.Location.City(
name = "Relay City 1",
id = GeoLocationId.City(countryCode = GeoLocationId.Country("RCo1"), cityCode = "RCi1"),
relays = listOf(DUMMY_RELAY_1),
expanded = false
)
private val DUMMY_RELAY_CITY_2 =
RelayItem.Location.City(
name = "Relay City 2",
id = GeoLocationId.City(countryCode = GeoLocationId.Country("RCo2"), cityCode = "RCi2"),
relays = listOf(DUMMY_RELAY_2),
expanded = false
)
private val DUMMY_RELAY_CITY_1 = RelayListCity("Relay City 1", "RCi1", arrayListOf(DUMMY_RELAY_1))
private val DUMMY_RELAY_CITY_2 = RelayListCity("Relay City 2", "RCi2", arrayListOf(DUMMY_RELAY_2))
private val DUMMY_RELAY_COUNTRY_1 =
RelayListCountry("Relay Country 1", "RCo1", arrayListOf(DUMMY_RELAY_CITY_1))
RelayItem.Location.Country(
name = "Relay Country 1",
id = GeoLocationId.Country("RCo1"),
expanded = false,
cities = listOf(DUMMY_RELAY_CITY_1)
)
private val DUMMY_RELAY_COUNTRY_2 =
RelayListCountry("Relay Country 2", "RCo2", arrayListOf(DUMMY_RELAY_CITY_2))
RelayItem.Location.Country(
name = "Relay Country 2",
id = GeoLocationId.Country("RCo2"),
expanded = false,
cities = listOf(DUMMY_RELAY_CITY_2)
)

private val DUMMY_WIREGUARD_PORT_RANGES = ArrayList<PortRange>()
private val DUMMY_WIREGUARD_ENDPOINT_DATA = WireguardEndpointData(DUMMY_WIREGUARD_PORT_RANGES)

val DUMMY_RELAY_COUNTRIES =
val DUMMY_RELAY_COUNTRIES = listOf(DUMMY_RELAY_COUNTRY_1, DUMMY_RELAY_COUNTRY_2)

val DUMMY_RELAY_LIST =
RelayList(
arrayListOf(DUMMY_RELAY_COUNTRY_1, DUMMY_RELAY_COUNTRY_2),
DUMMY_WIREGUARD_ENDPOINT_DATA,
)
.toRelayCountries()
DUMMY_RELAY_COUNTRIES,
DUMMY_WIREGUARD_ENDPOINT_DATA,
)

val DUMMY_CUSTOM_LISTS =
val DUMMY_RELAY_ITEM_CUSTOM_LISTS =
listOf(
RelayItem.CustomList(
CustomListName.fromString("First list"),
false,
"1",
customListName = CustomListName.fromString("First list"),
expanded = false,
id = CustomListId("1"),
locations = DUMMY_RELAY_COUNTRIES
),
RelayItem.CustomList(
CustomListName.fromString("Empty list"),
customListName = CustomListName.fromString("Empty list"),
expanded = false,
"2",
id = CustomListId("2"),
locations = emptyList()
)
)

val DUMMY_CUSTOM_LISTS =
listOf(
CustomList(
name = CustomListName.fromString("First list"),
id = CustomListId("1"),
locations = DUMMY_RELAY_COUNTRIES.map { it.id }
),
CustomList(
name = CustomListName.fromString("Empty list"),
id = CustomListId("2"),
locations = emptyList()
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import net.mullvad.mullvadvpn.compose.createEdgeToEdgeComposeExtension
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.compose.state.CreateCustomListUiState
import net.mullvad.mullvadvpn.compose.test.CREATE_CUSTOM_LIST_DIALOG_INPUT_TEST_TAG
import net.mullvad.mullvadvpn.model.CustomListsError
import net.mullvad.mullvadvpn.lib.model.CustomListAlreadyExists
import net.mullvad.mullvadvpn.lib.model.UnknownCustomListError
import net.mullvad.mullvadvpn.usecase.customlists.CreateWithLocationsError
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension
Expand Down Expand Up @@ -44,7 +46,10 @@ class CreateCustomListDialogTest {
fun givenCustomListExistsShouldShowCustomListExitsErrorText() =
composeExtension.use {
// Arrange
val state = CreateCustomListUiState(error = CustomListsError.CustomListExists)
val state =
CreateCustomListUiState(
error = CreateWithLocationsError.Create(CustomListAlreadyExists)
)
setContentWithTheme { CreateCustomListDialog(state = state) }

// Assert
Expand All @@ -56,7 +61,10 @@ class CreateCustomListDialogTest {
fun givenOtherCustomListErrorShouldShowAnErrorOccurredErrorText() =
composeExtension.use {
// Arrange
val state = CreateCustomListUiState(error = CustomListsError.OtherError)
val state =
CreateCustomListUiState(
error = CreateWithLocationsError.Create(UnknownCustomListError(Throwable()))
)
setContentWithTheme { CreateCustomListDialog(state = state) }

// Assert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import io.mockk.MockKAnnotations
import net.mullvad.mullvadvpn.compose.createEdgeToEdgeComposeExtension
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.compose.test.CUSTOM_PORT_DIALOG_INPUT_TEST_TAG
import net.mullvad.mullvadvpn.model.PortRange
import net.mullvad.mullvadvpn.lib.model.Port
import net.mullvad.mullvadvpn.lib.model.PortRange
import net.mullvad.mullvadvpn.onNodeWithTagAndText
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
Expand All @@ -29,9 +30,9 @@ class CustomPortDialogTest {
@SuppressLint("ComposableNaming")
@Composable
private fun testWireguardCustomPortDialog(
initialPort: Int? = null,
initialPort: Port? = null,
allowedPortRanges: List<PortRange> = emptyList(),
onSave: (Int?) -> Unit = { _ -> },
onSave: (Port?) -> Unit = { _ -> },
onDismiss: () -> Unit = {},
) {

Expand All @@ -47,21 +48,20 @@ class CustomPortDialogTest {
fun testShowWireguardCustomPortDialogInvalidInt() =
composeExtension.use {
// Input a number to make sure that a too long number does not show and it does not
// crash
// the app
// crash the app

// Arrange
setContentWithTheme { testWireguardCustomPortDialog() }

// Act
onNodeWithTag(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG).performTextInput(invalidCustomPort)
onNodeWithTag(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG).performTextInput(INVALID_CUSTOM_PORT)

// Assert
onNodeWithTagAndText(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG, invalidCustomPort)
onNodeWithTagAndText(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG, INVALID_CUSTOM_PORT)
.assertDoesNotExist()
}

companion object {
const val invalidCustomPort = "21474836471"
const val INVALID_CUSTOM_PORT = "21474836471"
}
}
Loading
Loading