Commit 312dad5b authored by Jinsuk Kim's avatar Jinsuk Kim Committed by Commit Bot

Android: Replace WebContentsUserdata with base.UserData

This CL rewrites WebContentsUserData using org.chromium.base.UserData.
There should be no functional change. WebContentsUserData is deleted.

Bug: 877878
Change-Id: Ib8f5b2267bf9d21f84661d2e747d8a6c9c1d9d66
Reviewed-on: https://chromium-review.googlesource.com/1189584
Commit-Queue: Jinsuk Kim <jinsukkim@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#589456}
parent fa02ae6a
......@@ -257,8 +257,8 @@ public class PopupWindowTest {
// Now long press on some texts and see if the text handles show up.
DOMUtils.longPressNode(popupContents.getWebContents(), "plain_text");
SelectionPopupController controller =
SelectionPopupController.fromWebContents(popupContents.getWebContents());
SelectionPopupController controller = ThreadUtils.runOnUiThreadBlocking(
() -> SelectionPopupController.fromWebContents(popupContents.getWebContents()));
assertWaitForSelectActionBarStatus(true, controller);
Assert.assertTrue(ThreadUtils.runOnUiThreadBlocking(() -> controller.hasSelection()));
......
......@@ -20,6 +20,7 @@ import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.JsPromptResultReceiver;
import org.chromium.android_webview.JsResultReceiver;
import org.chromium.android_webview.test.util.AwTestTouchUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.Feature;
import org.chromium.content_public.browser.GestureListenerManager;
......@@ -194,8 +195,10 @@ public class WebViewModalDialogOverrideTest {
private void tapViewAndWait(AwTestContainerView view) throws Throwable {
final TapGestureStateListener tapGestureStateListener = new TapGestureStateListener();
int callCount = tapGestureStateListener.getCallCount();
GestureListenerManager.fromWebContents(view.getWebContents())
.addListener(tapGestureStateListener);
ThreadUtils.runOnUiThreadBlocking(() -> {
GestureListenerManager.fromWebContents(view.getWebContents())
.addListener(tapGestureStateListener);
});
AwTestTouchUtils.simulateTouchCenterOfView(view);
tapGestureStateListener.waitForTap(callCount);
......
......@@ -30,11 +30,13 @@ import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher;
import org.chromium.content_public.browser.ViewEventSink;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsObserver;
import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestTouchUtils;
import org.chromium.content_public.browser.test.util.TouchCommon;
import org.chromium.content_public.browser.test.util.WebContentsUtils;
import org.chromium.ui.test.util.UiRestriction;
import java.util.ArrayDeque;
......@@ -197,9 +199,10 @@ public class ContentViewFocusTest {
@Test
@MediumTest
public void testPauseTriggersBlur() throws Exception {
final WebContents webContents = mActivityTestRule.getWebContents();
final CallbackHelper onTitleUpdatedHelper = new CallbackHelper();
final WebContentsObserver observer =
new WebContentsObserver(mActivityTestRule.getWebContents()) {
new WebContentsObserver(webContents) {
@Override
public void titleWasSet(String title) {
mTitle = title;
......@@ -210,7 +213,7 @@ public class ContentViewFocusTest {
String url = UrlUtils.getIsolatedTestFileUrl(
"chrome/test/data/android/content_view_focus/content_view_blur_focus.html");
mActivityTestRule.loadUrl(url);
ViewEventSink eventSink = ViewEventSink.from(mActivityTestRule.getWebContents());
ViewEventSink eventSink = WebContentsUtils.getViewEventSink(webContents);
onTitleUpdatedHelper.waitForCallback(callCount);
Assert.assertEquals("initial", mTitle);
callCount = onTitleUpdatedHelper.getCallCount();
......
......@@ -28,13 +28,13 @@ import org.chromium.base.test.util.UrlUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.content_public.browser.GestureListenerManager;
import org.chromium.content_public.browser.GestureStateListener;
import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer;
import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper;
import org.chromium.content_public.browser.test.util.TouchCommon;
import org.chromium.content_public.browser.test.util.WebContentsUtils;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
......@@ -241,18 +241,14 @@ public class ModalDialogTest {
}
}
private GestureListenerManager getGestureListenerManager() {
return GestureListenerManager.fromWebContents(
mActivityTestRule.getActivity().getCurrentWebContents());
}
/**
* Taps on a view and waits for a callback.
*/
private void tapViewAndWait() throws InterruptedException, TimeoutException {
final TapGestureStateListener tapGestureStateListener = new TapGestureStateListener();
int callCount = tapGestureStateListener.getCallCount();
getGestureListenerManager().addListener(tapGestureStateListener);
WebContentsUtils.getGestureListenerManager(mActivityTestRule.getWebContents())
.addListener(tapGestureStateListener);
TouchCommon.singleClickView(mActivityTestRule.getActivity().getActivityTab().getView());
tapGestureStateListener.waitForTap(callCount);
......
......@@ -31,6 +31,7 @@ import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.DOMUtils;
import org.chromium.content_public.browser.test.util.TestInputMethodManagerWrapper;
import org.chromium.content_public.browser.test.util.TouchCommon;
import org.chromium.content_public.browser.test.util.WebContentsUtils;
import org.chromium.ui.DropdownPopupWindowInterface;
import org.chromium.ui.R;
......@@ -151,7 +152,7 @@ public class AutofillPopupTest {
// brought up.
final WebContents webContents = mActivityTestRule.getActivity().getCurrentWebContents();
final ViewGroup view = webContents.getViewAndroidDelegate().getContainerView();
final ImeAdapter imeAdapter = ImeAdapter.fromWebContents(webContents);
final ImeAdapter imeAdapter = WebContentsUtils.getImeAdapter(webContents);
TestInputMethodManagerWrapper immw = TestInputMethodManagerWrapper.create(imeAdapter);
imeAdapter.setInputMethodManagerWrapper(immw);
......
......@@ -48,13 +48,13 @@ import org.chromium.chrome.test.util.browser.Features;
import org.chromium.content_public.browser.GestureListenerManager;
import org.chromium.content_public.browser.GestureStateListener;
import org.chromium.content_public.browser.SelectionPopupController;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.JavaScriptUtils;
import org.chromium.content_public.browser.test.util.TestTouchUtils;
import org.chromium.content_public.browser.test.util.TouchCommon;
import org.chromium.content_public.browser.test.util.UiUtils;
import org.chromium.content_public.browser.test.util.WebContentsUtils;
import org.chromium.net.test.EmbeddedTestServer;
import java.util.concurrent.TimeUnit;
......@@ -279,9 +279,8 @@ public class FullscreenManagerTest {
};
Tab tab = mActivityTestRule.getActivity().getActivityTab();
WebContents webContents = tab.getWebContents();
GestureListenerManager gestureListenerManager =
GestureListenerManager.fromWebContents(webContents);
WebContentsUtils.getGestureListenerManager(tab.getWebContents());
gestureListenerManager.addListener(scrollListener);
final CallbackHelper viewportCallback = new CallbackHelper();
......
......@@ -20,6 +20,7 @@ import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TouchCommon;
import org.chromium.content_public.browser.test.util.WebContentsUtils;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
......@@ -151,7 +152,7 @@ public class FullscreenManagerTestUtils {
};
GestureListenerManager gestureListenerManager =
GestureListenerManager.fromWebContents(webContents);
WebContentsUtils.getGestureListenerManager(webContents);
gestureListenerManager.addListener(scrollEndListener);
for (int i = 0; i < 10; i++) {
......
......@@ -111,7 +111,7 @@ GestureListenerManager::~GestureListenerManager() {
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
if (j_obj.is_null())
return;
Java_GestureListenerManagerImpl_onDestroy(env, j_obj);
Java_GestureListenerManagerImpl_onNativeDestroyed(env, j_obj);
}
void GestureListenerManager::ResetGestureDetection(
......
......@@ -150,7 +150,7 @@ ImeAdapterAndroid::~ImeAdapterAndroid() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
if (!obj.is_null())
Java_ImeAdapterImpl_destroy(env, obj);
Java_ImeAdapterImpl_onNativeDestroyed(env, obj);
}
void ImeAdapterAndroid::UpdateRenderProcessConnection(
......
......@@ -53,7 +53,7 @@ SelectPopup::~SelectPopup() {
ScopedJavaLocalRef<jobject> j_obj = java_obj_.get(env);
if (j_obj.is_null())
return;
Java_SelectPopup_destroy(env, j_obj);
Java_SelectPopup_onNativeDestroyed(env, j_obj);
}
void SelectPopup::ShowMenu(RenderFrameHost* frame,
......
......@@ -64,7 +64,7 @@ TextSuggestionHostAndroid::~TextSuggestionHostAndroid() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
if (!obj.is_null())
Java_TextSuggestionHost_destroy(env, obj);
Java_TextSuggestionHost_onNativeDestroyed(env, obj);
}
void TextSuggestionHostAndroid::UpdateRenderProcessConnection(
......
......@@ -219,7 +219,6 @@ android_library("content_java") {
"java/src/org/chromium/content/browser/selection/SmartSelectionProvider.java",
"java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java",
"java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java",
"java/src/org/chromium/content/browser/webcontents/WebContentsUserData.java",
"java/src/org/chromium/content/common/ContentSwitchUtils.java",
"java/src/org/chromium/content/common/ServiceManagerConnectionImpl.java",
"java/src/org/chromium/content/common/SurfaceWrapper.java",
......
......@@ -9,12 +9,12 @@ import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import org.chromium.base.UserData;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.content.browser.input.ImeAdapterImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.ViewEventSink.InternalAccessDelegate;
import org.chromium.content_public.browser.WebContents;
import org.chromium.device.gamepad.GamepadList;
......@@ -25,7 +25,7 @@ import org.chromium.ui.base.EventForwarder;
* content components.
*/
@JNINamespace("content")
public class ContentUiEventHandler {
public class ContentUiEventHandler implements UserData {
private final WebContentsImpl mWebContents;
private InternalAccessDelegate mEventDelegate;
private long mNativeContentUiEventHandler;
......@@ -36,8 +36,8 @@ public class ContentUiEventHandler {
}
public static ContentUiEventHandler fromWebContents(WebContents webContents) {
return WebContentsUserData.fromWebContents(
webContents, ContentUiEventHandler.class, UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(ContentUiEventHandler.class, UserDataFactoryLazyHolder.INSTANCE);
}
public ContentUiEventHandler(WebContents webContents) {
......
......@@ -6,9 +6,9 @@ package org.chromium.content.browser;
import android.content.Context;
import org.chromium.base.UserData;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.WebContents;
import org.chromium.device.gamepad.GamepadList;
......@@ -16,7 +16,7 @@ import org.chromium.device.gamepad.GamepadList;
* Encapsulates component class {@link GamepadList} for use in content, with regards
* to its state according to content being attached to/detached from window.
*/
class Gamepad implements WindowEventObserver {
class Gamepad implements WindowEventObserver, UserData {
private final Context mContext;
private static final class UserDataFactoryLazyHolder {
......@@ -24,8 +24,8 @@ class Gamepad implements WindowEventObserver {
}
public static Gamepad from(WebContents webContents) {
return WebContentsUserData.fromWebContents(
webContents, Gamepad.class, UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(Gamepad.class, UserDataFactoryLazyHolder.INSTANCE);
}
public Gamepad(WebContents webContents) {
......
......@@ -10,6 +10,7 @@ import android.view.View;
import org.chromium.base.ObserverList;
import org.chromium.base.ObserverList.RewindableIterator;
import org.chromium.base.TraceEvent;
import org.chromium.base.UserData;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.blink_public.web.WebInputEventType;
......@@ -17,7 +18,6 @@ import org.chromium.content.browser.input.ImeAdapterImpl;
import org.chromium.content.browser.selection.SelectionPopupControllerImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.GestureListenerManager;
import org.chromium.content_public.browser.GestureStateListener;
import org.chromium.content_public.browser.ViewEventSink.InternalAccessDelegate;
......@@ -29,11 +29,11 @@ import org.chromium.ui.base.ViewAndroidDelegate;
* Implementation of the interface {@link GestureListenerManager}. Manages
* the {@link GestureStateListener} instances, and invokes them upon
* notification of various events.
* Instantiated object is held inside {@link WebContentsUserData} that is
* managed by {@link WebContents}.
* Instantiated object is held inside {@link UserDataHost} that is managed by {@link WebContents}.
*/
@JNINamespace("content")
public class GestureListenerManagerImpl implements GestureListenerManager, WindowEventObserver {
public class GestureListenerManagerImpl
implements GestureListenerManager, WindowEventObserver, UserData {
private static final class UserDataFactoryLazyHolder {
private static final UserDataFactory<GestureListenerManagerImpl> INSTANCE =
GestureListenerManagerImpl::new;
......@@ -67,8 +67,9 @@ public class GestureListenerManagerImpl implements GestureListenerManager, Windo
* Creates one if not present.
*/
public static GestureListenerManagerImpl fromWebContents(WebContents webContents) {
return WebContentsUserData.fromWebContents(
webContents, GestureListenerManagerImpl.class, UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(
GestureListenerManagerImpl.class, UserDataFactoryLazyHolder.INSTANCE);
}
public GestureListenerManagerImpl(WebContents webContents) {
......@@ -258,7 +259,7 @@ public class GestureListenerManagerImpl implements GestureListenerManager, Windo
}
@CalledByNative
private void onDestroy() {
private void onNativeDestroyed() {
for (mIterator.rewind(); mIterator.hasNext();) mIterator.next().onDestroyed();
mListeners.clear();
mNativeGestureListenerManager = 0;
......
......@@ -6,10 +6,11 @@ package org.chromium.content.browser;
import android.util.Pair;
import org.chromium.base.UserData;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.JavascriptInjector;
import org.chromium.content_public.browser.WebContents;
......@@ -23,7 +24,7 @@ import java.util.Set;
* Implementation class of the interface {@link JavascriptInjector}.
*/
@JNINamespace("content")
public class JavascriptInjectorImpl implements JavascriptInjector {
public class JavascriptInjectorImpl implements JavascriptInjector, UserData {
private static final class UserDataFactoryLazyHolder {
private static final UserDataFactory<JavascriptInjectorImpl> INSTANCE =
JavascriptInjectorImpl::new;
......@@ -39,8 +40,8 @@ public class JavascriptInjectorImpl implements JavascriptInjector {
* Creates one if not present.
*/
public static JavascriptInjector fromWebContents(WebContents webContents) {
return WebContentsUserData.fromWebContents(
webContents, JavascriptInjectorImpl.class, UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(JavascriptInjectorImpl.class, UserDataFactoryLazyHolder.INSTANCE);
}
public JavascriptInjectorImpl(WebContents webContents) {
......
......@@ -7,9 +7,10 @@ package org.chromium.content.browser;
import android.view.InputDevice;
import android.view.MotionEvent;
import org.chromium.base.UserData;
import org.chromium.content.browser.input.ImeAdapterImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.ImeEventObserver;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.EventForwarder;
......@@ -17,7 +18,7 @@ import org.chromium.ui.base.EventForwarder;
/**
* Bridges content and joystick device event conversion and forwarding.
*/
public class JoystickHandler implements ImeEventObserver {
public class JoystickHandler implements ImeEventObserver, UserData {
private final EventForwarder mEventForwarder;
// Whether joystick scroll is enabled. It's disabled when an editable field is focused.
......@@ -28,8 +29,8 @@ public class JoystickHandler implements ImeEventObserver {
}
public static JoystickHandler fromWebContents(WebContents webContents) {
return WebContentsUserData.fromWebContents(
webContents, JoystickHandler.class, UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(JoystickHandler.class, UserDataFactoryLazyHolder.INSTANCE);
}
/**
......
......@@ -4,9 +4,10 @@
package org.chromium.content.browser;
import org.chromium.base.UserData;
import org.chromium.content.browser.selection.SelectionPopupControllerImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.WebContents;
import java.util.ArrayList;
......@@ -15,7 +16,7 @@ import java.util.List;
/**
* Controls all the popup views on content view.
*/
public class PopupController {
public class PopupController implements UserData {
/** Interface for popup views that expose a method for hiding itself. */
public interface HideablePopup {
/**
......@@ -31,8 +32,8 @@ public class PopupController {
private final List<HideablePopup> mHideablePopups = new ArrayList<>();
public static PopupController fromWebContents(WebContents webContents) {
return WebContentsUserData.fromWebContents(
webContents, PopupController.class, UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(PopupController.class, UserDataFactoryLazyHolder.INSTANCE);
}
private PopupController(WebContents webContents) {}
......
......@@ -7,9 +7,9 @@ package org.chromium.content.browser;
import android.content.res.Configuration;
import org.chromium.base.TraceEvent;
import org.chromium.base.UserData;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.ViewEventSink;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.ViewAndroidDelegate;
......@@ -18,7 +18,7 @@ import org.chromium.ui.base.WindowAndroid.ActivityStateObserver;
/**
* Implementation of the interface {@link ViewEventSink}.
*/
public final class ViewEventSinkImpl implements ViewEventSink, ActivityStateObserver {
public final class ViewEventSinkImpl implements ViewEventSink, ActivityStateObserver, UserData {
private final WebContentsImpl mWebContents;
// Whether the container view has view-level focus.
......@@ -40,8 +40,8 @@ public final class ViewEventSinkImpl implements ViewEventSink, ActivityStateObse
}
public static ViewEventSinkImpl from(WebContents webContents) {
return WebContentsUserData.fromWebContents(
webContents, ViewEventSinkImpl.class, UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(ViewEventSinkImpl.class, UserDataFactoryLazyHolder.INSTANCE);
}
public ViewEventSinkImpl(WebContents webContents) {
......
......@@ -8,9 +8,9 @@ import android.content.res.Configuration;
import org.chromium.base.ActivityState;
import org.chromium.base.ObserverList;
import org.chromium.base.UserData;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.display.DisplayAndroid;
......@@ -19,7 +19,7 @@ import org.chromium.ui.display.DisplayAndroid.DisplayAndroidObserver;
/**
* Manages {@link WindowEventObserver} instances used for WebContents.
*/
public final class WindowEventObserverManager implements DisplayAndroidObserver {
public final class WindowEventObserverManager implements DisplayAndroidObserver, UserData {
private final ObserverList<WindowEventObserver> mWindowEventObservers = new ObserverList<>();
private WindowAndroid mWindowAndroid;
......@@ -36,8 +36,9 @@ public final class WindowEventObserverManager implements DisplayAndroidObserver
}
public static WindowEventObserverManager from(WebContents webContents) {
return WebContentsUserData.fromWebContents(
webContents, WindowEventObserverManager.class, UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(
WindowEventObserverManager.class, UserDataFactoryLazyHolder.INSTANCE);
}
private WindowEventObserverManager(WebContents webContents) {
......
......@@ -27,6 +27,7 @@ import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeL
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import org.chromium.base.UserData;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
......@@ -36,7 +37,6 @@ import org.chromium.content.browser.WindowEventObserverManager;
import org.chromium.content.browser.accessibility.captioning.CaptioningController;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.AccessibilitySnapshotCallback;
import org.chromium.content_public.browser.AccessibilitySnapshotNode;
import org.chromium.content_public.browser.WebContents;
......@@ -54,7 +54,8 @@ import java.util.Locale;
*/
@JNINamespace("content")
public class WebContentsAccessibilityImpl extends AccessibilityNodeProvider
implements AccessibilityStateChangeListener, WebContentsAccessibility, WindowEventObserver {
implements AccessibilityStateChangeListener, WebContentsAccessibility, WindowEventObserver,
UserData {
// Constants from AccessibilityNodeInfo defined in the K SDK.
private static final int ACTION_COLLAPSE = 0x00080000;
private static final int ACTION_EXPAND = 0x00040000;
......@@ -140,8 +141,9 @@ public class WebContentsAccessibilityImpl extends AccessibilityNodeProvider
}
public static WebContentsAccessibilityImpl fromWebContents(WebContents webContents) {
return WebContentsUserData.fromWebContents(webContents, WebContentsAccessibilityImpl.class,
UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(
WebContentsAccessibilityImpl.class, UserDataFactoryLazyHolder.INSTANCE);
}
protected WebContentsAccessibilityImpl(WebContents webContents) {
......
......@@ -31,6 +31,7 @@ import android.view.inputmethod.InputMethodManager;
import org.chromium.base.Log;
import org.chromium.base.TraceEvent;
import org.chromium.base.UserData;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
......@@ -43,7 +44,6 @@ import org.chromium.content.browser.WindowEventObserverManager;
import org.chromium.content.browser.picker.InputDialogContainer;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.ImeAdapter;
import org.chromium.content_public.browser.ImeEventObserver;
import org.chromium.content_public.browser.InputMethodManagerWrapper;
......@@ -81,7 +81,7 @@ import java.util.List;
* lifetime of the object.
*/
@JNINamespace("content")
public class ImeAdapterImpl implements ImeAdapter, WindowEventObserver {
public class ImeAdapterImpl implements ImeAdapter, WindowEventObserver, UserData {
private static final String TAG = "cr_Ime";
private static final boolean DEBUG_LOGS = false;
......@@ -173,8 +173,8 @@ public class ImeAdapterImpl implements ImeAdapter, WindowEventObserver {
* @return {@link ImeAdapter} object.
*/
public static ImeAdapterImpl fromWebContents(WebContents webContents) {
return WebContentsUserData.fromWebContents(
webContents, ImeAdapterImpl.class, UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(ImeAdapterImpl.class, UserDataFactoryLazyHolder.INSTANCE);
}
/**
......@@ -685,7 +685,7 @@ public class ImeAdapterImpl implements ImeAdapter, WindowEventObserver {
}
@CalledByNative
private void destroy() {
private void onNativeDestroyed() {
resetAndHideKeyboard();
mNativeImeAdapterAndroid = 0;
mIsConnected = false;
......
......@@ -8,6 +8,7 @@ import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import org.chromium.base.UserData;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
......@@ -18,7 +19,6 @@ import org.chromium.content.browser.WindowEventObserverManager;
import org.chromium.content.browser.accessibility.WebContentsAccessibilityImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.DeviceFormFactor;
import org.chromium.ui.base.ViewAndroidDelegate;
......@@ -31,8 +31,8 @@ import java.util.List;
* Handles the popup UI for the lt&;select&gt; HTML tag support.
*/
@JNINamespace("content")
public class SelectPopup
implements HideablePopup, ViewAndroidDelegate.ContainerViewObserver, WindowEventObserver {
public class SelectPopup implements HideablePopup, ViewAndroidDelegate.ContainerViewObserver,
WindowEventObserver, UserData {
/** UI for Select popup. */
public interface Ui {
/**
......@@ -62,8 +62,8 @@ public class SelectPopup
* @return {@link SelectPopup} object.
*/
public static SelectPopup fromWebContents(WebContents webContents) {
return WebContentsUserData.fromWebContents(
webContents, SelectPopup.class, UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(SelectPopup.class, UserDataFactoryLazyHolder.INSTANCE);
}
@CalledByNative
......@@ -172,7 +172,7 @@ public class SelectPopup
}
@CalledByNative
private void destroy() {
private void onNativeDestroyed() {
mNativeSelectPopup = 0;
}
......
......@@ -6,6 +6,7 @@ package org.chromium.content.browser.input;
import android.content.Context;
import org.chromium.base.UserData;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
......@@ -15,7 +16,6 @@ import org.chromium.content.browser.WindowEventObserver;
import org.chromium.content.browser.WindowEventObserverManager;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.ViewAndroidDelegate;
import org.chromium.ui.base.WindowAndroid;
......@@ -26,7 +26,7 @@ import org.chromium.ui.base.WindowAndroid;
* the commands in that menu (by calling back to the C++ class).
*/
@JNINamespace("content")
public class TextSuggestionHost implements WindowEventObserver, HideablePopup {
public class TextSuggestionHost implements WindowEventObserver, HideablePopup, UserData {
private long mNativeTextSuggestionHost;
private final WebContentsImpl mWebContents;
private final Context mContext;
......@@ -49,8 +49,8 @@ public class TextSuggestionHost implements WindowEventObserver, HideablePopup {
* @return {@link TextSuggestionHost} object.
*/
public static TextSuggestionHost fromWebContents(WebContents webContents) {
return WebContentsUserData.fromWebContents(
webContents, TextSuggestionHost.class, UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(TextSuggestionHost.class, UserDataFactoryLazyHolder.INSTANCE);
}
/**
......@@ -200,7 +200,7 @@ public class TextSuggestionHost implements WindowEventObserver, HideablePopup {
}
@CalledByNative
private void destroy() {
private void onNativeDestroyed() {
hidePopups();
mNativeTextSuggestionHost = 0;
}
......
......@@ -36,6 +36,7 @@ import android.view.textclassifier.TextClassifier;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.Log;
import org.chromium.base.UserData;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
......@@ -51,7 +52,6 @@ import org.chromium.content.browser.WindowEventObserverManager;
import org.chromium.content.browser.input.ImeAdapterImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content.browser.webcontents.WebContentsUserData;
import org.chromium.content_public.browser.ActionModeCallbackHelper;
import org.chromium.content_public.browser.ImeEventObserver;
import org.chromium.content_public.browser.SelectionClient;
......@@ -73,7 +73,7 @@ import java.util.List;
@TargetApi(Build.VERSION_CODES.M)
public class SelectionPopupControllerImpl extends ActionModeCallbackHelper
implements ImeEventObserver, SelectionPopupController, WindowEventObserver, HideablePopup,
ContainerViewObserver {
ContainerViewObserver, UserData {
private static final String TAG = "SelectionPopupCtlr"; // 20 char limit
/**
......@@ -199,8 +199,9 @@ public class SelectionPopupControllerImpl extends ActionModeCallbackHelper
* {@link #create()} is not called yet.
*/
public static SelectionPopupControllerImpl fromWebContents(WebContents webContents) {
return WebContentsUserData.fromWebContents(webContents, SelectionPopupControllerImpl.class,
UserDataFactoryLazyHolder.INSTANCE);
return ((WebContentsImpl) webContents)
.getOrSetUserData(
SelectionPopupControllerImpl.class, UserDataFactoryLazyHolder.INSTANCE);
}
/**
......
......@@ -20,6 +20,8 @@ import android.view.Surface;
import org.chromium.base.Callback;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.base.UserData;
import org.chromium.base.UserDataHost;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
......@@ -51,9 +53,7 @@ import org.chromium.ui.base.ViewAndroidDelegate;
import org.chromium.ui.base.WindowAndroid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
......@@ -188,7 +188,7 @@ public class WebContentsImpl implements WebContents, RenderFrameHostDelegate, Wi
private boolean mInitialized;
private static class WebContentsInternalsImpl implements WebContentsInternals {
public HashMap<Class<?>, WebContentsUserData> userDataMap;
public UserDataHost userDataHost;
public ViewAndroidDelegate viewAndroidDelegate;
}
......@@ -216,7 +216,7 @@ public class WebContentsImpl implements WebContents, RenderFrameHostDelegate, Wi
mInternalsHolder = internalsHolder;
WebContentsInternalsImpl internals = new WebContentsInternalsImpl();
internals.userDataMap = new HashMap<>();
internals.userDataHost = new UserDataHost();
mInternalsHolder.set(internals);
mRenderCoordinates = new RenderCoordinatesImpl();
......@@ -319,9 +319,13 @@ public class WebContentsImpl implements WebContents, RenderFrameHostDelegate, Wi
@Override
public void destroy() {
// Note that |WebContents.destroy| is not guaranteed to be invoked.
// Any resource release relying on this method will likely be leaked.
if (!ThreadUtils.runningOnUiThread()) {
throw new IllegalStateException("Attempting to destroy WebContents on non-UI thread");
}
if (mNativeWebContentsAndroid != 0) nativeDestroyWebContents(mNativeWebContentsAndroid);
}
......@@ -797,40 +801,42 @@ public class WebContentsImpl implements WebContents, RenderFrameHostDelegate, Wi
* not created yet, or {@code userDataFactory} is null, or the internal data
* storage is already garbage-collected.
*/
public <T> T getOrSetUserData(Class<T> key, UserDataFactory<T> userDataFactory) {
public <T extends UserData> T getOrSetUserData(
Class<T> key, UserDataFactory<T> userDataFactory) {
// For tests that go without calling |initialize|.
if (!mInitialized) return null;
Map<Class<?>, WebContentsUserData> userDataMap = getUserDataMap();
UserDataHost userDataHost = getUserDataHost();
// Map can be null after WebView gets gc'ed on its way to destruction.
if (userDataMap == null) {
Log.e(TAG, "UserDataMap can't be found");
if (userDataHost == null) {
Log.e(TAG, "UserDataHost can't be found");
return null;
}
WebContentsUserData data = userDataMap.get(key);
T data = userDataHost.getUserData(key);
if (data == null && userDataFactory != null) {
assert !userDataMap.containsKey(key); // Do not allow duplicated Data
assert userDataHost.getUserData(key) == null; // Do not allow overwriting
T object = userDataFactory.create(this);
assert key.isInstance(object);
userDataMap.put(key, new WebContentsUserData(object));
// Retrieves from the map again to return null in case |setUserData| fails
// to store the object.
data = userDataMap.get(key);
data = userDataHost.setUserData(key, object);
}
return data != null ? key.cast(data.getObject()) : null;
return key.cast(data);
}
/**
* @return {@code UserDataMap} that contains internal user data. {@code null} if
* the map is already gc'ed.
* @return {@code UserDataHost} that contains internal user data. {@code null} if
* it is already gc'ed.
*/
private Map<Class<?>, WebContentsUserData> getUserDataMap() {
private UserDataHost getUserDataHost() {
if (mInternalsHolder == null) return null;
WebContentsInternals internals = mInternalsHolder.get();
if (internals == null) return null;
return ((WebContentsInternalsImpl) internals).userDataMap;
return ((WebContentsInternalsImpl) internals).userDataHost;
}
// WindowEventObserver
......
// Copyright 2017 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.content.browser.webcontents;
import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content_public.browser.WebContents;
/**
* Holds an object to be stored in {@code userDataMap} in {@link WebContents} for those
* classes that have the lifetime of {@link WebContents} without hanging directly onto it.
* To create an object of a class {@code MyClass}, define a static method
* {@code fromWebContents()} where you call:
* <code>
* WebContentsUserData.fromWebContents(webContents, MyClass.class, MyClass::new);
* </code>
*
* {@code MyClass} should have a contstructor that accepts only one parameter:
* <code>
* public MyClass(WebContents webContents);
* </code>
*/
public final class WebContentsUserData {
private final Object mObject;
WebContentsUserData(Object object) {
mObject = object;
}
Object getObject() {
return mObject;
}
/**
* Looks up the generic object of the given web contents.
*
* @param webContents The web contents for which to lookup the object.
* @param key Class instance of the object used as the key.
* @param userDataFactory Factory that creates an object of the generic class. Creates a new
* instance and returns it if not created yet.
* @return The object of the given web contents. Can be null if the object was not set,
* the user data map is already garbage-collected, or {@link WebContents#initialize()}
* is not called yet.
*
*/
public static <T> T fromWebContents(
WebContents webContents, Class<T> key, UserDataFactory<T> userDataFactory) {
return ((WebContentsImpl) webContents).getOrSetUserData(key, userDataFactory);
}
}
......@@ -27,7 +27,6 @@ import org.chromium.base.test.util.UrlUtils;
import org.chromium.content.browser.input.ChromiumBaseInputConnection;
import org.chromium.content.browser.input.ImeTestUtils;
import org.chromium.content.browser.selection.SelectionPopupControllerImpl;
import org.chromium.content_public.browser.ImeAdapter;
import org.chromium.content_public.browser.SelectionClient;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.test.ContentJUnit4ClassRunner;
......@@ -107,8 +106,7 @@ public class ContentTextSelectionTest {
mActivityTestRule.waitForActiveShellToBeDoneLoading();
mWebContents = mActivityTestRule.getWebContents();
mSelectionPopupController =
SelectionPopupControllerImpl.fromWebContents(mActivityTestRule.getWebContents());
mSelectionPopupController = mActivityTestRule.getSelectionPopupController();
waitForSelectActionBarVisible(false);
waitForPastePopupStatus(false);
}
......@@ -635,8 +633,7 @@ public class ContentTextSelectionTest {
private CharSequence getTextBeforeCursor(final int length, final int flags) {
final ChromiumBaseInputConnection connection =
(ChromiumBaseInputConnection) ImeAdapter
.fromWebContents(mActivityTestRule.getWebContents())
(ChromiumBaseInputConnection) mActivityTestRule.getImeAdapter()
.getInputConnectionForTest();
return ImeTestUtils.runBlockingOnHandlerNoException(
connection.getHandler(), new Callable<CharSequence>() {
......
......@@ -26,6 +26,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.MinAndroidSdkLevel;
import org.chromium.base.test.util.UrlUtils;
......@@ -34,6 +35,7 @@ import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_shell_apk.ContentShellActivityTestRule;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutionException;
/**
* Tests for WebContentsAccessibility. Actually tests WebContentsAccessibilityImpl that
......@@ -64,8 +66,7 @@ public class WebContentsAccessibilityTest {
* returns something not null.
*/
private AccessibilityNodeProvider enableAccessibilityAndWaitForNodeProvider() {
final WebContentsAccessibilityImpl wcax =
WebContentsAccessibilityImpl.fromWebContents(mActivityTestRule.getWebContents());
final WebContentsAccessibilityImpl wcax = mActivityTestRule.getWebContentsAccessibility();
wcax.setState(true);
wcax.setAccessibilityEnabledForTesting();
......@@ -220,7 +221,8 @@ public class WebContentsAccessibilityTest {
}
});
int virtualViewId = findNodeMatching(provider, View.NO_ID, matcher);
int virtualViewId = ThreadUtils.runOnUiThreadBlockingNoException(
() -> findNodeMatching(provider, View.NO_ID, matcher));
Assert.assertNotEquals(View.NO_ID, virtualViewId);
return virtualViewId;
}
......@@ -313,11 +315,11 @@ public class WebContentsAccessibilityTest {
}
});
boolean result1 = provider.performAction(
editFieldVirtualViewId, AccessibilityNodeInfo.ACTION_FOCUS, null);
boolean result2 = provider.performAction(
editFieldVirtualViewId, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
boolean result3 = provider.performAction(editFieldVirtualViewId,
boolean result1 = performActionOnUiThread(
provider, editFieldVirtualViewId, AccessibilityNodeInfo.ACTION_FOCUS, null);
boolean result2 = performActionOnUiThread(provider, editFieldVirtualViewId,
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
boolean result3 = performActionOnUiThread(provider, editFieldVirtualViewId,
AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
// Assert all actions are performed successfully.
......@@ -339,20 +341,26 @@ public class WebContentsAccessibilityTest {
// Simulate swipe left.
for (int i = 3; i >= 0; i--) {
boolean result = provider.performAction(editFieldVirtualViewId,
boolean result = performActionOnUiThread(provider, editFieldVirtualViewId,
AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
// Assert that the index of the character traversed is correct.
Assert.assertEquals(i, mostRecentCharIndex.value);
}
// Simulate swipe right.
for (int i = 0; i <= 3; i++) {
boolean result = provider.performAction(editFieldVirtualViewId,
boolean result = performActionOnUiThread(provider, editFieldVirtualViewId,
AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, args);
// Assert that the index of the character traversed is correct.
Assert.assertEquals(i, mostRecentCharIndex.value);
}
}
private static boolean performActionOnUiThread(AccessibilityNodeProvider provider, int viewId,
int action, Bundle args) throws ExecutionException {
return ThreadUtils.runOnUiThreadBlocking(
() -> provider.performAction(viewId, action, args));
}
/**
* Text fields should expose ACTION_SET_TEXT
*/
......
......@@ -60,7 +60,7 @@ class ImeActivityTestRule extends ContentShellActivityTestRule {
public void setUpForUrl(String url) throws Exception {
launchContentShellWithUrlSync(url);
mSelectionPopupController = SelectionPopupControllerImpl.fromWebContents(getWebContents());
mSelectionPopupController = getSelectionPopupController();
final ImeAdapter imeAdapter = getImeAdapter();
InputConnectionProvider provider =
......@@ -126,10 +126,6 @@ class ImeActivityTestRule extends ContentShellActivityTestRule {
resetAllStates();
}
SelectionPopupControllerImpl getSelectionPopupController() {
return mSelectionPopupController;
}
TestCallbackHelperContainer getTestCallBackHelperContainer() {
return mCallbackContainer;
}
......@@ -307,10 +303,6 @@ class ImeActivityTestRule extends ContentShellActivityTestRule {
});
}
ImeAdapterImpl getImeAdapter() {
return ImeAdapterImpl.fromWebContents(getWebContents());
}
ChromiumBaseInputConnection getInputConnection() {
try {
return ThreadUtils.runOnUiThreadBlocking(new Callable<ChromiumBaseInputConnection>() {
......
......@@ -24,7 +24,6 @@ import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.DOMUtils;
import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer;
import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper;
import org.chromium.content_public.browser.test.util.WebContentsUtils;
import org.chromium.content_shell_apk.ContentShellActivityTestRule;
import org.chromium.content_shell_apk.ContentShellActivityTestRule.RerunWithUpdatedContainerView;
......@@ -61,7 +60,7 @@ public class SelectPopupTest {
@Override
public boolean isSatisfied() {
return WebContentsUtils.isSelectPopupVisible(mActivityTestRule.getWebContents());
return mActivityTestRule.getSelectPopup().isVisibleForTesting();
}
}
......@@ -72,7 +71,7 @@ public class SelectPopupTest {
@Override
public boolean isSatisfied() {
return !WebContentsUtils.isSelectPopupVisible(mActivityTestRule.getWebContents());
return !mActivityTestRule.getSelectPopup().isVisibleForTesting();
}
}
......
......@@ -282,7 +282,7 @@ public class TextSuggestionMenuTest {
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
TextSuggestionHost.fromWebContents(webContents)
getTextSuggestionHost(webContents)
.getTextSuggestionsPopupWindowForTesting()
.dismiss();
}
......@@ -313,12 +313,11 @@ public class TextSuggestionMenuTest {
@Override
public boolean isSatisfied() {
SuggestionsPopupWindow suggestionsPopupWindow =
TextSuggestionHost.fromWebContents(webContents)
getTextSuggestionHost(webContents)
.getTextSuggestionsPopupWindowForTesting();
SuggestionsPopupWindow spellCheckPopupWindow =
TextSuggestionHost.fromWebContents(webContents)
.getSpellCheckPopupWindowForTesting();
getTextSuggestionHost(webContents).getSpellCheckPopupWindowForTesting();
return suggestionsPopupWindow == null && spellCheckPopupWindow == null;
}
......@@ -327,16 +326,14 @@ public class TextSuggestionMenuTest {
private View getContentView(WebContents webContents) {
SuggestionsPopupWindow suggestionsPopupWindow =
TextSuggestionHost.fromWebContents(webContents)
.getTextSuggestionsPopupWindowForTesting();
getTextSuggestionHost(webContents).getTextSuggestionsPopupWindowForTesting();
if (suggestionsPopupWindow != null) {
return suggestionsPopupWindow.getContentViewForTesting();
}
SuggestionsPopupWindow spellCheckPopupWindow =
TextSuggestionHost.fromWebContents(webContents)
.getSpellCheckPopupWindowForTesting();
getTextSuggestionHost(webContents).getSpellCheckPopupWindowForTesting();
if (spellCheckPopupWindow != null) {
return spellCheckPopupWindow.getContentViewForTesting();
......@@ -345,6 +342,11 @@ public class TextSuggestionMenuTest {
return null;
}
private TextSuggestionHost getTextSuggestionHost(WebContents webContents) {
return ThreadUtils.runOnUiThreadBlockingNoException(
() -> TextSuggestionHost.fromWebContents(webContents));
}
private ListView getSuggestionList(WebContents webContents) {
View contentView = getContentView(webContents);
return (ListView) contentView.findViewById(R.id.suggestionContainer);
......
......@@ -8,9 +8,14 @@ import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.content.browser.input.SelectPopup;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content_public.browser.GestureListenerManager;
import org.chromium.content_public.browser.ImeAdapter;
import org.chromium.content_public.browser.RenderFrameHost;
import org.chromium.content_public.browser.ViewEventSink;
import org.chromium.content_public.browser.WebContents;
import java.util.concurrent.ExecutionException;
/**
* Collection of test-only WebContents utilities.
*/
......@@ -55,6 +60,43 @@ public class WebContentsUtils {
((WebContentsImpl) webContents).simulateRendererKilledForTesting(wasOomProtected));
}
/**
* Returns {@link ImeAdapter} instance associated with a given {@link WebContents}.
* @param webContents The WebContents in use.
*/
public static ImeAdapter getImeAdapter(WebContents webContents) {
try {
return ThreadUtils.runOnUiThreadBlocking(() -> ImeAdapter.fromWebContents(webContents));
} catch (ExecutionException e) {
return null;
}
}
/**
* Returns {@link GestureListenerManager} instance associated with a given {@link WebContents}.
* @param webContents The WebContents in use.
*/
public static GestureListenerManager getGestureListenerManager(WebContents webContents) {
try {
return ThreadUtils.runOnUiThreadBlocking(
() -> GestureListenerManager.fromWebContents(webContents));
} catch (ExecutionException e) {
return null;
}
}
/**
* Returns {@link ViewEventSink} instance associated with a given {@link WebContents}.
* @param webContents The WebContents in use.
*/
public static ViewEventSink getViewEventSink(WebContents webContents) {
try {
return ThreadUtils.runOnUiThreadBlocking(() -> ViewEventSink.from(webContents));
} catch (ExecutionException e) {
return null;
}
}
private static native void nativeReportAllFrameSubmissions(
WebContents webContents, boolean enabled);
private static native RenderFrameHost nativeGetFocusedFrame(WebContents webContents);
......
......@@ -25,6 +25,10 @@ import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.UrlUtils;
import org.chromium.content.browser.RenderCoordinatesImpl;
import org.chromium.content.browser.accessibility.WebContentsAccessibilityImpl;
import org.chromium.content.browser.input.ImeAdapterImpl;
import org.chromium.content.browser.input.SelectPopup;
import org.chromium.content.browser.selection.SelectionPopupControllerImpl;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content_public.browser.JavascriptInjector;
import org.chromium.content_public.browser.LoadUrlParams;
......@@ -156,13 +160,60 @@ public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellA
}
}
/**
* Returns the {@link SelectionPopupControllerImpl} of the WebContents.
*/
public SelectionPopupControllerImpl getSelectionPopupController() {
try {
return ThreadUtils.runOnUiThreadBlocking(() -> {
return SelectionPopupControllerImpl.fromWebContents(
getActivity().getActiveShell().getWebContents());
});
} catch (ExecutionException e) {
return null;
}
}
/**
* Returns the {@link ImeAdapterImpl} of the WebContents.
*/
public ImeAdapterImpl getImeAdapter() {
try {
return ThreadUtils.runOnUiThreadBlocking(
() -> ImeAdapterImpl.fromWebContents(getWebContents()));
} catch (ExecutionException e) {
return null;
}
}
/**
* Returns the {@link SelectPopup} of the WebContents.
*/
public SelectPopup getSelectPopup() {
try {
return ThreadUtils.runOnUiThreadBlocking(
() -> SelectPopup.fromWebContents(getWebContents()));
} catch (ExecutionException e) {
return null;
}
}
public WebContentsAccessibilityImpl getWebContentsAccessibility() {
try {
return ThreadUtils.runOnUiThreadBlocking(
() -> WebContentsAccessibilityImpl.fromWebContents(getWebContents()));
} catch (ExecutionException e) {
return null;
}
}
/**
* Returns the RenderCoordinates of the WebContents.
*/
public RenderCoordinatesImpl getRenderCoordinates() {
try {
return ThreadUtils.runOnUiThreadBlocking(
() -> { return ((WebContentsImpl) getWebContents()).getRenderCoordinates(); });
() -> ((WebContentsImpl) getWebContents()).getRenderCoordinates());
} catch (ExecutionException e) {
return null;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment