Skip to content

Commit

Permalink
FxA updates (MozillaReality#2129)
Browse files Browse the repository at this point in the history
* Use GeckoWebExecutor for FxA Services

* Get rid of a complex getAuthicationUrlAsync

Per MozillaReality#1973 (comment)

* Remove WorkManager initialization

Per MozillaReality#1973 (comment)

* Restore mistakenly removed callback

* Rebase updates

* Revert the workmanager fix, there are still crashes without this

* Call prefs before creating the runtime

* Megazord integration

* Rebase updated
  • Loading branch information
keianhzo authored and Alexandre Lissy committed Jan 21, 2020
1 parent fdffba0 commit 56894ea
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 150 deletions.
16 changes: 16 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,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

Expand Down
50 changes: 0 additions & 50 deletions app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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) {

Expand Down Expand Up @@ -281,53 +278,6 @@ class Accounts constructor(val context: Context) {
}
}

fun getAuthenticationUrlAsync(): CompletableFuture<String> {
val future: CompletableFuture<String> = 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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.*
Expand All @@ -28,6 +29,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 {
Expand All @@ -42,8 +46,9 @@ 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 { HttpURLConnectionClient() })
RustHttpConfig.setClient(lazy { EngineProvider.createClient(context) })

// Make sure we get logs out of our android-components.
Log.addSink(AndroidLogSink())
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -34,11 +32,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() {
Expand All @@ -65,48 +58,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);
}
}
// FIXME: Once GeckoView has a prefs API
SessionUtils.vrPrefsWorkAround(context, aExtras);

public GeckoRuntime getRuntime() {
return mRuntime;
mRuntime = EngineProvider.INSTANCE.getOrCreateRuntime(context);
}

public void initializeServices() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -214,18 +215,32 @@ 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 {
CompletableFuture<String> 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);

mBookmarksViewListeners.forEach((listener) -> listener.onFxALogin(view));
}

}, 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;
});
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -211,18 +212,32 @@ 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 {
CompletableFuture<String> 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);

mHistoryViewListeners.forEach((listener) -> listener.onFxALogin(view));
}

}, 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;
});
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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() {
Expand Down
Loading

0 comments on commit 56894ea

Please sign in to comment.