blob: 9d5ef871be0449ff5f09ef55bcfdef00431b649d [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.weblayer_private;
import android.os.RemoteException;
import android.webkit.ValueCallback;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.weblayer_private.interfaces.IFullscreenCallbackClient;
import org.chromium.weblayer_private.interfaces.ObjectWrapper;
/**
* Owns the c++ FullscreenCallbackProxy class, which is responsible for forwarding all
* FullscreenDelegate delegate calls to this class, which in turn forwards to the
* FullscreenCallbackClient.
*/
@JNINamespace("weblayer")
public final class FullscreenCallbackProxy {
private long mNativeFullscreenCallbackProxy;
private IFullscreenCallbackClient mClient;
private TabImpl mTab;
private FullscreenToast mToast;
private boolean mIsNotifyingClientOfEnter;
// Used so that only the most recent callback supplied to the client is acted on.
private int mNextFullscreenId;
FullscreenCallbackProxy(TabImpl tab, long nativeTab, IFullscreenCallbackClient client) {
assert client != null;
mClient = client;
mTab = tab;
mNativeFullscreenCallbackProxy =
FullscreenCallbackProxyJni.get().createFullscreenCallbackProxy(this, nativeTab);
}
public void setClient(IFullscreenCallbackClient client) {
assert client != null;
mClient = client;
}
public void destroy() {
FullscreenCallbackProxyJni.get().deleteFullscreenCallbackProxy(
mNativeFullscreenCallbackProxy);
mNativeFullscreenCallbackProxy = 0;
destroyToast();
mTab = null;
}
public void destroyToast() {
if (mToast == null) return;
mToast.destroy();
mToast = null;
}
@VisibleForTesting
public boolean didShowFullscreenToast() {
return mToast != null && mToast.didShowFullscreenToast();
}
@CalledByNative
private void enterFullscreen() throws RemoteException {
final int id = ++mNextFullscreenId;
ValueCallback<Void> exitFullscreenCallback = new ValueCallback<Void>() {
@Override
public void onReceiveValue(Void result) {
ThreadUtils.assertOnUiThread();
if (id != mNextFullscreenId) {
// This is an old fullscreen request. Ignore it.
return;
}
if (mNativeFullscreenCallbackProxy == 0) {
throw new IllegalStateException("Called after destroy()");
}
if (mIsNotifyingClientOfEnter) {
throw new IllegalStateException(
"Fullscreen callback must not be called synchronously");
}
destroyToast();
FullscreenCallbackProxyJni.get().doExitFullscreen(mNativeFullscreenCallbackProxy);
}
};
destroyToast();
mToast = new FullscreenToast(mTab);
mIsNotifyingClientOfEnter = true;
try {
mClient.enterFullscreen(ObjectWrapper.wrap(exitFullscreenCallback));
} finally {
mIsNotifyingClientOfEnter = false;
}
}
@CalledByNative
private void exitFullscreen() throws RemoteException {
mClient.exitFullscreen();
destroyToast();
}
@NativeMethods
interface Natives {
long createFullscreenCallbackProxy(FullscreenCallbackProxy proxy, long tab);
void deleteFullscreenCallbackProxy(long proxy);
void doExitFullscreen(long nativeFullscreenCallbackProxy);
}
}