Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WebPayments] Introduce OverlayWidget & Use it by PaymentHandler #1654

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.chromium.wolvic.DownloadManagerBridge;
import org.chromium.wolvic.PasswordForm;
import org.chromium.wolvic.PermissionManagerBridge;
import org.chromium.wolvic.TabCompositorView;
import org.chromium.wolvic.UserDialogManagerBridge;

import java.io.InputStream;
Expand Down Expand Up @@ -114,8 +115,8 @@ public void setActive(boolean active) {
if (mTab == null)
return;

assert mTab.getContentView() != null;
WebContents webContents = mTab.getContentView().getWebContents();
assert mTab.getActiveWebContents() != null;
WebContents webContents = mTab.getActiveWebContents();
if (active) {
webContents.onShow();
} else {
Expand All @@ -129,8 +130,8 @@ public void setActive(boolean active) {
public void setFocused(boolean focused) {
if (mTab == null)
return;
assert mTab.getContentView() != null;
mTab.getContentView().getWebContents().setFocus(focused);
assert mTab.getActiveWebContents() != null;
mTab.getActiveWebContents().setFocus(focused);
}

@Override
Expand Down Expand Up @@ -215,6 +216,20 @@ public void releaseDisplay(@NonNull WDisplay display) {
getTextInput().setView(null);
}

public WDisplay acquireOverlayDisplay(TabCompositorView compositorView) {
SettingsStore settings = SettingsStore.getInstance(mRuntime.getContext());
WDisplay display = new DisplayImpl(this, compositorView);
mRuntime.getContainerView().addView(compositorView,
new ViewGroup.LayoutParams(settings.getWindowWidth() / 2, settings.getWindowHeight() / 2));
getTextInput().setView(getContentView());
return display;
}

public void releaseOverlayDisplay(TabCompositorView compositorView) {
mRuntime.getContainerView().removeView(compositorView);
getTextInput().setView(null);
}

@Override
public void restoreState(@NonNull WSessionState state) {

Expand Down Expand Up @@ -457,7 +472,7 @@ public TabImpl getTab() {
}

public ViewGroup getContentView() {
return mTab != null ? mTab.getContentView() : null;
return mTab != null ? mTab.getActiveContentView() : null;
}

// The onReadyCallback() mechanism is really limited because it heavily depends on renderers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,25 @@

import androidx.annotation.NonNull;

import org.chromium.components.embedder_support.view.ContentView;
import org.chromium.content_public.browser.MediaSessionObserver;
import org.chromium.content_public.browser.SelectionPopupController;
import org.chromium.content_public.browser.WebContents;
import org.chromium.wolvic.Tab;
import org.chromium.wolvic.TabCompositorView;

/**
* Controlls a single tab content in a browser for chromium backend.
* Controls a single tab content in a browser for chromium backend.
*/
public class TabImpl extends Tab {
private TabMediaSessionObserver mTabMediaSessionObserver;
private TabWebContentsDelegate mTabWebContentsDelegate;
private TabWebContentsObserver mWebContentsObserver;
private WebContents mPaymentHandlerWebContents;
// TODO: Need to Payment's mediator
private ContentView mPaymentHandlerContentView;
private TabCompositorView mPaymentHandlerCompositorView;


public TabImpl(@NonNull Context context, @NonNull SessionImpl session, WebContents webContents) {
super(context, session.getSettings().getUsePrivateMode(), webContents);
Expand All @@ -27,7 +34,7 @@ private void registerCallbacks(@NonNull SessionImpl session) {
mTabWebContentsDelegate = new TabWebContentsDelegate(session, mWebContents);
setWebContentsDelegate(mWebContents, mTabWebContentsDelegate);

mWebContentsObserver = new TabWebContentsObserver(mWebContents, session);
mWebContentsObserver = new TabWebContentsObserver(this, session);

SelectionPopupController controller =
SelectionPopupController.fromWebContents(mWebContents);
Expand All @@ -47,4 +54,22 @@ public void onMediaFullscreen(boolean isFullscreen) {
public void purgeHistory() {
mWebContents.getNavigationController().clearHistory();
}

public void setPaymentWebContents(WebContents webContents, ContentView contentView, TabCompositorView compositorView) {
mPaymentHandlerWebContents = webContents;
mPaymentHandlerContentView = contentView;
mPaymentHandlerCompositorView = compositorView;
}

public WebContents getActiveWebContents() {
return mPaymentHandlerWebContents != null ? mPaymentHandlerWebContents : mWebContents;
}

public ContentView getActiveContentView() {
return mPaymentHandlerContentView != null ? mPaymentHandlerContentView : getContentView();
}

public TabCompositorView getActiveCompositorView() {
return mPaymentHandlerCompositorView != null ? mPaymentHandlerCompositorView : getCompositorView();
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,39 @@
package com.igalia.wolvic.browser.api.impl;

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.igalia.wolvic.browser.api.WDisplay;
import com.igalia.wolvic.browser.api.WSession;
import com.igalia.wolvic.browser.api.WWebRequestError;

import org.chromium.base.ContextUtils;
import org.chromium.components.embedder_support.view.ContentView;
import org.chromium.content_public.browser.LifecycleState;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.NavigationHandle;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsObserver;
import org.chromium.ui.base.ActivityWindowAndroid;
import org.chromium.ui.base.IntentRequestTracker;
import org.chromium.ui.base.ViewAndroidDelegate;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.url.GURL;
import org.chromium.wolvic.TabCompositorView;
import org.chromium.wolvic.WolvicWebContentsFactory;

import java.security.cert.X509Certificate;

public class TabWebContentsObserver extends WebContentsObserver {
private @NonNull SessionImpl mSession;
private @NonNull TabImpl mTab;
private WebContentsObserver mPaymentWebContentsObserver;

public TabWebContentsObserver(WebContents webContents, @NonNull SessionImpl session) {
super(webContents);
public TabWebContentsObserver(TabImpl tab, @NonNull SessionImpl session) {
super(tab.getActiveWebContents());
mTab = tab;
mSession = session;
}

Expand Down Expand Up @@ -106,6 +121,51 @@ public void didStopLoading(GURL url, boolean isKnownValid) {
dispatchCanGoBackOrForward();
}

@Override
public void onCreateNewPaymentHandler(final WebContents newWebContents) {
WSession.ContentDelegate contentDelegate = mSession.getContentDelegate();
if (contentDelegate == null) {
return;
}

assert newWebContents.getViewAndroidDelegate() != null
: "WebContents should be initialized.";
WindowAndroid windowAndroid = newWebContents.getTopLevelNativeWindow();
Context context = mWebContents.get().getTopLevelNativeWindow().getContext().get();
final TabCompositorView compositorView = new TabCompositorView(context);
compositorView.onNativeLibraryLoaded(windowAndroid);
windowAndroid.setAnimationPlaceholderView(compositorView);

ViewAndroidDelegate viewDelegate = newWebContents.getViewAndroidDelegate();
assert viewDelegate.getContainerView() instanceof ContentView
: "WebContents should not set container views other than ContentView.";

mTab.setPaymentWebContents(newWebContents, (ContentView) viewDelegate.getContainerView(), compositorView);

WDisplay display = mSession.acquireOverlayDisplay(compositorView);
contentDelegate.onShowPaymentHandler(mSession, display, () -> {
if (newWebContents.isDestroyed()) {
return;
}
mTab.setPaymentWebContents(null, null, null);
newWebContents.destroy();
});

// Show Compositor View after attaching to the parent view.
compositorView.setCurrentWebContents(newWebContents);

mPaymentWebContentsObserver = new WebContentsObserver(newWebContents) {
@Override
public void destroy() {
mSession.releaseOverlayDisplay(compositorView);
mTab.setPaymentWebContents(null, null, null);

contentDelegate.onHidePaymentHandler(mSession);
newWebContents.removeObserver(this);
}
};
}

@Override
public void didFailLoad(boolean isInPrimaryMainFrame, int errorCode, GURL failingUrl, @LifecycleState int rfhLifecycleState) {
@Nullable WSession.ProgressDelegate delegate = mSession.getProgressDelegate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import org.chromium.content_public.browser.ImeAdapter;
import org.chromium.content_public.browser.InputMethodManagerWrapper;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.WindowAndroid;

public class TextInputImpl implements WTextInput {
Expand Down Expand Up @@ -180,6 +181,7 @@ public WSession.TextInputDelegate getDelegate() {
}

private ImeAdapter getImeAdapter() {
return mSession.getTab() != null ? mSession.getTab().getImeAdapter() : null;
WebContents webContents = mSession.getTab() != null ? mSession.getTab().getActiveWebContents() : null;
return webContents != null ? ImeAdapter.fromWebContents(webContents) : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import com.igalia.wolvic.ui.widgets.AppServicesProvider;
import com.igalia.wolvic.ui.widgets.KeyboardWidget;
import com.igalia.wolvic.ui.widgets.NavigationBarWidget;
import com.igalia.wolvic.ui.widgets.OverlayContentWidget;
import com.igalia.wolvic.ui.widgets.RootWidget;
import com.igalia.wolvic.ui.widgets.TrayWidget;
import com.igalia.wolvic.ui.widgets.UISurfaceTextureRenderer;
Expand Down Expand Up @@ -1107,6 +1108,8 @@ void handleMotionEvent(final int aHandle, final int aDevice, final boolean aFocu
if (!windowWidget.isLibraryVisible()) {
scale = 1.0f;
}
} else if (widget instanceof OverlayContentWidget) {
scale = 1.0f;
}
final float x = aX / scale;
final float y = aY / scale;
Expand Down
23 changes: 23 additions & 0 deletions app/src/common/shared/com/igalia/wolvic/browser/api/WSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,29 @@ WResult<WSlowScriptResponse> onSlowScript(
*/
@UiThread
default void onShowDynamicToolbar(@NonNull final WSession aSession) {}

public interface OnPaymentHandlerCallback {
void onDismiss();
}

/**
* The view should display its payment handler, overlayed on the active tab.
*
* @param aSession ISession that initiated the callback.
* @param aDisplay IDisplay that initiated the callback.
* @param callback Callback interface.
*/
@UiThread
default void onShowPaymentHandler(@NonNull final WSession aSession,
@NonNull final WDisplay aDisplay,
@NonNull final OnPaymentHandlerCallback callback) {}
/**
* The view should hide its payment handler.
*
* @param aSession ISession that initiated the callback.
*/
@UiThread
default void onHidePaymentHandler(@NonNull final WSession aSession) {}
}

interface NavigationDelegate {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1422,6 +1422,20 @@ public void onExternalResponse(@NonNull WSession aSession, @NonNull WWebResponse
}
}

@Override
public void onShowPaymentHandler(@NonNull final WSession aSession, @NonNull WDisplay aDisplay, @NonNull OnPaymentHandlerCallback callback) {
for (WSession.ContentDelegate listener : mContentListeners) {
listener.onShowPaymentHandler(aSession, aDisplay, callback);
}
}

@Override
public void onHidePaymentHandler(@NonNull final WSession aSession) {
for (WSession.ContentDelegate listener : mContentListeners) {
listener.onHidePaymentHandler(aSession);
}
}

// TextInput Delegate

@Override
Expand Down
Loading
Loading