mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 975838 - Part 1: add methods to log or throw if called on the wrong thread, pepper GeckoMenu with thread affinities. r=wesj
This commit is contained in:
parent
8940db8adf
commit
8a8147efd5
@ -8,6 +8,7 @@ package org.mozilla.gecko;
|
||||
import org.mozilla.gecko.gfx.InputConnectionHandler;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils.AssertBehavior;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
@ -361,7 +362,7 @@ final class GeckoEditable
|
||||
}
|
||||
|
||||
private void assertOnIcThread() {
|
||||
ThreadUtils.assertOnThread(mIcRunHandler.getLooper().getThread());
|
||||
ThreadUtils.assertOnThread(mIcRunHandler.getLooper().getThread(), AssertBehavior.THROW);
|
||||
}
|
||||
|
||||
private void geckoPostToIc(Runnable runnable) {
|
||||
|
@ -5,10 +5,16 @@
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
|
||||
import org.mozilla.gecko.gfx.InputConnectionHandler;
|
||||
import org.mozilla.gecko.util.Clipboard;
|
||||
import org.mozilla.gecko.util.GamepadUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils.AssertBehavior;
|
||||
|
||||
import android.R;
|
||||
import android.content.Context;
|
||||
@ -33,11 +39,6 @@ import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
|
||||
class GeckoInputConnection
|
||||
extends BaseInputConnection
|
||||
implements InputConnectionHandler, GeckoEditableListener {
|
||||
@ -115,7 +116,7 @@ class GeckoInputConnection
|
||||
|
||||
public void waitForUiThread(Handler icHandler) {
|
||||
if (DEBUG) {
|
||||
ThreadUtils.assertOnThread(icHandler.getLooper().getThread());
|
||||
ThreadUtils.assertOnThread(icHandler.getLooper().getThread(), AssertBehavior.THROW);
|
||||
Log.d(LOGTAG, "waitForUiThread() blocking on thread " +
|
||||
icHandler.getLooper().getThread().getName());
|
||||
}
|
||||
@ -154,7 +155,7 @@ class GeckoInputConnection
|
||||
public Editable getEditableForUiThread(final Handler uiHandler,
|
||||
final GeckoEditableClient client) {
|
||||
if (DEBUG) {
|
||||
ThreadUtils.assertOnThread(uiHandler.getLooper().getThread());
|
||||
ThreadUtils.assertOnThread(uiHandler.getLooper().getThread(), AssertBehavior.THROW);
|
||||
}
|
||||
final Handler icHandler = client.getInputConnectionHandler();
|
||||
if (icHandler.getLooper() == uiHandler.getLooper()) {
|
||||
@ -171,7 +172,7 @@ class GeckoInputConnection
|
||||
final Method method,
|
||||
final Object[] args) throws Throwable {
|
||||
if (DEBUG) {
|
||||
ThreadUtils.assertOnThread(uiHandler.getLooper().getThread());
|
||||
ThreadUtils.assertOnThread(uiHandler.getLooper().getThread(), AssertBehavior.THROW);
|
||||
Log.d(LOGTAG, "UiEditable." + method.getName() + "() blocking");
|
||||
}
|
||||
synchronized (icHandler) {
|
||||
|
@ -4,7 +4,10 @@
|
||||
|
||||
package org.mozilla.gecko.menu;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils.AssertBehavior;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@ -35,6 +38,12 @@ public class GeckoMenu extends ListView
|
||||
GeckoMenuItem.OnShowAsActionChangedListener {
|
||||
private static final String LOGTAG = "GeckoMenu";
|
||||
|
||||
/**
|
||||
* Controls whether off-UI-thread method calls in this class cause an
|
||||
* exception or just logging.
|
||||
*/
|
||||
private static final AssertBehavior THREAD_ASSERT_BEHAVIOR = AppConstants.RELEASE_BUILD ? AssertBehavior.NONE : AssertBehavior.THROW;
|
||||
|
||||
/*
|
||||
* A callback for a menu item selected event.
|
||||
*/
|
||||
@ -52,7 +61,7 @@ public class GeckoMenu extends ListView
|
||||
// Open the menu.
|
||||
public void openMenu();
|
||||
|
||||
// Show the actual view contaning the menu items. This can either be a parent or sub-menu.
|
||||
// Show the actual view containing the menu items. This can either be a parent or sub-menu.
|
||||
public void showMenu(View menu);
|
||||
|
||||
// Close the menu.
|
||||
@ -130,6 +139,10 @@ public class GeckoMenu extends ListView
|
||||
mSecondaryActionItemBar = (DefaultActionItemBar) LayoutInflater.from(context).inflate(R.layout.menu_secondary_action_bar, null);
|
||||
}
|
||||
|
||||
private static void assertOnUiThread() {
|
||||
ThreadUtils.assertOnUiThread(THREAD_ASSERT_BEHAVIOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuItem add(CharSequence title) {
|
||||
GeckoMenuItem menuItem = new GeckoMenuItem(this, NO_ID, 0, title);
|
||||
@ -159,12 +172,14 @@ public class GeckoMenu extends ListView
|
||||
}
|
||||
|
||||
private void addItem(GeckoMenuItem menuItem) {
|
||||
assertOnUiThread();
|
||||
menuItem.setOnShowAsActionChangedListener(this);
|
||||
mAdapter.addMenuItem(menuItem);
|
||||
mItems.add(menuItem);
|
||||
}
|
||||
|
||||
private boolean addActionItem(final GeckoMenuItem menuItem) {
|
||||
assertOnUiThread();
|
||||
menuItem.setOnShowAsActionChangedListener(this);
|
||||
|
||||
final View actionView = menuItem.getActionView();
|
||||
@ -272,6 +287,7 @@ public class GeckoMenu extends ListView
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
assertOnUiThread();
|
||||
for (GeckoMenuItem menuItem : mItems) {
|
||||
if (menuItem.hasSubMenu()) {
|
||||
SubMenu sub = menuItem.getSubMenu();
|
||||
@ -355,6 +371,7 @@ public class GeckoMenu extends ListView
|
||||
|
||||
@Override
|
||||
public boolean hasVisibleItems() {
|
||||
assertOnUiThread();
|
||||
for (GeckoMenuItem menuItem : mItems) {
|
||||
if (menuItem.isVisible() &&
|
||||
!mPrimaryActionItems.containsKey(menuItem) &&
|
||||
@ -386,6 +403,7 @@ public class GeckoMenu extends ListView
|
||||
|
||||
@Override
|
||||
public void removeItem(int id) {
|
||||
assertOnUiThread();
|
||||
GeckoMenuItem item = (GeckoMenuItem) findItem(id);
|
||||
if (item == null)
|
||||
return;
|
||||
@ -473,6 +491,7 @@ public class GeckoMenu extends ListView
|
||||
}
|
||||
|
||||
public void onItemChanged(GeckoMenuItem item) {
|
||||
assertOnUiThread();
|
||||
if (item.isActionItem()) {
|
||||
final View actionView;
|
||||
if (item.getActionEnum() == GeckoMenuItem.SHOW_AS_ACTION_ALWAYS) {
|
||||
|
@ -5,15 +5,24 @@
|
||||
|
||||
package org.mozilla.gecko.util;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.MessageQueue;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public final class ThreadUtils {
|
||||
private static final String LOGTAG = "ThreadUtils";
|
||||
|
||||
/**
|
||||
* Controls the action taken when a method like
|
||||
* {@link ThreadUtils#assertOnUiThread(AssertBehavior)} detects a problem.
|
||||
*/
|
||||
public static enum AssertBehavior {
|
||||
NONE,
|
||||
THROW,
|
||||
}
|
||||
|
||||
private static Thread sUiThread;
|
||||
private static Thread sBackgroundThread;
|
||||
|
||||
@ -101,28 +110,46 @@ public final class ThreadUtils {
|
||||
GeckoBackgroundThread.post(runnable);
|
||||
}
|
||||
|
||||
public static void assertOnUiThread(final AssertBehavior assertBehavior) {
|
||||
assertOnThread(getUiThread(), assertBehavior);
|
||||
}
|
||||
|
||||
public static void assertOnUiThread() {
|
||||
assertOnThread(getUiThread());
|
||||
assertOnThread(getUiThread(), AssertBehavior.THROW);
|
||||
}
|
||||
|
||||
public static void assertOnGeckoThread() {
|
||||
assertOnThread(sGeckoThread);
|
||||
assertOnThread(sGeckoThread, AssertBehavior.THROW);
|
||||
}
|
||||
|
||||
public static void assertOnBackgroundThread() {
|
||||
assertOnThread(getBackgroundThread());
|
||||
assertOnThread(getBackgroundThread(), AssertBehavior.THROW);
|
||||
}
|
||||
|
||||
public static void assertOnThread(Thread expectedThread) {
|
||||
Thread currentThread = Thread.currentThread();
|
||||
long currentThreadId = currentThread.getId();
|
||||
long expectedThreadId = expectedThread.getId();
|
||||
public static void assertOnThread(final Thread expectedThread) {
|
||||
assertOnThread(expectedThread, AssertBehavior.THROW);
|
||||
}
|
||||
|
||||
if (currentThreadId != expectedThreadId) {
|
||||
throw new IllegalThreadStateException("Expected thread " + expectedThreadId + " (\""
|
||||
+ expectedThread.getName()
|
||||
+ "\"), but running on thread " + currentThreadId
|
||||
+ " (\"" + currentThread.getName() + ")");
|
||||
public static void assertOnThread(final Thread expectedThread, AssertBehavior behavior) {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
final long currentThreadId = currentThread.getId();
|
||||
final long expectedThreadId = expectedThread.getId();
|
||||
|
||||
if (currentThreadId == expectedThreadId) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String message = "Expected thread " +
|
||||
expectedThreadId + " (\"" + expectedThread.getName() +
|
||||
"\"), but running on thread " +
|
||||
currentThreadId + " (\"" + currentThread.getName() + ")";
|
||||
final IllegalThreadStateException e = new IllegalThreadStateException(message);
|
||||
|
||||
switch (behavior) {
|
||||
case THROW:
|
||||
throw e;
|
||||
default:
|
||||
Log.e(LOGTAG, "Method called on wrong thread!", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user