diff --git a/build.sbt b/build.sbt
index 62d5a5ee..2b292c2b 100644
--- a/build.sbt
+++ b/build.sbt
@@ -30,6 +30,8 @@ resolvers += Resolver.jcenterRepo
useSupportVectors
+googleServicesSettings
+
libraryDependencies ++= Seq(
"com.android.support" % "design" % "24.2.1",
"com.android.support" % "gridlayout-v7" % "24.2.1",
@@ -39,6 +41,8 @@ libraryDependencies ++= Seq(
"com.github.kevinsawicki" % "http-request" % "6.0",
"com.google.android.gms" % "play-services-ads" % "9.6.1",
"com.google.android.gms" % "play-services-analytics" % "9.6.1",
+ "com.google.firebase" % "firebase-core" % "9.6.1",
+ "com.google.firebase" % "firebase-storage" % "9.6.1",
"com.j256.ormlite" % "ormlite-android" % "5.0",
"com.twofortyfouram" % "android-plugin-api-for-locale" % "1.0.2",
"dnsjava" % "dnsjava" % "2.1.7",
@@ -52,6 +56,7 @@ proguardVersion in Android := "5.3"
proguardCache in Android := Seq()
proguardOptions in Android ++= Seq(
+ "-keepattributes Signature",
"-keep class com.github.shadowsocks.System { *; }",
"-dontwarn com.google.android.gms.internal.**",
"-dontwarn com.j256.ormlite.**",
diff --git a/project/plugins.sbt b/project/plugins.sbt
index f10c70aa..8131ffcc 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -1,5 +1,7 @@
addSbtPlugin("org.scala-android" % "sbt-android" % "1.6.18")
+addSbtPlugin("org.scala-android" % "sbt-android-gms" % "0.2")
+
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.10")
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.8.2")
diff --git a/src/main/res/xml/pref_all.xml b/src/main/res/xml/pref_all.xml
index 8af41fe1..d4df4e23 100644
--- a/src/main/res/xml/pref_all.xml
+++ b/src/main/res/xml/pref_all.xml
@@ -121,9 +121,6 @@
android:summary="@string/nat_summary"/>
-
diff --git a/src/main/scala/com/github/shadowsocks/BaseService.scala b/src/main/scala/com/github/shadowsocks/BaseService.scala
index e3c620b6..15aacaf3 100644
--- a/src/main/scala/com/github/shadowsocks/BaseService.scala
+++ b/src/main/scala/com/github/shadowsocks/BaseService.scala
@@ -39,6 +39,7 @@
package com.github.shadowsocks
+import java.io.File
import java.io.IOException
import java.util.{Timer, TimerTask}
@@ -55,6 +56,10 @@ import com.github.shadowsocks.utils._
import com.github.shadowsocks.ShadowsocksApplication.app
import com.github.shadowsocks.database.Profile
+import com.google.firebase.FirebaseApp
+import com.google.firebase.storage.FileDownloadTask
+import com.google.firebase.storage.FirebaseStorage
+
trait BaseService extends Service {
@volatile private var state = State.STOPPED
@@ -276,6 +281,7 @@ trait BaseService extends Service {
override def onCreate() {
super.onCreate()
+ FirebaseApp.initializeApp(this)
app.refreshContainerHolder
}
@@ -311,4 +317,28 @@ trait BaseService extends Service {
case ex: Exception => "exclude = " + default + ";"
}
}
+
+ def getAcl(route: String) {
+ val localAcl = route match {
+ case Route.BYPASS_LAN => "bypass_lan.acl"
+ case Route.BYPASS_CHN => "bypass_chn.acl"
+ case Route.BYPASS_LAN_CHN => "bypass_lan_chn.acl"
+ case Route.GFWLIST => "gfwlist.acl"
+ case Route.CHINALIST => "chinalist.acl"
+ }
+ val cloudAclFile = new File(getApplicationInfo.dataDir + "/" + localAcl)
+ if (!cloudAclFile.exists) cloudAclFile.createNewFile
+ val tempFile = File.createTempFile(localAcl, "acl")
+ val storage = FirebaseStorage.getInstance
+ val storageRef = storage.getReferenceFromUrl("gs://admob-app-id-3330146721.appspot.com/acl/")
+ val aclRef = storageRef.child(localAcl)
+
+ val task = aclRef.getFile(tempFile)
+ task.addOnSuccessListener((_) => {
+ tempFile.renameTo(cloudAclFile)
+ return
+ })
+ task.addOnFailureListener((_) => Log.e("shadowsocks", "Unable to download " + localAcl))
+ tempFile.deleteOnExit()
+ }
}
diff --git a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala
index e82dbd98..43651183 100644
--- a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala
+++ b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala
@@ -545,15 +545,6 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
}
}
- def flushDnsCache() {
- val h = showProgress(R.string.flushing)
- Utils.ThrowableFuture {
- if (!Utils.toggleAirplaneMode(getBaseContext)) h.post(() => Snackbar.make(findViewById(android.R.id.content),
- R.string.flush_dnscache_no_root, Snackbar.LENGTH_LONG).show)
- h.sendEmptyMessage(0)
- }
- }
-
override def onActivityResult(requestCode: Int, resultCode: Int, data: Intent) = resultCode match {
case Activity.RESULT_OK =>
serviceLoad()
diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
index a518dc24..187db537 100644
--- a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
+++ b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
@@ -96,6 +96,7 @@ class ShadowsocksNatService extends BaseService {
if (profile.route != Route.ALL) {
cmd += "--acl"
+
profile.route match {
case Route.BYPASS_LAN => cmd += (getApplicationInfo.dataDir + "/bypass_lan.acl")
case Route.BYPASS_CHN => cmd += (getApplicationInfo.dataDir + "/bypass_chn.acl")
@@ -336,8 +337,10 @@ class ShadowsocksNatService extends BaseService {
}
handleConnection()
- // Set DNS
- su.addCommand(Utils.FLUSH_DNS)
+
+ // lazily get ACL from cloud
+ getAcl(profile.route)
+
changeState(State.CONNECTED)
notification = new ShadowsocksNotification(this, profile.name, true)
}
diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala
index f1304f17..a52753e1 100644
--- a/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala
+++ b/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala
@@ -170,12 +170,6 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
true
})
- findPreference("flush_dnscache").setOnPreferenceClickListener(_ => {
- app.track(TAG, "flush_dnscache")
- activity.flushDnsCache()
- true
- })
-
findPreference("about").setOnPreferenceClickListener((preference: Preference) => {
app.track(TAG, "about")
val web = new WebView(activity)
diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
index 0c174bd3..8a49bbba 100644
--- a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
+++ b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
@@ -162,6 +162,10 @@ class ShadowsocksVpnService extends VpnService with BaseService {
handleConnection()
changeState(State.CONNECTED)
+
+ // lazily get ACL from cloud
+ getAcl(profile.route)
+
notification = new ShadowsocksNotification(this, profile.name)
}
@@ -257,6 +261,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
if (profile.route != Route.ALL) {
cmd += "--acl"
+
profile.route match {
case Route.BYPASS_LAN => cmd += (getApplicationInfo.dataDir + "/bypass_lan.acl")
case Route.BYPASS_CHN => cmd += (getApplicationInfo.dataDir + "/bypass_chn.acl")
diff --git a/src/main/scala/com/github/shadowsocks/utils/Utils.scala b/src/main/scala/com/github/shadowsocks/utils/Utils.scala
index 4c417816..e6f32f02 100644
--- a/src/main/scala/com/github/shadowsocks/utils/Utils.scala
+++ b/src/main/scala/com/github/shadowsocks/utils/Utils.scala
@@ -169,19 +169,6 @@ object Utils {
result
}
- // Because /sys/class/net/* isn't accessible since API level 24
- final val FLUSH_DNS = "for if in /sys/class/net/*; do " +
- "if [ \"down\" != $(cat $if/operstate) ]; then " + // up or unknown
- "ndc resolver flushif ${if##*/}; " +
- "fi " +
- "done; echo done"
-
- // Blocked > 3 seconds
- def toggleAirplaneMode(context: Context) = {
- val result = Shell.SU.run(FLUSH_DNS)
- result != null && !result.isEmpty
- }
-
def resolve(host: String, addrType: Int): Option[String] = {
try {
val lookup = new Lookup(host, addrType)