From b287d0b27eeaa12252d6e92b46902b68b0a315b8 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Fri, 3 May 2019 11:28:11 -0700 Subject: [PATCH 1/4] work on android service --- android/AndroidManifest.xml | 3 + .../openprivacy/cwtch/ui/CwtchActivity.java | 22 ++--- .../cwtch/ui/CwtchIntentService.java | 34 +++++++ .../src/ca/openprivacy/cwtch/ui/Runnable.java | 14 +++ .../CwtchActivity.go} | 10 +- go/gothings/android/CwtchService.go | 27 +++++ go/gothings/android/runnable.go | 98 +++++++++++++++++++ main.go | 3 +- 8 files changed, 189 insertions(+), 22 deletions(-) create mode 100644 android/src/ca/openprivacy/cwtch/ui/CwtchIntentService.java create mode 100644 android/src/ca/openprivacy/cwtch/ui/Runnable.java rename go/gothings/{androidCwtchActivity.go => android/CwtchActivity.go} (77%) create mode 100644 go/gothings/android/CwtchService.go create mode 100644 go/gothings/android/runnable.go diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 417982ba..de3dbbab 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -64,6 +64,9 @@ + + + diff --git a/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java b/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java index 4623ae15..ef721874 100644 --- a/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java +++ b/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java @@ -1,10 +1,10 @@ -package ca.openprivacy.cwtch.ui; +package ca.openprivcy.cwtch.ui; import android.app.Notification; import android.app.NotificationManager; import android.app.NotificationChannel; import android.content.Context; -import android.util.Log; +import android.content.Intent; import static android.app.Notification.DEFAULT_LIGHTS; @@ -16,20 +16,7 @@ import static android.content.Context.NOTIFICATION_SERVICE; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.os.Build.VERSION.SDK_INT; -import static android.app.Notification.CATEGORY_SERVICE; - - -/*import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE; -import static android.support.v4.app.NotificationCompat.CATEGORY_SERVICE; -import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL; -import static android.support.v4.app.NotificationCompat.PRIORITY_LOW; -import static android.support.v4.app.NotificationCompat.PRIORITY_MIN; -import static android.support.v4.app.NotificationCompat.PRIORITY_DEFAULT; -import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET; -import static android.support.v4.content.ContextCompat.getColor;*/ - - - +import static android.app.Notification.CATEGORY_SERVICE;SS public class CwtchActivity extends org.qtproject.qt5.android.bindings.QtActivity { @@ -53,6 +40,9 @@ public class CwtchActivity extends org.qtproject.qt5.android.bindings.QtActivity public CwtchActivity() { m_instance = this; + + /*Intent intent = new Intent(this, CwtchService.class); + startService(intent);*/ } public static void notify(String s) diff --git a/android/src/ca/openprivacy/cwtch/ui/CwtchIntentService.java b/android/src/ca/openprivacy/cwtch/ui/CwtchIntentService.java new file mode 100644 index 00000000..411ac359 --- /dev/null +++ b/android/src/ca/openprivacy/cwtch/ui/CwtchIntentService.java @@ -0,0 +1,34 @@ +package ca.openprivcy.cwtch.ui; + +import android.app.IntentService; +import android.content.Intent; +import android.util.Log; + +public class CwtchIntentService extends IntentService { + + /** + * A constructor is required, and must call the super IntentService(String) + * constructor with a name for the worker thread. + */ + public CwtchIntentService() { + super("CwtchIntentService"); + } + + /** + * The IntentService calls this method from the default worker thread with + * the intent that started the service. When this method returns, IntentService + * stops the service, as appropriate. + */ + @Override + protected void onHandleIntent(Intent intent) { + // Normally we would do some work here, like download a file. + // For our sample, we just sleep for 5 seconds. + try { + Log.i("CwtchIntentService", "onHandleIntent!!!!!!"); + } catch (Exception e) { //InterruptedException e) { + // Restore interrupt status. + Thread.currentThread().interrupt(); + } + } +} + diff --git a/android/src/ca/openprivacy/cwtch/ui/Runnable.java b/android/src/ca/openprivacy/cwtch/ui/Runnable.java new file mode 100644 index 00000000..dfda506e --- /dev/null +++ b/android/src/ca/openprivacy/cwtch/ui/Runnable.java @@ -0,0 +1,14 @@ +package ca.openprivcy.cwtch.ui; + +public class Runnable implements java.lang.Runnable { + static { + System.loadLibrary("go"); + } + public String ObjectName; + + public static native void qtrun(qt.java.lang.Runnable me); + @Override + public void run() { + qtrun(this); + } +} \ No newline at end of file diff --git a/go/gothings/androidCwtchActivity.go b/go/gothings/android/CwtchActivity.go similarity index 77% rename from go/gothings/androidCwtchActivity.go rename to go/gothings/android/CwtchActivity.go index 72e41fa8..e0ae4050 100644 --- a/go/gothings/androidCwtchActivity.go +++ b/go/gothings/android/CwtchActivity.go @@ -1,11 +1,11 @@ -package gothings +package android import ( "github.com/therecipe/qt/androidextras" "github.com/therecipe/qt/core" ) -type AndroidCwtchActivity struct { +type CwtchActivity struct { core.QObject _ func() `constructor:"init"` @@ -15,13 +15,13 @@ type AndroidCwtchActivity struct { _ func(string) `slot:"updateAndroidNotification"` } -func (c *AndroidCwtchActivity) init() { +func (c *CwtchActivity) init() { c.createOngoingNotification() c.ConnectNotificationChanged(c.updateAndroidNotification) } -func (c *AndroidCwtchActivity) updateAndroidNotification(n string) { +func (c *CwtchActivity) updateAndroidNotification(n string) { var err = androidextras.QAndroidJniObject_CallStaticMethodVoid2Caught( "ca/openprivacy/cwtch/ui/CwtchActivity", @@ -35,7 +35,7 @@ func (c *AndroidCwtchActivity) updateAndroidNotification(n string) { } } -func (c *AndroidCwtchActivity) createOngoingNotification() { +func (c *CwtchActivity) createOngoingNotification() { var err = androidextras.QAndroidJniObject_CallStaticMethodVoid2Caught( "ca/openprivacy/cwtch/ui/CwtchActivity", diff --git a/go/gothings/android/CwtchService.go b/go/gothings/android/CwtchService.go new file mode 100644 index 00000000..a6034423 --- /dev/null +++ b/go/gothings/android/CwtchService.go @@ -0,0 +1,27 @@ +package android + +import ( + "git.openprivacy.ca/openprivacy/libricochet-go/log" + "github.com/therecipe/qt/androidextras" + "time" +) + +type CwtchService struct { + androidextras.QAndroidService + //core.QObject + + //_ func() `constructor:"init"` +} + +func (cs *CwtchService) onCreate() { + log.Infof("CwtchService onCreate()\n") + + go func() { + i := 0 + for true { + time.Sleep(2 * time.Second) + log.Infof("CwtchService thread iteration %d\n", i) + i++ + } + }() +} diff --git a/go/gothings/android/runnable.go b/go/gothings/android/runnable.go new file mode 100644 index 00000000..6ad133a2 --- /dev/null +++ b/go/gothings/android/runnable.go @@ -0,0 +1,98 @@ +package android + +import "C" +import ( + "unsafe" + + "github.com/therecipe/qt" + "github.com/therecipe/qt/androidextras" +) + +type Runnable struct { + ptr *androidextras.QAndroidJniObject +} + +type Runnable_ITF interface { + Runnable_PTR() *Runnable +} + +func (p *Runnable) Pointer() *androidextras.QAndroidJniObject { + return p.ptr +} + +func (p *Runnable) SetPointer(ptr *androidextras.QAndroidJniObject) { + p.ptr = ptr +} + +func (ptr *Runnable) ConnectRun(f func()) { + if ptr.Pointer() != nil && ptr.Pointer().IsValid() { + + qt.ConnectSignal(ptr.Pointer().ToString(), "Runnable::run", unsafe.Pointer(&f)) + } +} + +func (ptr *Runnable) DisconnectRun() { + if ptr.Pointer() != nil && ptr.Pointer().IsValid() { + + qt.DisconnectSignal(ptr.Pointer().ToString(), "Runnable::run") + } +} + +//export Java_qt_java_lang_Runnable_qtrun +func Java_qt_java_lang_Runnable_qtrun(_, _, this unsafe.Pointer) { + if signal := qt.GetSignal(androidextras.NewQAndroidJniObject6(this).ToString(), "Runnable::run"); signal != nil { + (*(*func())(signal))() + } + +} + +func (ptr *Runnable) Run() { + if ptr.Pointer() != nil && ptr.Pointer().IsValid() { + ptr.Pointer().CallMethodVoid2("run", "()V") + } +} + +func PointerFromRunnable(ptr Runnable_ITF) *androidextras.QAndroidJniObject { + if ptr != nil { + return ptr.Runnable_PTR().Pointer() + } + return nil +} + +func NewRunnableFromPointer(ptr androidextras.QAndroidJniObject_ITF) *Runnable { + var n = new(Runnable) + n.SetPointer(ptr.QAndroidJniObject_PTR()) + return n +} + +func (ptr *Runnable) Runnable_PTR() *Runnable { + return ptr +} + +func Runnable__IsClassAvailable() bool { + return androidextras.QAndroidJniObject_IsClassAvailable("java/lang/Runnable") +} + +func Runnable__IsQtClassAvailable() bool { + return androidextras.QAndroidJniObject_IsClassAvailable("qt/java/lang/Runnable") +} + +func (ptr *Runnable) SetObjectName(n string) { + if ptr.Pointer() != nil && ptr.Pointer().IsValid() { + ptr.Pointer().SetField2("ObjectName", "Ljava/lang/String;", n) + } +} + +func (ptr *Runnable) ObjectName() string { + if ptr.Pointer() != nil && ptr.Pointer().IsValid() { + return ptr.Pointer().GetObjectField2("ObjectName", "Ljava/lang/String;").ToString() + } + return "" +} + +func NewQtRunnable() *Runnable { + return NewRunnableFromPointer(androidextras.NewQAndroidJniObject3("qt/java/lang/Runnable", "()V")) +} +func NewRunnable() *Runnable { + return NewRunnableFromPointer(androidextras.NewQAndroidJniObject3("java/lang/Runnable", "()V")) +} diff --git a/main.go b/main.go index 36009b73..3de0ec4e 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "cwtch.im/ui/go/characters" "cwtch.im/ui/go/gobjects" "cwtch.im/ui/go/gothings" + "cwtch.im/ui/go/gothings/android" "cwtch.im/ui/go/the" "flag" "fmt" @@ -111,7 +112,7 @@ func main() { } engine.RootContext().SetContextProperty("gcd", gcd) - var androidCwtchActivity = gothings.NewAndroidCwtchActivity(nil) + var androidCwtchActivity = android.NewCwtchActivity(nil) engine.RootContext().SetContextProperty("androidCwtchActivity", androidCwtchActivity) engine.Load(qmlSource) From 8a666a7f37aebab0aaa692587ce93f5ea66d292a Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Thu, 9 May 2019 14:45:02 -0700 Subject: [PATCH 2/4] starts a go service --- android/AndroidManifest.xml | 40 +++++ .../openprivacy/cwtch/ui/CwtchActivity.java | 26 ++- .../cwtch/ui/CwtchIntentService.java | 34 ---- .../ca/openprivacy/cwtch/ui/CwtchService.java | 15 ++ .../src/ca/openprivacy/cwtch/ui/Runnable.java | 14 -- go/gothings/android/CwtchService.go | 27 --- go/gothings/android/runnable.go | 98 ---------- main.go | 167 +++++++++++------- 8 files changed, 174 insertions(+), 247 deletions(-) delete mode 100644 android/src/ca/openprivacy/cwtch/ui/CwtchIntentService.java create mode 100644 android/src/ca/openprivacy/cwtch/ui/CwtchService.java delete mode 100644 android/src/ca/openprivacy/cwtch/ui/Runnable.java delete mode 100644 go/gothings/android/CwtchService.go delete mode 100644 go/gothings/android/runnable.go diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index de3dbbab..ad2b8849 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -63,7 +63,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -75,6 +114,7 @@ + diff --git a/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java b/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java index ef721874..5936c34b 100644 --- a/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java +++ b/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java @@ -1,11 +1,13 @@ -package ca.openprivcy.cwtch.ui; +package ca.openprivacy.cwtch.ui; import android.app.Notification; import android.app.NotificationManager; import android.app.NotificationChannel; import android.content.Context; import android.content.Intent; - +import android.util.Log; +import android.os.Bundle; +import android.content.ComponentName; import static android.app.Notification.DEFAULT_LIGHTS; import static android.app.Notification.DEFAULT_SOUND; @@ -16,7 +18,7 @@ import static android.content.Context.NOTIFICATION_SERVICE; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.os.Build.VERSION.SDK_INT; -import static android.app.Notification.CATEGORY_SERVICE;SS +import static android.app.Notification.CATEGORY_SERVICE; public class CwtchActivity extends org.qtproject.qt5.android.bindings.QtActivity { @@ -37,12 +39,22 @@ public class CwtchActivity extends org.qtproject.qt5.android.bindings.QtActivity private static String CONTENT_NOTIFICATION_ID_NAME = "content"; - public CwtchActivity() - { + public CwtchActivity() { m_instance = this; + } - /*Intent intent = new Intent(this, CwtchService.class); - startService(intent);*/ + // https://github.com/bbernhard/qtandroidservices_example/blob/master/source/java/MyCustomAppActivity.java + @Override + public void onCreate(Bundle bundle) { + super.onCreate(bundle); + Log.i("CwtchActivity", "Starting service!"); + Intent serviceIntent = new Intent(this, ca.openprivacy.cwtch.ui.CwtchService.class); + ComponentName ret = startService(serviceIntent); + if (ret == null) { + Log.i("CwtchActivity", "Started Service: FAILED with null"); + } else { + Log.i("CwtchActivity", "Started Service: " + ret.flattenToString()); + } } public static void notify(String s) diff --git a/android/src/ca/openprivacy/cwtch/ui/CwtchIntentService.java b/android/src/ca/openprivacy/cwtch/ui/CwtchIntentService.java deleted file mode 100644 index 411ac359..00000000 --- a/android/src/ca/openprivacy/cwtch/ui/CwtchIntentService.java +++ /dev/null @@ -1,34 +0,0 @@ -package ca.openprivcy.cwtch.ui; - -import android.app.IntentService; -import android.content.Intent; -import android.util.Log; - -public class CwtchIntentService extends IntentService { - - /** - * A constructor is required, and must call the super IntentService(String) - * constructor with a name for the worker thread. - */ - public CwtchIntentService() { - super("CwtchIntentService"); - } - - /** - * The IntentService calls this method from the default worker thread with - * the intent that started the service. When this method returns, IntentService - * stops the service, as appropriate. - */ - @Override - protected void onHandleIntent(Intent intent) { - // Normally we would do some work here, like download a file. - // For our sample, we just sleep for 5 seconds. - try { - Log.i("CwtchIntentService", "onHandleIntent!!!!!!"); - } catch (Exception e) { //InterruptedException e) { - // Restore interrupt status. - Thread.currentThread().interrupt(); - } - } -} - diff --git a/android/src/ca/openprivacy/cwtch/ui/CwtchService.java b/android/src/ca/openprivacy/cwtch/ui/CwtchService.java new file mode 100644 index 00000000..13601b45 --- /dev/null +++ b/android/src/ca/openprivacy/cwtch/ui/CwtchService.java @@ -0,0 +1,15 @@ +package ca.openprivacy.cwtch.ui; + + +import android.app.IntentService; +import android.content.Intent; +import android.util.Log; +import android.content.Context; +import android.content.Intent; +import org.qtproject.qt5.android.bindings.QtService; + +// https://github.com/bbernhard/qtandroidservices_example +public class CwtchService extends QtService { + +} + diff --git a/android/src/ca/openprivacy/cwtch/ui/Runnable.java b/android/src/ca/openprivacy/cwtch/ui/Runnable.java deleted file mode 100644 index dfda506e..00000000 --- a/android/src/ca/openprivacy/cwtch/ui/Runnable.java +++ /dev/null @@ -1,14 +0,0 @@ -package ca.openprivcy.cwtch.ui; - -public class Runnable implements java.lang.Runnable { - static { - System.loadLibrary("go"); - } - public String ObjectName; - - public static native void qtrun(qt.java.lang.Runnable me); - @Override - public void run() { - qtrun(this); - } -} \ No newline at end of file diff --git a/go/gothings/android/CwtchService.go b/go/gothings/android/CwtchService.go deleted file mode 100644 index a6034423..00000000 --- a/go/gothings/android/CwtchService.go +++ /dev/null @@ -1,27 +0,0 @@ -package android - -import ( - "git.openprivacy.ca/openprivacy/libricochet-go/log" - "github.com/therecipe/qt/androidextras" - "time" -) - -type CwtchService struct { - androidextras.QAndroidService - //core.QObject - - //_ func() `constructor:"init"` -} - -func (cs *CwtchService) onCreate() { - log.Infof("CwtchService onCreate()\n") - - go func() { - i := 0 - for true { - time.Sleep(2 * time.Second) - log.Infof("CwtchService thread iteration %d\n", i) - i++ - } - }() -} diff --git a/go/gothings/android/runnable.go b/go/gothings/android/runnable.go deleted file mode 100644 index 6ad133a2..00000000 --- a/go/gothings/android/runnable.go +++ /dev/null @@ -1,98 +0,0 @@ -package android - -import "C" -import ( - "unsafe" - - "github.com/therecipe/qt" - "github.com/therecipe/qt/androidextras" -) - -type Runnable struct { - ptr *androidextras.QAndroidJniObject -} - -type Runnable_ITF interface { - Runnable_PTR() *Runnable -} - -func (p *Runnable) Pointer() *androidextras.QAndroidJniObject { - return p.ptr -} - -func (p *Runnable) SetPointer(ptr *androidextras.QAndroidJniObject) { - p.ptr = ptr -} - -func (ptr *Runnable) ConnectRun(f func()) { - if ptr.Pointer() != nil && ptr.Pointer().IsValid() { - - qt.ConnectSignal(ptr.Pointer().ToString(), "Runnable::run", unsafe.Pointer(&f)) - } -} - -func (ptr *Runnable) DisconnectRun() { - if ptr.Pointer() != nil && ptr.Pointer().IsValid() { - - qt.DisconnectSignal(ptr.Pointer().ToString(), "Runnable::run") - } -} - -//export Java_qt_java_lang_Runnable_qtrun -func Java_qt_java_lang_Runnable_qtrun(_, _, this unsafe.Pointer) { - if signal := qt.GetSignal(androidextras.NewQAndroidJniObject6(this).ToString(), "Runnable::run"); signal != nil { - (*(*func())(signal))() - } - -} - -func (ptr *Runnable) Run() { - if ptr.Pointer() != nil && ptr.Pointer().IsValid() { - ptr.Pointer().CallMethodVoid2("run", "()V") - } -} - -func PointerFromRunnable(ptr Runnable_ITF) *androidextras.QAndroidJniObject { - if ptr != nil { - return ptr.Runnable_PTR().Pointer() - } - return nil -} - -func NewRunnableFromPointer(ptr androidextras.QAndroidJniObject_ITF) *Runnable { - var n = new(Runnable) - n.SetPointer(ptr.QAndroidJniObject_PTR()) - return n -} - -func (ptr *Runnable) Runnable_PTR() *Runnable { - return ptr -} - -func Runnable__IsClassAvailable() bool { - return androidextras.QAndroidJniObject_IsClassAvailable("java/lang/Runnable") -} - -func Runnable__IsQtClassAvailable() bool { - return androidextras.QAndroidJniObject_IsClassAvailable("qt/java/lang/Runnable") -} - -func (ptr *Runnable) SetObjectName(n string) { - if ptr.Pointer() != nil && ptr.Pointer().IsValid() { - ptr.Pointer().SetField2("ObjectName", "Ljava/lang/String;", n) - } -} - -func (ptr *Runnable) ObjectName() string { - if ptr.Pointer() != nil && ptr.Pointer().IsValid() { - return ptr.Pointer().GetObjectField2("ObjectName", "Ljava/lang/String;").ToString() - } - return "" -} - -func NewQtRunnable() *Runnable { - return NewRunnableFromPointer(androidextras.NewQAndroidJniObject3("qt/java/lang/Runnable", "()V")) -} -func NewRunnable() *Runnable { - return NewRunnableFromPointer(androidextras.NewQAndroidJniObject3("java/lang/Runnable", "()V")) -} diff --git a/main.go b/main.go index 3de0ec4e..15f9f2b6 100644 --- a/main.go +++ b/main.go @@ -21,6 +21,7 @@ import ( "path" "path/filepath" "runtime" + "time" ) const androidBaseDir = "/data/data/ca.openprivacy.cwtch.ui/" @@ -36,8 +37,10 @@ func init() { } func main() { + log.Infoln("ui main()\n") flagDebug := flag.Bool("debug", false, "turn on extra logging. WARNING: THIS MAY EXPOSE PRIVATE INFORMATION IN CONSOLE OUTPUT!") flagLocal := flag.Bool("local", false, "load user interface from the local folder \"qml\" instead of the built-in UI") + flagService := flag.Bool("service", false, "indicate this process should run as an android service") flag.Parse() if *flagDebug { @@ -46,83 +49,113 @@ func main() { log.SetLevel(log.LevelInfo) } - // our globals - gcd := gothings.NewGrandCentralDispatcher(nil) - gcd.SetOs(runtime.GOOS) - if buildVer != "" { - gcd.SetVersion(buildVer) - gcd.SetBuildDate(buildDate) + log.Infof("cwtch main args: %v\n", os.Args) + + if *flagService { + log.Infoln("I am the service") + torpath := path.Join(androidBaseDir, "lib/libtor.so") + log.Infoln("Starting Tor...") + acn, _ := connectivity.StartTor(the.CwtchDir, torpath) + log.Infoln("Starting a cwtch app...") + the.CwtchApp = libapp.NewApp(acn, the.CwtchDir) + + log.Infoln("Sleepinging???") + for true { + time.Sleep(5 * time.Second) + log.Infoln("Wake up, repeat") + } + } else { - gcd.SetVersion("development") - gcd.SetBuildDate("now") - } - gcd.UIState = gothings.NewUIState(gcd) - the.AcknowledgementIDs = make(map[string][]*the.AckId) - gcd.OutgoingMessages = make(chan gobjects.Letter, 1000) + log.Infoln("I am the application") - //TODO: put theme stuff somewhere better - gcd.SetThemeScale(1.0) + app := gui.NewQGuiApplication(len(os.Args), os.Args) - // this is to load local qml files quickly when developing - var qmlSource *core.QUrl - if *flagLocal { - qmlSource = core.QUrl_FromLocalFile("./qml/main.qml") - } else { - qmlSource = core.NewQUrl3("qrc:/qml/main.qml", 0) - } + // our globals + gcd := gothings.NewGrandCentralDispatcher(nil) + gcd.SetOs(runtime.GOOS) + if buildVer != "" { + gcd.SetVersion(buildVer) + gcd.SetBuildDate(buildDate) + } else { + gcd.SetVersion("development") + gcd.SetBuildDate("now") + } + gcd.UIState = gothings.NewUIState(gcd) + the.AcknowledgementIDs = make(map[string][]*the.AckId) + gcd.OutgoingMessages = make(chan gobjects.Letter, 1000) - app := gui.NewQGuiApplication(len(os.Args), os.Args) - app.SetWindowIcon(gui.NewQIcon5(":/qml/images/cwtch-icon.png")) - - // load english first so it becomes the default in case we don't have a .ts for the user's locale, or if it contains unfinished strings - translator := core.NewQTranslator(nil) - translator.Load("translation_en", ":/i18n/", "", "") - core.QCoreApplication_InstallTranslator(translator) - - gcd.Translator = core.NewQTranslator(nil) - gcd.Translator.Load("translation_"+core.QLocale_System().Name(), ":/i18n/", "", "") - core.QCoreApplication_InstallTranslator(gcd.Translator) - - core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true) - quickcontrols2.QQuickStyle_SetStyle("Universe") - engine := qml.NewQQmlApplicationEngine(nil) - gcd.QMLEngine = engine - - // prevent qt from initiating network connections (possible deanon attempts!) - factory := qml.NewQQmlNetworkAccessManagerFactory() - factory.ConnectCreate(func(parent *core.QObject) *network.QNetworkAccessManager { - nam := network.NewQNetworkAccessManager(parent) - nam.SetNetworkAccessible(network.QNetworkAccessManager__NotAccessible) - proxy := network.NewQNetworkProxy() - proxy.SetHostName("0.0.0.0") - nam.SetProxy(proxy) - //nam.ConnectCreateRequest(func(op network.QNetworkAccessManager__Operation, originalReq *network.QNetworkRequest, outgoingData *core.QIODevice) *network.QNetworkReply { - // log.Errorf("network access request detected - possible remote content insertion bug!!!") - // return nil - //}) - return nam - }) - engine.SetNetworkAccessManagerFactory(factory) - - // variables we want to access from inside qml - if runtime.GOOS == "android" { - gcd.SetThemeScale(2.9) - } else { + //TODO: put theme stuff somewhere better gcd.SetThemeScale(1.0) + + // this is to load local qml files quickly when developing + var qmlSource *core.QUrl + if *flagLocal { + qmlSource = core.QUrl_FromLocalFile("./qml/main.qml") + } else { + qmlSource = core.NewQUrl3("qrc:/qml/main.qml", 0) + } + + app.SetWindowIcon(gui.NewQIcon5(":/qml/images/cwtch-icon.png")) + + // load english first so it becomes the default in case we don't have a .ts for the user's locale, or if it contains unfinished strings + translator := core.NewQTranslator(nil) + translator.Load("translation_en", ":/i18n/", "", "") + core.QCoreApplication_InstallTranslator(translator) + + gcd.Translator = core.NewQTranslator(nil) + gcd.Translator.Load("translation_"+core.QLocale_System().Name(), ":/i18n/", "", "") + core.QCoreApplication_InstallTranslator(gcd.Translator) + + core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true) + quickcontrols2.QQuickStyle_SetStyle("Universe") + engine := qml.NewQQmlApplicationEngine(nil) + gcd.QMLEngine = engine + + // prevent qt from initiating network connections (possible deanon attempts!) + factory := qml.NewQQmlNetworkAccessManagerFactory() + factory.ConnectCreate(func(parent *core.QObject) *network.QNetworkAccessManager { + nam := network.NewQNetworkAccessManager(parent) + nam.SetNetworkAccessible(network.QNetworkAccessManager__NotAccessible) + proxy := network.NewQNetworkProxy() + proxy.SetHostName("0.0.0.0") + nam.SetProxy(proxy) + //nam.ConnectCreateRequest(func(op network.QNetworkAccessManager__Operation, originalReq *network.QNetworkRequest, outgoingData *core.QIODevice) *network.QNetworkReply { + // log.Errorf("network access request detected - possible remote content insertion bug!!!") + // return nil + //}) + return nam + }) + engine.SetNetworkAccessManagerFactory(factory) + + // variables we want to access from inside qml + if runtime.GOOS == "android" { + gcd.SetThemeScale(2.9) + } else { + gcd.SetThemeScale(1.0) + } + engine.RootContext().SetContextProperty("gcd", gcd) + + var androidCwtchActivity = android.NewCwtchActivity(nil) + engine.RootContext().SetContextProperty("androidCwtchActivity", androidCwtchActivity) + /*if runtime.GOOS == "android" { + androidCwtchActivity.StartCwtchService() + }*/ + + //engine.addImportPath(QStringLiteral("qrc:/")); + //engine.load(QUrl(QStringLiteral("qrc:/source/qml/main.qml"))); + + engine.Load(qmlSource) + + the.ACN = nil + go loadNetworkingAndFiles(gcd) + + app.Exec() } - engine.RootContext().SetContextProperty("gcd", gcd) - - var androidCwtchActivity = android.NewCwtchActivity(nil) - engine.RootContext().SetContextProperty("androidCwtchActivity", androidCwtchActivity) - - engine.Load(qmlSource) - the.ACN = nil - go loadNetworkingAndFiles(gcd) - app.Exec() if the.ACN != nil { the.ACN.Close() } + log.Infoln("Exiting main()") } func loadNetworkingAndFiles(gcd *gothings.GrandCentralDispatcher) { From 9400d5aa63061e609d1ba2939d0f6964535954d9 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Mon, 13 May 2019 14:01:08 -0700 Subject: [PATCH 3/4] refactoring of main to mainUi() and mainService() --- main.go | 231 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 119 insertions(+), 112 deletions(-) diff --git a/main.go b/main.go index 15f9f2b6..ed6327a8 100644 --- a/main.go +++ b/main.go @@ -8,7 +8,6 @@ import ( "cwtch.im/ui/go/gothings/android" "cwtch.im/ui/go/the" "flag" - "fmt" "git.openprivacy.ca/openprivacy/libricochet-go/connectivity" "git.openprivacy.ca/openprivacy/libricochet-go/log" "github.com/therecipe/qt/core" @@ -49,116 +48,6 @@ func main() { log.SetLevel(log.LevelInfo) } - log.Infof("cwtch main args: %v\n", os.Args) - - if *flagService { - log.Infoln("I am the service") - torpath := path.Join(androidBaseDir, "lib/libtor.so") - log.Infoln("Starting Tor...") - acn, _ := connectivity.StartTor(the.CwtchDir, torpath) - log.Infoln("Starting a cwtch app...") - the.CwtchApp = libapp.NewApp(acn, the.CwtchDir) - - log.Infoln("Sleepinging???") - for true { - time.Sleep(5 * time.Second) - log.Infoln("Wake up, repeat") - } - - } else { - log.Infoln("I am the application") - - app := gui.NewQGuiApplication(len(os.Args), os.Args) - - // our globals - gcd := gothings.NewGrandCentralDispatcher(nil) - gcd.SetOs(runtime.GOOS) - if buildVer != "" { - gcd.SetVersion(buildVer) - gcd.SetBuildDate(buildDate) - } else { - gcd.SetVersion("development") - gcd.SetBuildDate("now") - } - gcd.UIState = gothings.NewUIState(gcd) - the.AcknowledgementIDs = make(map[string][]*the.AckId) - gcd.OutgoingMessages = make(chan gobjects.Letter, 1000) - - //TODO: put theme stuff somewhere better - gcd.SetThemeScale(1.0) - - // this is to load local qml files quickly when developing - var qmlSource *core.QUrl - if *flagLocal { - qmlSource = core.QUrl_FromLocalFile("./qml/main.qml") - } else { - qmlSource = core.NewQUrl3("qrc:/qml/main.qml", 0) - } - - app.SetWindowIcon(gui.NewQIcon5(":/qml/images/cwtch-icon.png")) - - // load english first so it becomes the default in case we don't have a .ts for the user's locale, or if it contains unfinished strings - translator := core.NewQTranslator(nil) - translator.Load("translation_en", ":/i18n/", "", "") - core.QCoreApplication_InstallTranslator(translator) - - gcd.Translator = core.NewQTranslator(nil) - gcd.Translator.Load("translation_"+core.QLocale_System().Name(), ":/i18n/", "", "") - core.QCoreApplication_InstallTranslator(gcd.Translator) - - core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true) - quickcontrols2.QQuickStyle_SetStyle("Universe") - engine := qml.NewQQmlApplicationEngine(nil) - gcd.QMLEngine = engine - - // prevent qt from initiating network connections (possible deanon attempts!) - factory := qml.NewQQmlNetworkAccessManagerFactory() - factory.ConnectCreate(func(parent *core.QObject) *network.QNetworkAccessManager { - nam := network.NewQNetworkAccessManager(parent) - nam.SetNetworkAccessible(network.QNetworkAccessManager__NotAccessible) - proxy := network.NewQNetworkProxy() - proxy.SetHostName("0.0.0.0") - nam.SetProxy(proxy) - //nam.ConnectCreateRequest(func(op network.QNetworkAccessManager__Operation, originalReq *network.QNetworkRequest, outgoingData *core.QIODevice) *network.QNetworkReply { - // log.Errorf("network access request detected - possible remote content insertion bug!!!") - // return nil - //}) - return nam - }) - engine.SetNetworkAccessManagerFactory(factory) - - // variables we want to access from inside qml - if runtime.GOOS == "android" { - gcd.SetThemeScale(2.9) - } else { - gcd.SetThemeScale(1.0) - } - engine.RootContext().SetContextProperty("gcd", gcd) - - var androidCwtchActivity = android.NewCwtchActivity(nil) - engine.RootContext().SetContextProperty("androidCwtchActivity", androidCwtchActivity) - /*if runtime.GOOS == "android" { - androidCwtchActivity.StartCwtchService() - }*/ - - //engine.addImportPath(QStringLiteral("qrc:/")); - //engine.load(QUrl(QStringLiteral("qrc:/source/qml/main.qml"))); - - engine.Load(qmlSource) - - the.ACN = nil - go loadNetworkingAndFiles(gcd) - - app.Exec() - } - - if the.ACN != nil { - the.ACN.Close() - } - log.Infoln("Exiting main()") -} - -func loadNetworkingAndFiles(gcd *gothings.GrandCentralDispatcher) { if os.Getenv("CWTCH_FOLDER") != "" { the.CwtchDir = os.Getenv("CWTCH_FOLDER") } else if runtime.GOOS == "android" { @@ -166,12 +55,123 @@ func loadNetworkingAndFiles(gcd *gothings.GrandCentralDispatcher) { } else { usr, err := user.Current() if err != nil { - fmt.Printf("\nerror: could not load current user: %v\n", err) + log.Errorf("\nerror: could not load current user: %v\n", err) os.Exit(1) } the.CwtchDir = path.Join(usr.HomeDir, ".cwtch") } + the.ACN = nil + if *flagService { + mainService() + + } else { + mainUi(*flagLocal) + } + + if the.ACN != nil { + the.ACN.Close() + } +} + +func mainService() { + log.Infoln("I am the service") + loadACN() + log.Infoln("Starting a cwtch app...") + the.CwtchApp = libapp.NewApp(the.ACN, the.CwtchDir) + + log.Infoln("Sleepinging???") + for true { + time.Sleep(5 * time.Second) + log.Infoln("Wake up, repeat") + } +} + +func mainUi(flagLocal bool) { + log.Infoln("I am the application") + + app := gui.NewQGuiApplication(len(os.Args), os.Args) + + // our globals + gcd := gothings.NewGrandCentralDispatcher(nil) + gcd.SetOs(runtime.GOOS) + if buildVer != "" { + gcd.SetVersion(buildVer) + gcd.SetBuildDate(buildDate) + } else { + gcd.SetVersion("development") + gcd.SetBuildDate("now") + } + gcd.UIState = gothings.NewUIState(gcd) + the.AcknowledgementIDs = make(map[string][]*the.AckId) + gcd.OutgoingMessages = make(chan gobjects.Letter, 1000) + + //TODO: put theme stuff somewhere better + gcd.SetThemeScale(1.0) + + // this is to load local qml files quickly when developing + var qmlSource *core.QUrl + if flagLocal { + qmlSource = core.QUrl_FromLocalFile("./qml/main.qml") + } else { + qmlSource = core.NewQUrl3("qrc:/qml/main.qml", 0) + } + + app.SetWindowIcon(gui.NewQIcon5(":/qml/images/cwtch-icon.png")) + + // load english first so it becomes the default in case we don't have a .ts for the user's locale, or if it contains unfinished strings + translator := core.NewQTranslator(nil) + translator.Load("translation_en", ":/i18n/", "", "") + core.QCoreApplication_InstallTranslator(translator) + + gcd.Translator = core.NewQTranslator(nil) + gcd.Translator.Load("translation_"+core.QLocale_System().Name(), ":/i18n/", "", "") + core.QCoreApplication_InstallTranslator(gcd.Translator) + + core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true) + quickcontrols2.QQuickStyle_SetStyle("Universe") + engine := qml.NewQQmlApplicationEngine(nil) + gcd.QMLEngine = engine + + // prevent qt from initiating network connections (possible deanon attempts!) + factory := qml.NewQQmlNetworkAccessManagerFactory() + factory.ConnectCreate(func(parent *core.QObject) *network.QNetworkAccessManager { + nam := network.NewQNetworkAccessManager(parent) + nam.SetNetworkAccessible(network.QNetworkAccessManager__NotAccessible) + proxy := network.NewQNetworkProxy() + proxy.SetHostName("0.0.0.0") + nam.SetProxy(proxy) + //nam.ConnectCreateRequest(func(op network.QNetworkAccessManager__Operation, originalReq *network.QNetworkRequest, outgoingData *core.QIODevice) *network.QNetworkReply { + // log.Errorf("network access request detected - possible remote content insertion bug!!!") + // return nil + //}) + return nam + }) + engine.SetNetworkAccessManagerFactory(factory) + + // variables we want to access from inside qml + if runtime.GOOS == "android" { + gcd.SetThemeScale(2.9) + } else { + gcd.SetThemeScale(1.0) + } + engine.RootContext().SetContextProperty("gcd", gcd) + + var androidCwtchActivity = android.NewCwtchActivity(nil) + engine.RootContext().SetContextProperty("androidCwtchActivity", androidCwtchActivity) + + //engine.addImportPath(QStringLiteral("qrc:/")); + //engine.load(QUrl(QStringLiteral("qrc:/source/qml/main.qml"))); + + engine.Load(qmlSource) + + go loadNetworkingAndFiles(gcd) + + app.Exec() + +} + +func loadACN() { torpath := "tor" if runtime.GOOS == "android" { torpath = path.Join(androidBaseDir, "lib/libtor.so") @@ -197,8 +197,15 @@ func loadNetworkingAndFiles(gcd *gothings.GrandCentralDispatcher) { log.Errorf("Could not start Tor: %v", err) os.Exit(1) } +} + +func loadNetworkingAndFiles(gcd *gothings.GrandCentralDispatcher) { + if runtime.GOOS != "android" { + loadACN() + } the.Peer = nil + os.MkdirAll(the.CwtchDir, 0700) the.CwtchApp = libapp.NewApp(the.ACN, the.CwtchDir) From 75111e0421ae2bf74149cd4062ff2a54e11086e5 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Fri, 21 Jun 2019 14:58:40 -0700 Subject: [PATCH 4/4] port from cwtch.app to appClient and appService --- android/AndroidManifest.xml | 4 +- go/characters/torstatuspoller.go | 3 ++ go/the/globals.go | 2 + main.go | 72 ++++++++++++++++++++++---------- 4 files changed, 58 insertions(+), 23 deletions(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index ad2b8849..5c222929 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,7 +1,9 @@ - + diff --git a/go/characters/torstatuspoller.go b/go/characters/torstatuspoller.go index 135f441d..9fe7950c 100644 --- a/go/characters/torstatuspoller.go +++ b/go/characters/torstatuspoller.go @@ -6,6 +6,9 @@ import ( ) func TorStatusPoller(setTorStatus func(int, string), acn connectivity.ACN) { + if acn == nil { + return + } for { time.Sleep(time.Second) diff --git a/go/the/globals.go b/go/the/globals.go index 2d75bd7c..a4239d08 100644 --- a/go/the/globals.go +++ b/go/the/globals.go @@ -8,11 +8,13 @@ import ( ) var CwtchApp app.Application +var CwtchService app.ApplicationService var EventBus event.Manager var AppBus event.Manager var ACN connectivity.ACN var Peer libPeer.CwtchPeer var CwtchDir string +var IPCBridge event.IPCBridge type AckId struct { ID string diff --git a/main.go b/main.go index ed6327a8..9ee3c276 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( libapp "cwtch.im/cwtch/app" + "cwtch.im/cwtch/event/bridge" "cwtch.im/ui/go/characters" "cwtch.im/ui/go/gobjects" "cwtch.im/ui/go/gothings" @@ -20,7 +21,6 @@ import ( "path" "path/filepath" "runtime" - "time" ) const androidBaseDir = "/data/data/ca.openprivacy.cwtch.ui/" @@ -48,6 +48,12 @@ func main() { log.SetLevel(log.LevelInfo) } + // TESTING + log.SetLevel(log.LevelDebug) + log.ExcludeFromPattern("connection/connection") + log.ExcludeFromPattern("outbound/3dhauthchannel") + log.ExcludeFromPattern("event/eventmanager") + if os.Getenv("CWTCH_FOLDER") != "" { the.CwtchDir = os.Getenv("CWTCH_FOLDER") } else if runtime.GOOS == "android" { @@ -61,6 +67,11 @@ func main() { the.CwtchDir = path.Join(usr.HomeDir, ".cwtch") } the.ACN = nil + the.Peer = nil + the.IPCBridge = nil + the.CwtchApp = nil + the.CwtchService = nil + os.MkdirAll(the.CwtchDir, 0700) if *flagService { mainService() @@ -76,15 +87,14 @@ func main() { func mainService() { log.Infoln("I am the service") - loadACN() log.Infoln("Starting a cwtch app...") - the.CwtchApp = libapp.NewApp(the.ACN, the.CwtchDir) + go loadNetworkingAndFiles(nil, true) + + //app := androidextras.NewQAndroidService(len(os.Args), os.Args) + app := gui.NewQGuiApplication(len(os.Args), os.Args) + log.Infoln("Cwtch Service starting app.Exec") + app.Exec() - log.Infoln("Sleepinging???") - for true { - time.Sleep(5 * time.Second) - log.Infoln("Wake up, repeat") - } } func mainUi(flagLocal bool) { @@ -160,13 +170,11 @@ func mainUi(flagLocal bool) { var androidCwtchActivity = android.NewCwtchActivity(nil) engine.RootContext().SetContextProperty("androidCwtchActivity", androidCwtchActivity) - //engine.addImportPath(QStringLiteral("qrc:/")); - //engine.load(QUrl(QStringLiteral("qrc:/source/qml/main.qml"))); - engine.Load(qmlSource) - go loadNetworkingAndFiles(gcd) + go loadNetworkingAndFiles(gcd, false) + log.Infoln("Cwtch App starting app.Exec") app.Exec() } @@ -199,17 +207,37 @@ func loadACN() { } } -func loadNetworkingAndFiles(gcd *gothings.GrandCentralDispatcher) { - if runtime.GOOS != "android" { +func loadNetworkingAndFiles(gcd *gothings.GrandCentralDispatcher, service bool) { + if runtime.GOOS == "android" { + clientIn := path.Join(the.CwtchDir, "clientIn") + serviceIn := path.Join(the.CwtchDir, "serviceIn") + if service { + loadACN() + serviceBridge, err := bridge.NewPipeBridgeService(serviceIn, clientIn) + if err != nil { + log.Errorf("Could not create service bridge: %v\n", err) + os.Exit(1) + } + log.Infoln("Creating New App Service") + the.CwtchService = libapp.NewAppService(the.ACN, the.CwtchDir, serviceBridge) + } else { + clientBridge, err := bridge.NewPipeBridgeClient(clientIn, serviceIn) + if err != nil { + log.Errorf("Could not create client bridge: %v\n", err) + os.Exit(1) + } + log.Infoln("Creating New App Client") + the.CwtchApp = libapp.NewAppClient(the.CwtchDir, clientBridge) + } + } else { loadACN() + log.Infoln("Creating New App") + the.CwtchApp = libapp.NewApp(the.ACN, the.CwtchDir) } - the.Peer = nil - - os.MkdirAll(the.CwtchDir, 0700) - - the.CwtchApp = libapp.NewApp(the.ACN, the.CwtchDir) - the.AppBus = the.CwtchApp.GetPrimaryBus() - go characters.AppEventListener(gcd) - the.CwtchApp.LoadProfiles("be gay do crime") + if !service { + the.AppBus = the.CwtchApp.GetPrimaryBus() + go characters.AppEventListener(gcd) + the.CwtchApp.LoadProfiles("be gay do crime") + } }