Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
AC WebExtensions + WebCompat + FxAWebChannels
Browse files Browse the repository at this point in the history
  • Loading branch information
keianhzo committed Jun 15, 2020
1 parent 6b20069 commit 5a145fe
Show file tree
Hide file tree
Showing 29 changed files with 1,244 additions and 88 deletions.
Binary file removed app/aars/appcompat.aar
Binary file not shown.
11 changes: 5 additions & 6 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,6 @@ android {
configurations {
armImplementation
x86Implementation
all*.exclude group: 'androidx.appcompat', module: 'appcompat'
}

repositories {
Expand All @@ -412,8 +411,7 @@ dependencies {
implementation deps.lifecycle.runtime
implementation deps.lifecycle.viewmodel
implementation deps.support.cardview
//implementation deps.support.app_compat
implementation(name:'appcompat', ext:'aar')
implementation deps.support.app_compat
implementation deps.support.vector_drawable
implementation deps.support.annotations
implementation deps.constraint_layout
Expand All @@ -427,24 +425,25 @@ dependencies {
implementation deps.android_components.telemetry
implementation deps.android_components.browser_errorpages
implementation deps.android_components.browser_search
implementation deps.android_components.browser_state
implementation deps.android_components.browser_storage
implementation deps.android_components.browser_domains
implementation deps.android_components.service_accounts
implementation deps.android_components.mozilla_service_location
implementation deps.android_components.ui_autocomplete
implementation deps.android_components.concept_engine
implementation deps.android_components.concept_fetch
implementation deps.android_components.lib_fetch
implementation deps.android_components.support_rustlog
implementation deps.android_components.support_rusthttp
implementation deps.android_components.feature_accounts
implementation deps.android_components.feature_webcompat
implementation deps.android_components.glean
implementation deps.app_services.rustlog

// TODO this should not be necessary at all, see Services.kt
implementation deps.work.runtime

// TODO this should not be necessary at all, see Services.kt
implementation deps.work.runtime

// Kotlin dependency
implementation deps.kotlin.stdlib
implementation deps.kotlin.coroutines
Expand Down
18 changes: 2 additions & 16 deletions app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,7 @@ protected void onCreate(Bundle savedInstanceState) {
BitmapCache.getInstance(this).onCreate();

Bundle extras = getIntent() != null ? getIntent().getExtras() : null;
SessionStore.get().setContext(this, extras);
SessionStore.get().initializeServices();
SessionStore.get().initializeStores(this);
SessionStore.get().initialize(this, extras);
SessionStore.get().setLocales(LocaleUtils.getPreferredLanguageTags(this));

EngineProvider.INSTANCE.getOrCreateRuntime(this).appendAppNotesToCrashReport("Firefox Reality " + BuildConfig.VERSION_NAME + "-" + BuildConfig.VERSION_CODE + "-" + BuildConfig.FLAVOR + "-" + BuildConfig.BUILD_TYPE + " (" + BuildConfig.GIT_HASH + ")");
Expand Down Expand Up @@ -393,19 +391,7 @@ public void onWindowVideoAvailabilityChanged(@NonNull WindowWidget aWindow) {
mWhatsNewWidget.show(UIWidget.REQUEST_FOCUS);
}

EngineProvider.INSTANCE.loadExtensions()
.thenAcceptAsync(aVoid -> {
Log.d(LOGTAG, "WebExtensions loaded");
mWindows.restoreSessions();
}, getServicesProvider().getExecutors().mainThread())
.exceptionally(throwable -> {
String msg = throwable.getLocalizedMessage();
if (msg != null) {
Log.e(LOGTAG, "Extensions load error: " + msg);
}
mWindows.restoreSessions();
return null;
});
mWindows.restoreSessions();
}

private void attachToWindow(@NonNull WindowWidget aWindow, @Nullable WindowWidget aPrevWindow) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void onCreate() {
super.onCreate();
mAppExecutors = new AppExecutors();
mBitmapCache = new BitmapCache(this, mAppExecutors.diskIO(), mAppExecutors.mainThread());

TelemetryWrapper.init(this);
GleanMetricsService.init(this);
}
Expand Down
12 changes: 11 additions & 1 deletion app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ class Services(val context: Context, places: Places): GeckoSession.NavigationDel
companion object {
const val CLIENT_ID = "7ad9917f6c55fb77"
const val REDIRECT_URL = "https://accounts.firefox.com/oauth/success/$CLIENT_ID"

fun redirectUrl(context: Context) = if (SettingsStore.getInstance(context).isFxAWebChannelsEnabled) {
"urn:ietf:wg:oauth:2.0:oob:oauth-redirect-webchannel"
} else {
REDIRECT_URL
}
}
interface TabReceivedDelegate {
fun onTabsReceived(uri: List<TabData>)
Expand Down Expand Up @@ -98,9 +104,11 @@ class Services(val context: Context, places: Places): GeckoSession.NavigationDel
}
}
}
public val serverConfig = ServerConfig(Server.RELEASE, CLIENT_ID, redirectUrl(context))

val accountManager = FxaAccountManager(
context = context,
serverConfig = ServerConfig(Server.RELEASE, CLIENT_ID, REDIRECT_URL),
serverConfig = serverConfig,
deviceConfig = DeviceConfig(
// This is a default name, and can be changed once user is logged in.
// E.g. accountManager.authenticatedAccount()?.deviceConstellation()?.setDeviceNameAsync("new name")
Expand All @@ -112,6 +120,7 @@ class Services(val context: Context, places: Places): GeckoSession.NavigationDel

).also {
it.registerForAccountEvents(deviceEventObserver, ProcessLifecycleOwner.get(), true)

}

init {
Expand Down Expand Up @@ -150,4 +159,5 @@ class Services(val context: Context, places: Places): GeckoSession.NavigationDel

return GeckoResult.ALLOW
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
import org.mozilla.vrbrowser.browser.engine.Session;

public interface SessionChangeListener {
default void onRemoveSession(Session aSession) {}
default void onSessionAdded(Session aSession) {}
default void onSessionOpened(Session aSession) {}
default void onSessionClosed(Session aSession) {}
default void onSessionRemoved(Session aSession) {}
default void onSessionStateChanged(Session aSession, boolean aActive) {}
default void onCurrentSessionChange(GeckoSession aOldSession, GeckoSession aSession) {}
default void onStackSession(Session aSession) {}
default void onUnstackSession(Session aSession, Session aParent) {}
default void onActiveStateChange(Session aSession, boolean aActive) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@

import android.content.Context;
import android.content.SharedPreferences;
import android.database.Observable;
import android.graphics.Color;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.util.Log;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.databinding.ObservableBoolean;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

import org.json.JSONArray;
Expand Down Expand Up @@ -102,6 +99,7 @@ SettingsStore getInstance(final @NonNull Context aContext) {
public final static boolean MULTI_E10S = false;
public final static int DOWNLOADS_STORAGE_DEFAULT = INTERNAL;
public final static int DOWNLOADS_SORTING_ORDER_DEFAULT = SortingContextMenuWidget.SORT_DATE_ASC;
public final static boolean FXA_WEBCHANNELS_ENABLED = true;

// Enable telemetry by default (opt-out).
public final static boolean CRASH_REPORTING_DEFAULT = false;
Expand Down Expand Up @@ -738,5 +736,15 @@ public void setDownloadsSortingOrder(@SortingContextMenuWidget.Order int order)
public @Storage int getDownloadsSortingOrder() {
return mPrefs.getInt(mContext.getString(R.string.settings_key_downloads_sorting_order), DOWNLOADS_SORTING_ORDER_DEFAULT);
}

public void setFxAWebChannelsEnabled(boolean isEnabled) {
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(mContext.getString(R.string.settings_key_webchannels_enabled), isEnabled);
editor.commit();
}

public boolean isFxAWebChannelsEnabled() {
return mPrefs.getBoolean(mContext.getString(R.string.settings_key_webchannels_enabled), FXA_WEBCHANNELS_ENABLED);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.mozilla.vrbrowser.browser.adapter

import mozilla.components.browser.state.action.EngineAction
import mozilla.components.browser.state.action.TabListAction
import mozilla.components.browser.state.state.*
import mozilla.components.browser.state.store.BrowserStore
import org.mozilla.geckoview.GeckoSession
import org.mozilla.vrbrowser.browser.components.GeckoEngineSession
import org.mozilla.vrbrowser.browser.engine.Session

class ComponentsAdapter private constructor(
val store: BrowserStore = BrowserStore()
) {
companion object {
private val instance: ComponentsAdapter = ComponentsAdapter()

fun get(): ComponentsAdapter = instance
}

fun addSession(session: Session) {
store.dispatch(TabListAction.AddTabAction(
tab = session.toTabSessionState()
))
}

fun removeSession(session: Session) {
store.dispatch(TabListAction.RemoveTabAction(
tabId = session.id
))
}

fun selectSession(session: Session) {
store.dispatch(TabListAction.SelectTabAction(
tabId = session.id
))
}

fun link(tabId: String, geckoSession: GeckoSession) {
store.dispatch(EngineAction.LinkEngineSessionAction(
tabId,
GeckoEngineSession(geckoSession)
))
}

fun unlink(tabId: String) {
store.dispatch(EngineAction.UnlinkEngineSessionAction(
tabId
))
}
}

private fun Session.toTabSessionState(): TabSessionState {
return TabSessionState(
id = id,
content = ContentState(
url = currentUri,
private = isPrivateMode,
title = currentTitle
),
parentId = null,
extensionState = emptyMap(),
readerState = ReaderState(),
engineState = EngineState(
GeckoEngineSession(geckoSession),
null
)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.mozilla.vrbrowser.browser.components

import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.EngineSessionState
import mozilla.components.concept.engine.Settings
import org.json.JSONObject
import org.mozilla.geckoview.GeckoSession
import org.mozilla.vrbrowser.browser.engine.SessionStore

class GeckoEngineSession(
val geckoSession: GeckoSession
): EngineSession() {
constructor() :
this(SessionStore.get().createSession(false, false).geckoSession)

override fun loadUrl(url: String, parent: EngineSession?, flags: LoadUrlFlags, additionalHeaders: Map<String, String>?) {
geckoSession.loadUri(url)
}

override val settings: Settings = object : Settings() {}
override fun clearFindMatches() = Unit
override fun disableTrackingProtection() = Unit
override fun enableTrackingProtection(policy: TrackingProtectionPolicy) = Unit
override fun exitFullScreenMode() = Unit
override fun findAll(text: String) = Unit
override fun findNext(forward: Boolean) = Unit
override fun goBack() = Unit
override fun goForward() = Unit
override fun loadData(data: String, mimeType: String, encoding: String) = Unit
override fun recoverFromCrash(): Boolean = true
override fun reload() = Unit
override fun restoreState(state: EngineSessionState) = true
override fun saveState(): EngineSessionState = DummyEngineSessionState()
override fun stopLoading() = Unit
override fun toggleDesktopMode(enable: Boolean, reload: Boolean) = Unit
}

private class DummyEngineSessionState : EngineSessionState {
override fun toJSON(): JSONObject = JSONObject()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* 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.components

import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.launch
import mozilla.components.concept.engine.CancellableOperation
import org.mozilla.geckoview.GeckoResult
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

/**
* Wait for a GeckoResult to be complete in a co-routine.
*/
suspend fun <T> GeckoResult<T>.await() = suspendCoroutine<T?> { continuation ->
then({
continuation.resume(it)
GeckoResult<Void>()
}, {
continuation.resumeWithException(it)
GeckoResult<Void>()
})
}

/**
* Converts a [GeckoResult] to a [CancellableOperation].
*/
fun <T> GeckoResult<T>.asCancellableOperation(): CancellableOperation {
val geckoResult = this
return object : CancellableOperation {
override fun cancel(): Deferred<Boolean> {
val result = CompletableDeferred<Boolean>()
geckoResult.cancel().then({
result.complete(it ?: false)
GeckoResult<Void>()
}, { throwable ->
result.completeExceptionally(throwable)
GeckoResult<Void>()
})
return result
}
}
}

/**
* Create a GeckoResult from a co-routine.
*/
@Suppress("TooGenericExceptionCaught")
fun <T> CoroutineScope.launchGeckoResult(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
) = GeckoResult<T>().apply {
launch(context, start) {
try {
val value = block()
complete(value)
} catch (exception: Throwable) {
completeExceptionally(exception)
}
}
}
Loading

0 comments on commit 5a145fe

Please sign in to comment.