From 5a2da4794dddf9679203820eb124963f21a13226 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 4 Nov 2019 13:20:44 +0100 Subject: [PATCH 1/9] Use GeckoWebExecutor for FxA Services --- .../org/mozilla/vrbrowser/browser/Services.kt | 5 +- .../browser/engine/EngineProvider.kt | 68 +++++++++++++++++++ .../browser/engine/SessionStore.java | 51 +------------- 3 files changed, 75 insertions(+), 49 deletions(-) create mode 100644 app/src/common/shared/org/mozilla/vrbrowser/browser/engine/EngineProvider.kt diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt index cf92d931a..7979e21f4 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt @@ -28,6 +28,9 @@ import org.mozilla.geckoview.AllowOrDeny import org.mozilla.geckoview.GeckoResult import org.mozilla.geckoview.GeckoSession import org.mozilla.vrbrowser.R +import org.mozilla.vrbrowser.browser.engine.EngineProvider +import org.mozilla.vrbrowser.browser.engine.GeckoViewFetchClient +import org.mozilla.vrbrowser.browser.engine.SessionStore class Services(context: Context, places: Places): GeckoSession.NavigationDelegate { companion object { @@ -43,7 +46,7 @@ class Services(context: Context, places: Places): GeckoSession.NavigationDelegat // This makes bookmarks storage accessible to background sync workers. init { RustLog.enable() - RustHttpConfig.setClient(lazy { HttpURLConnectionClient() }) + RustHttpConfig.setClient(lazy { EngineProvider.createClient(context) }) // Make sure we get logs out of our android-components. Log.addSink(AndroidLogSink()) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/EngineProvider.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/EngineProvider.kt new file mode 100644 index 000000000..552099f68 --- /dev/null +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/EngineProvider.kt @@ -0,0 +1,68 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.vrbrowser.browser.engine + +import android.content.Context +import mozilla.components.concept.fetch.Client +import org.mozilla.geckoview.ContentBlocking +import org.mozilla.geckoview.GeckoRuntime +import org.mozilla.geckoview.GeckoRuntimeSettings +import org.mozilla.geckoview.WebExtension +import org.mozilla.vrbrowser.BuildConfig +import org.mozilla.vrbrowser.browser.SettingsStore +import org.mozilla.vrbrowser.crashreporting.CrashReporterService + +object EngineProvider { + + private val WEB_EXTENSIONS = arrayOf("webcompat_vimeo", "webcompat_youtube") + + private var runtime: GeckoRuntime? = null + + @Synchronized + fun getOrCreateRuntime(context: Context): GeckoRuntime { + if (runtime == null) { + val builder = GeckoRuntimeSettings.Builder() + + builder.crashHandler(CrashReporterService::class.java) + builder.contentBlocking(ContentBlocking.Settings.Builder() + .antiTracking(ContentBlocking.AntiTracking.AD or ContentBlocking.AntiTracking.SOCIAL or ContentBlocking.AntiTracking.ANALYTIC) + .build()) + builder.consoleOutput(SettingsStore.getInstance(context).isConsoleLogsEnabled) + builder.displayDensityOverride(SettingsStore.getInstance(context).displayDensity) + builder.remoteDebuggingEnabled(SettingsStore.getInstance(context).isRemoteDebuggingEnabled) + builder.displayDpiOverride(SettingsStore.getInstance(context).displayDpi) + builder.screenSizeOverride(SettingsStore.getInstance(context).maxWindowWidth, + SettingsStore.getInstance(context).maxWindowHeight) + builder.autoplayDefault(if (SettingsStore.getInstance(context).isAutoplayEnabled) GeckoRuntimeSettings.AUTOPLAY_DEFAULT_ALLOWED else GeckoRuntimeSettings.AUTOPLAY_DEFAULT_BLOCKED) + + if (SettingsStore.getInstance(context).transparentBorderWidth > 0) { + builder.useMaxScreenDepth(true) + } + + if (BuildConfig.DEBUG) { + builder.arguments(arrayOf("-purgecaches")) + builder.debugLogging(true) + builder.aboutConfigEnabled(true) + } else { + builder.debugLogging(SettingsStore.getInstance(context).isDebugLogginEnabled) + } + + runtime = GeckoRuntime.create(context, builder.build()) + for (extension in WEB_EXTENSIONS) { + val path = "resource://android/assets/web_extensions/$extension/" + runtime!!.registerWebExtension(WebExtension(path)) + } + + + } + + return runtime!! + } + + fun createClient(context: Context): Client { + val runtime = getOrCreateRuntime(context) + return GeckoViewFetchClient(context, runtime) + } +} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java index 54fe71303..7e9fc1ef0 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java @@ -14,8 +14,6 @@ import org.mozilla.geckoview.GeckoRuntime; import org.mozilla.geckoview.GeckoRuntimeSettings; import org.mozilla.geckoview.GeckoSession; -import org.mozilla.geckoview.WebExtension; -import org.mozilla.vrbrowser.BuildConfig; import org.mozilla.vrbrowser.VRBrowserApplication; import org.mozilla.vrbrowser.browser.BookmarksStore; import org.mozilla.vrbrowser.browser.HistoryStore; @@ -33,11 +31,6 @@ public class SessionStore implements GeckoSession.PermissionDelegate { private static final String LOGTAG = SystemUtils.createLogtag(SessionStore.class); private static final int MAX_GECKO_SESSIONS = 5; - private static final String[] WEB_EXTENSIONS = new String[] { - "webcompat_vimeo", - "webcompat_youtube" - }; - private static SessionStore mInstance; public static SessionStore get() { @@ -64,48 +57,10 @@ private SessionStore() { public void setContext(Context context, Bundle aExtras) { mContext = context; - if (mRuntime == null) { - // FIXME: Once GeckoView has a prefs API - SessionUtils.vrPrefsWorkAround(context, aExtras); - - GeckoRuntimeSettings.Builder runtimeSettingsBuilder = new GeckoRuntimeSettings.Builder(); - runtimeSettingsBuilder.crashHandler(CrashReporterService.class); - runtimeSettingsBuilder.contentBlocking((new ContentBlocking.Settings.Builder() - .antiTracking(ContentBlocking.AntiTracking.AD | ContentBlocking.AntiTracking.SOCIAL| ContentBlocking.AntiTracking.ANALYTIC)) - .build()); - runtimeSettingsBuilder.consoleOutput(SettingsStore.getInstance(context).isConsoleLogsEnabled()); - runtimeSettingsBuilder.displayDensityOverride(SettingsStore.getInstance(context).getDisplayDensity()); - runtimeSettingsBuilder.remoteDebuggingEnabled(SettingsStore.getInstance(context).isRemoteDebuggingEnabled()); - runtimeSettingsBuilder.displayDpiOverride(SettingsStore.getInstance(context).getDisplayDpi()); - runtimeSettingsBuilder.screenSizeOverride(SettingsStore.getInstance(context).getMaxWindowWidth(), - SettingsStore.getInstance(context).getMaxWindowHeight()); - runtimeSettingsBuilder.autoplayDefault(SettingsStore.getInstance(mContext).isAutoplayEnabled() ? GeckoRuntimeSettings.AUTOPLAY_DEFAULT_ALLOWED : GeckoRuntimeSettings.AUTOPLAY_DEFAULT_BLOCKED); - - if (SettingsStore.getInstance(context).getTransparentBorderWidth() > 0) { - runtimeSettingsBuilder.useMaxScreenDepth(true); - } - - if (BuildConfig.DEBUG) { - runtimeSettingsBuilder.arguments(new String[] { "-purgecaches" }); - runtimeSettingsBuilder.debugLogging(true); - runtimeSettingsBuilder.aboutConfigEnabled(true); - } else { - runtimeSettingsBuilder.debugLogging(SettingsStore.getInstance(context).isDebugLogginEnabled()); - } - - mRuntime = GeckoRuntime.create(context, runtimeSettingsBuilder.build()); - for (String extension: WEB_EXTENSIONS) { - String path = "resource://android/assets/web_extensions/" + extension + "/"; - mRuntime.registerWebExtension(new WebExtension(path)); - } - - } else { - mRuntime.attachTo(context); - } - } + mRuntime = EngineProvider.INSTANCE.getOrCreateRuntime(context); - public GeckoRuntime getRuntime() { - return mRuntime; + // FIXME: Once GeckoView has a prefs API + SessionUtils.vrPrefsWorkAround(context, aExtras); } public void initializeServices() { From 31acc244ea083c7c6c1359709e07d999fb74ba33 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 4 Nov 2019 13:40:05 +0100 Subject: [PATCH 2/9] Get rid of a complex getAuthicationUrlAsync Per https://github.com/MozillaReality/FirefoxReality/pull/1973#discussion_r337533325 --- .../org/mozilla/vrbrowser/browser/Accounts.kt | 50 ------------------- .../vrbrowser/ui/views/BookmarksView.java | 22 +++++--- .../vrbrowser/ui/views/HistoryView.java | 22 +++++--- .../ui/widgets/dialogs/WhatsNewWidget.java | 25 ++++++---- .../ui/widgets/settings/SettingsWidget.java | 22 +++++--- 5 files changed, 59 insertions(+), 82 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt index dcc78be64..f3d393fa5 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt @@ -21,12 +21,9 @@ import mozilla.components.service.fxa.manager.SyncEnginesStorage import mozilla.components.service.fxa.sync.SyncReason import mozilla.components.service.fxa.sync.SyncStatusObserver import mozilla.components.service.fxa.sync.getLastSynced -import mozilla.components.support.base.log.logger.Logger import org.mozilla.vrbrowser.VRBrowserApplication import org.mozilla.vrbrowser.utils.SystemUtils import java.util.concurrent.CompletableFuture -import java.util.concurrent.ExecutionException -import java.util.concurrent.Executors class Accounts constructor(val context: Context) { @@ -281,53 +278,6 @@ class Accounts constructor(val context: Context) { } } - fun getAuthenticationUrlAsync(): CompletableFuture { - val future: CompletableFuture = CompletableFuture() - - // If we're already logged-in, and not in a "need to reconnect" state, logout. - if (services.accountManager.authenticatedAccount() != null && !services.accountManager.accountNeedsReauth()) { - services.accountManager.logoutAsync() - future.complete(null) - } - - // Otherwise, obtain an authentication URL and load it in the gecko session. - // Recovering from "need to reconnect" state is treated the same as just logging in. - val futureUrl = authUrlAsync() - if (futureUrl == null) { - Logger(LOGTAG).debug("Got a 'null' futureUrl") - services.accountManager.logoutAsync() - future.complete(null) - } - - Executors.newSingleThreadExecutor().submit { - try { - val url = futureUrl!!.get() - if (url == null) { - Logger(LOGTAG).debug("Got a 'null' url after resolving futureUrl") - services.accountManager.logoutAsync() - future.complete(null) - } - Logger(LOGTAG).debug("Got an auth url: " + url!!) - - // Actually process the url on the main thread. - Handler(Looper.getMainLooper()).post { - Logger(LOGTAG).debug("We got an authentication url, we can continue...") - future.complete(url) - } - - } catch (e: ExecutionException) { - Logger(LOGTAG).debug("Error obtaining auth url", e) - future.complete(null) - - } catch (e: InterruptedException) { - Logger(LOGTAG).debug("Error obtaining auth url", e) - future.complete(null) - } - } - - return future - } - fun isEngineEnabled(engine: SyncEngine): Boolean { return syncStorage.getStatus()[engine]?: false } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java index 7f9241325..2475fe744 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java @@ -214,13 +214,21 @@ public void onSyncBookmarks(@NonNull View view) { @Override public void onFxALogin(@NonNull View view) { - mAccounts.getAuthenticationUrlAsync().thenAcceptAsync((url) -> { - if (url != null) { - mAccounts.setLoginOrigin(Accounts.LoginOrigin.BOOKMARKS); - WidgetManagerDelegate widgetManager = ((VRBrowserActivity)getContext()); - widgetManager.openNewTabForeground(url); - widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); - } + if (mAccounts.getAccountStatus() == Accounts.AccountStatus.SIGNED_IN) { + mAccounts.logoutAsync(); + + } else { + mAccounts.authUrlAsync().thenAcceptAsync((url) -> { + if (url == null) { + mAccounts.logoutAsync(); + + } else { + mAccounts.setLoginOrigin(Accounts.LoginOrigin.BOOKMARKS); + WidgetManagerDelegate widgetManager = ((VRBrowserActivity)getContext()); + widgetManager.openNewTabForeground(url); + widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); + } + }, mUIThreadExecutor).exceptionally(throwable -> { Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); throwable.printStackTrace(); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java index 4f644d2b7..9197b5421 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java @@ -211,13 +211,21 @@ public void onSyncHistory(@NonNull View view) { @Override public void onFxALogin(@NonNull View view) { - mAccounts.getAuthenticationUrlAsync().thenAcceptAsync((url) -> { - if (url != null) { - mAccounts.setLoginOrigin(Accounts.LoginOrigin.HISTORY); - WidgetManagerDelegate widgetManager = ((VRBrowserActivity)getContext()); - widgetManager.openNewTabForeground(url); - widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); - } + if (mAccounts.getAccountStatus() == Accounts.AccountStatus.SIGNED_IN) { + mAccounts.logoutAsync(); + + } else { + mAccounts.authUrlAsync().thenAcceptAsync((url) -> { + if (url == null) { + mAccounts.logoutAsync(); + + } else { + mAccounts.setLoginOrigin(Accounts.LoginOrigin.HISTORY); + WidgetManagerDelegate widgetManager = ((VRBrowserActivity)getContext()); + widgetManager.openNewTabForeground(url); + widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); + } + }, mUIThreadExecutor).exceptionally(throwable -> { Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); throwable.printStackTrace(); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java index cb87cf123..db812abe7 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java @@ -99,17 +99,20 @@ public void hide(@HideFlags int aHideFlags) { } private void signIn(View view) { - mAccounts.getAuthenticationUrlAsync().thenAcceptAsync((url) -> { - if (url != null) { - mAccounts.setLoginOrigin(mLoginOrigin); - mWidgetManager.openNewTabForeground(url); - mWidgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_VR); - mWidgetManager.getFocusedWindow().getSession().loadUri(url); - } - - if (mSignInCallback != null) { - mSignInCallback.run(); - } + if (mAccounts.getAccountStatus() == Accounts.AccountStatus.SIGNED_IN) { + mAccounts.logoutAsync(); + + } else { + mAccounts.authUrlAsync().thenAcceptAsync((url) -> { + if (url == null) { + mAccounts.logoutAsync(); + + } else { + mAccounts.setLoginOrigin(mLoginOrigin); + mWidgetManager.openNewTabForeground(url); + mWidgetManager.getFocusedWindow().getSession().loadUri(url); + mWidgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_VR); + } }, mUIThreadExecutor).exceptionally(throwable -> { Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java index 83922bc8d..227feb56a 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java @@ -281,13 +281,21 @@ private void manageAccount() { case SIGNED_OUT: case NEEDS_RECONNECT: hide(REMOVE_WIDGET); - mAccounts.getAuthenticationUrlAsync().thenAcceptAsync((url) -> { - if (url != null) { - mAccounts.setLoginOrigin(Accounts.LoginOrigin.SETTINGS); - WidgetManagerDelegate widgetManager = ((VRBrowserActivity)getContext()); - widgetManager.openNewTabForeground(url); - widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); - } + if (mAccounts.getAccountStatus() == Accounts.AccountStatus.SIGNED_IN) { + mAccounts.logoutAsync(); + + mAccounts.authUrlAsync().thenAcceptAsync((url) -> { + } else { + if (url == null) { + + mAccounts.logoutAsync(); + } else { + mAccounts.setLoginOrigin(Accounts.LoginOrigin.SETTINGS); + widgetManager.openNewTabForeground(url); + WidgetManagerDelegate widgetManager = ((VRBrowserActivity)getContext()); + widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); + } + }, mUIThreadExecutor).exceptionally(throwable -> { Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); throwable.printStackTrace(); From f7e261309949387f8873eaca381c5aef54984a01 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 4 Nov 2019 13:40:47 +0100 Subject: [PATCH 3/9] Remove WorkManager initialization Per https://github.com/MozillaReality/FirefoxReality/pull/1973#discussion_r337518862 --- .../org/mozilla/vrbrowser/browser/Services.kt | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt index 7979e21f4..f5a6ec278 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt @@ -53,20 +53,6 @@ class Services(context: Context, places: Places): GeckoSession.NavigationDelegat GlobalSyncableStoreProvider.configureStore(SyncEngine.Bookmarks to places.bookmarks) GlobalSyncableStoreProvider.configureStore(SyncEngine.History to places.history) - - // TODO this really shouldn't be necessary, since WorkManager auto-initializes itself, unless - // auto-initialization is disabled in the manifest file. We don't disable the initialization, - // but i'm seeing crashes locally because WorkManager isn't initialized correctly... - // Maybe this is a race of sorts? We're trying to access it before it had a chance to auto-initialize? - // It's not well-documented _when_ that auto-initialization is supposed to happen. - - // For now, let's just manually initialize it here, and swallow failures (it's already initialized). - try { - WorkManager.initialize( - context, - Configuration.Builder().setMinimumLoggingLevel(android.util.Log.INFO).build() - ) - } catch (e: IllegalStateException) {} } // Process received device events, only handling received tabs for now. From 64fcc738705d9f68ad58bc4bfe1f609693a84bc8 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 4 Nov 2019 13:45:56 +0100 Subject: [PATCH 4/9] Restore mistakenly removed callback --- .../vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java index db812abe7..135047166 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java @@ -114,6 +114,12 @@ private void signIn(View view) { mWidgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_VR); } + if (mSignInCallback != null) { + mSignInCallback.run(); + } + + }, new UIThreadExecutor()); + } }, mUIThreadExecutor).exceptionally(throwable -> { Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); throwable.printStackTrace(); From 44e33af0b22c74af0b9c703ea5db06f73b580e70 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 11 Nov 2019 14:27:41 +0100 Subject: [PATCH 5/9] Rebase updates --- .../vrbrowser/ui/views/BookmarksView.java | 37 ++++++++------- .../vrbrowser/ui/views/HistoryView.java | 37 ++++++++------- .../ui/widgets/dialogs/WhatsNewWidget.java | 45 ++++++++++--------- .../ui/widgets/settings/SettingsWidget.java | 37 ++++++++------- 4 files changed, 87 insertions(+), 69 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java index 2475fe744..bf63830eb 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java @@ -40,6 +40,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import mozilla.appservices.places.BookmarkRoot; @@ -218,22 +219,26 @@ public void onFxALogin(@NonNull View view) { mAccounts.logoutAsync(); } else { - mAccounts.authUrlAsync().thenAcceptAsync((url) -> { - if (url == null) { - mAccounts.logoutAsync(); - - } else { - mAccounts.setLoginOrigin(Accounts.LoginOrigin.BOOKMARKS); - WidgetManagerDelegate widgetManager = ((VRBrowserActivity)getContext()); - widgetManager.openNewTabForeground(url); - widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); - } - - }, mUIThreadExecutor).exceptionally(throwable -> { - Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); - throwable.printStackTrace(); - return null; - }); + CompletableFuture result = mAccounts.authUrlAsync(); + if (result != null) { + result.thenAcceptAsync((url) -> { + if (url == null) { + mAccounts.logoutAsync(); + + } else { + mAccounts.setLoginOrigin(Accounts.LoginOrigin.BOOKMARKS); + WidgetManagerDelegate widgetManager = ((VRBrowserActivity) getContext()); + widgetManager.openNewTabForeground(url); + widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); + } + + }, mUIThreadExecutor).exceptionally(throwable -> { + Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); + throwable.printStackTrace(); + return null; + }); + } + } } @Override diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java index 9197b5421..6ddba5141 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java @@ -42,6 +42,7 @@ import java.util.GregorianCalendar; import java.util.List; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.function.Function; @@ -215,22 +216,26 @@ public void onFxALogin(@NonNull View view) { mAccounts.logoutAsync(); } else { - mAccounts.authUrlAsync().thenAcceptAsync((url) -> { - if (url == null) { - mAccounts.logoutAsync(); - - } else { - mAccounts.setLoginOrigin(Accounts.LoginOrigin.HISTORY); - WidgetManagerDelegate widgetManager = ((VRBrowserActivity)getContext()); - widgetManager.openNewTabForeground(url); - widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); - } - - }, mUIThreadExecutor).exceptionally(throwable -> { - Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); - throwable.printStackTrace(); - return null; - }); + CompletableFuture result = mAccounts.authUrlAsync(); + if (result != null) { + result.thenAcceptAsync((url) -> { + if (url == null) { + mAccounts.logoutAsync(); + + } else { + mAccounts.setLoginOrigin(Accounts.LoginOrigin.HISTORY); + WidgetManagerDelegate widgetManager = ((VRBrowserActivity) getContext()); + widgetManager.openNewTabForeground(url); + widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); + } + + }, mUIThreadExecutor).exceptionally(throwable -> { + Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); + throwable.printStackTrace(); + return null; + }); + } + } } @Override diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java index 135047166..de3d73dab 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java @@ -23,6 +23,7 @@ import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; public class WhatsNewWidget extends UIDialog implements WidgetManagerDelegate.WorldClickListener { @@ -103,28 +104,30 @@ private void signIn(View view) { mAccounts.logoutAsync(); } else { - mAccounts.authUrlAsync().thenAcceptAsync((url) -> { - if (url == null) { - mAccounts.logoutAsync(); - - } else { - mAccounts.setLoginOrigin(mLoginOrigin); - mWidgetManager.openNewTabForeground(url); - mWidgetManager.getFocusedWindow().getSession().loadUri(url); - mWidgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_VR); - } - - if (mSignInCallback != null) { - mSignInCallback.run(); - } - - }, new UIThreadExecutor()); + CompletableFuture result = mAccounts.authUrlAsync(); + if (result != null) { + result.thenAcceptAsync((url) -> { + if (url == null) { + mAccounts.logoutAsync(); + + } else { + mAccounts.setLoginOrigin(mLoginOrigin); + mWidgetManager.openNewTabForeground(url); + mWidgetManager.getFocusedWindow().getSession().loadUri(url); + mWidgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_VR); + } + + if (mSignInCallback != null) { + mSignInCallback.run(); + } + + }, mUIThreadExecutor).exceptionally(throwable -> { + Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); + throwable.printStackTrace(); + return null; + }); + } } - }, mUIThreadExecutor).exceptionally(throwable -> { - Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); - throwable.printStackTrace(); - return null; - }); } private void startBrowsing(View view) { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java index 227feb56a..e07d8ac48 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java @@ -48,6 +48,7 @@ import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLEncoder; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import mozilla.components.concept.sync.AccountObserver; @@ -284,23 +285,27 @@ private void manageAccount() { if (mAccounts.getAccountStatus() == Accounts.AccountStatus.SIGNED_IN) { mAccounts.logoutAsync(); - mAccounts.authUrlAsync().thenAcceptAsync((url) -> { } else { - if (url == null) { - - mAccounts.logoutAsync(); - } else { - mAccounts.setLoginOrigin(Accounts.LoginOrigin.SETTINGS); - widgetManager.openNewTabForeground(url); - WidgetManagerDelegate widgetManager = ((VRBrowserActivity)getContext()); - widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); - } - - }, mUIThreadExecutor).exceptionally(throwable -> { - Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); - throwable.printStackTrace(); - return null; - }); + CompletableFuture result = mAccounts.authUrlAsync(); + if (result != null) { + result.thenAcceptAsync((url) -> { + if (url == null) { + mAccounts.logoutAsync(); + + } else { + mAccounts.setLoginOrigin(Accounts.LoginOrigin.SETTINGS); + mWidgetManager.openNewTabForeground(url); + WidgetManagerDelegate widgetManager = ((VRBrowserActivity)getContext()); + widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); + } + + }, mUIThreadExecutor).exceptionally(throwable -> { + Log.d(LOGTAG, "Error getting the authentication URL: " + throwable.getLocalizedMessage()); + throwable.printStackTrace(); + return null; + }); + } + } break; case SIGNED_IN: From d02fcfe647a2860f3ecc36e9d2e6eee74e221707 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 11 Nov 2019 14:28:03 +0100 Subject: [PATCH 6/9] Revert the workmanager fix, there are still crashes without this --- .../org/mozilla/vrbrowser/browser/Services.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt index f5a6ec278..7979e21f4 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt @@ -53,6 +53,20 @@ class Services(context: Context, places: Places): GeckoSession.NavigationDelegat GlobalSyncableStoreProvider.configureStore(SyncEngine.Bookmarks to places.bookmarks) GlobalSyncableStoreProvider.configureStore(SyncEngine.History to places.history) + + // TODO this really shouldn't be necessary, since WorkManager auto-initializes itself, unless + // auto-initialization is disabled in the manifest file. We don't disable the initialization, + // but i'm seeing crashes locally because WorkManager isn't initialized correctly... + // Maybe this is a race of sorts? We're trying to access it before it had a chance to auto-initialize? + // It's not well-documented _when_ that auto-initialization is supposed to happen. + + // For now, let's just manually initialize it here, and swallow failures (it's already initialized). + try { + WorkManager.initialize( + context, + Configuration.Builder().setMinimumLoggingLevel(android.util.Log.INFO).build() + ) + } catch (e: IllegalStateException) {} } // Process received device events, only handling received tabs for now. From 42d5d859bc3b0a0f5b7f17db990754b6c0dce2ab Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Fri, 22 Nov 2019 11:51:33 +0100 Subject: [PATCH 7/9] Call prefs before creating the runtime --- .../org/mozilla/vrbrowser/browser/engine/SessionStore.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java index 7e9fc1ef0..2942ecef5 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java @@ -57,10 +57,10 @@ private SessionStore() { public void setContext(Context context, Bundle aExtras) { mContext = context; - mRuntime = EngineProvider.INSTANCE.getOrCreateRuntime(context); - // FIXME: Once GeckoView has a prefs API SessionUtils.vrPrefsWorkAround(context, aExtras); + + mRuntime = EngineProvider.INSTANCE.getOrCreateRuntime(context); } public void initializeServices() { From e1361dc79c14374824dbaf89f54271e3f517435b Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Fri, 22 Nov 2019 12:32:04 +0100 Subject: [PATCH 8/9] Megazord integration --- app/build.gradle | 16 ++++++++++++++++ .../org/mozilla/vrbrowser/browser/Services.kt | 2 ++ versions.gradle | 14 +++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index cd1aedb75..1222195ec 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -461,6 +461,22 @@ dependencies { implementation deps.android_components.support_rusthttp implementation deps.android_components.glean + // For production builds, the native code for all `org.mozilla.appservices` + // dependencies gets compiled together into a single "megazord" build, and + // different megazords are published for different subsets of features. Ref + // https://mozilla.github.io/application-services/docs/applications/consuming-megazord-libraries.html + // For now we can jut use the one that's specifically designed for Fenix. + implementation deps.app_services.megazord + testImplementation deps.app_services.megazord_forUnitTests + modules { + module('org.mozilla.appservices:full-megazord') { + replacedBy('org.mozilla.appservices:fenix-megazord', 'prefer the fenix megazord, to reduce final application size') + } + module('org.mozilla.appservices:fenix-megazord') { + replacedBy('org.mozilla.appservices:fenix-megazord-forUnitTests', 'prefer the forUnitTests variant if present') + } + } + // TODO this should not be necessary at all, see Services.kt implementation deps.work.runtime diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt index 7979e21f4..dc792cdf3 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt @@ -14,6 +14,7 @@ import androidx.work.WorkManager import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import mozilla.appservices.Megazord import mozilla.components.concept.sync.* import mozilla.components.lib.fetch.httpurlconnection.HttpURLConnectionClient import mozilla.components.service.fxa.* @@ -45,6 +46,7 @@ class Services(context: Context, places: Places): GeckoSession.NavigationDelegat // This makes bookmarks storage accessible to background sync workers. init { + Megazord.init() RustLog.enable() RustHttpConfig.setClient(lazy { EngineProvider.createClient(context) }) diff --git a/versions.gradle b/versions.gradle index ff4bd5fde..c79ec0910 100644 --- a/versions.gradle +++ b/versions.gradle @@ -25,7 +25,14 @@ def versions = [:] // GeckoView versions can be found here: // https://maven.mozilla.org/?prefix=maven2/org/mozilla/geckoview/ versions.gecko_view = "72.0.20191118093852" -versions.android_components = "19.0.1" +versions.android_components = "21.0.0" +// Note that android-components also depends on application-services, +// and in fact is our main source of appservices-related functionality. +// The version number below tracks the application-services version +// that we depend on directly for the fenix-megazord (and for it's +// forUnitTest variant), and it's important that it be kept in +// sync with the version used by android-components above. +versions.mozilla_appservices = "0.42.2" versions.mozilla_speech = "1.0.6" versions.openwnn = "1.3.7" versions.google_vr = "1.190.0" @@ -66,6 +73,11 @@ android_components.support_rustlog = "org.mozilla.components:support-rustlog:$ve android_components.support_rusthttp = "org.mozilla.components:support-rusthttp:$versions.android_components" deps.android_components = android_components +def app_services = [:] +app_services.megazord = "org.mozilla.appservices:fenix-megazord:${versions.mozilla_appservices}" +app_services.megazord_forUnitTests = "org.mozilla.appservices:fenix-megazord-forUnitTests:${versions.mozilla_appservices}" +deps.app_services = app_services + deps.mozilla_speech = "com.github.mozilla:mozillaspeechlibrary:$versions.mozilla_speech" deps.openwnn = "jp.co.omronsoft.openwnn:openwnn:$versions.openwnn" From 2ff5af0af3fe79b2c85e76d2011e3407a49baa72 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 25 Nov 2019 12:36:10 +0100 Subject: [PATCH 9/9] Rebase updated --- .../org/mozilla/vrbrowser/ui/views/BookmarksView.java | 2 ++ .../org/mozilla/vrbrowser/ui/views/HistoryView.java | 2 ++ .../org/mozilla/vrbrowser/ui/widgets/WindowWidget.java | 10 ++++++++++ .../vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java | 2 ++ .../vrbrowser/ui/widgets/settings/SettingsWidget.java | 3 ++- 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java index bf63830eb..f27834623 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/BookmarksView.java @@ -230,6 +230,8 @@ public void onFxALogin(@NonNull View view) { WidgetManagerDelegate widgetManager = ((VRBrowserActivity) getContext()); widgetManager.openNewTabForeground(url); widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); + + mBookmarksViewListeners.forEach((listener) -> listener.onFxALogin(view)); } }, mUIThreadExecutor).exceptionally(throwable -> { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java index 6ddba5141..0f28e4971 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/views/HistoryView.java @@ -227,6 +227,8 @@ public void onFxALogin(@NonNull View view) { WidgetManagerDelegate widgetManager = ((VRBrowserActivity) getContext()); widgetManager.openNewTabForeground(url); widgetManager.getFocusedWindow().getSession().setUaMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); + + mHistoryViewListeners.forEach((listener) -> listener.onFxALogin(view)); } }, mUIThreadExecutor).exceptionally(throwable -> { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java index 9746e9a5b..f16dc83b3 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java @@ -1428,6 +1428,11 @@ public void onHideContextMenu(@NonNull View view) { public void onItemClicked(@NonNull View view, Bookmark item) { hideBookmarks(); } + + @Override + public void onFxALogin(@NonNull View view) { + hideBookmarks(); + } }; private HistoryCallback mHistoryListener = new HistoryCallback() { @@ -1462,6 +1467,11 @@ public void onHideContextMenu(@NonNull View view) { public void onItemClicked(@NonNull View view, VisitInfo item) { hideHistory(); } + + @Override + public void onFxALogin(@NonNull View view) { + hideHistory(); + } }; private void hideContextMenus() { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java index de3d73dab..e5ca78620 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java @@ -104,6 +104,8 @@ private void signIn(View view) { mAccounts.logoutAsync(); } else { + hide(REMOVE_WIDGET); + CompletableFuture result = mAccounts.authUrlAsync(); if (result != null) { result.thenAcceptAsync((url) -> { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java index e07d8ac48..6894c04f4 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java @@ -281,11 +281,12 @@ private void manageAccount() { switch(mAccounts.getAccountStatus()) { case SIGNED_OUT: case NEEDS_RECONNECT: - hide(REMOVE_WIDGET); if (mAccounts.getAccountStatus() == Accounts.AccountStatus.SIGNED_IN) { mAccounts.logoutAsync(); } else { + hide(REMOVE_WIDGET); + CompletableFuture result = mAccounts.authUrlAsync(); if (result != null) { result.thenAcceptAsync((url) -> {