Bug 1260243 - Add GeckoThread.waitOnGecko; r=snorp

GeckoThread.waitOnGecko blocks the current thread and waits for previous
events on the Gecko thread to finish executing before continuing. This
is implemented by synchronously running a dummy event on the Gecko
thread. This patch also lets us get rid of sendEventToGeckoSync in
GeckoAppShell.
This commit is contained in:
Jim Chen 2016-04-05 21:43:40 -04:00
parent 2503738abf
commit 8318ca75b7
8 changed files with 40 additions and 8 deletions

View File

@ -2161,9 +2161,9 @@ public abstract class GeckoApp
return;
}
if (GeckoThread.isRunning()) {
// Let the Gecko thread prepare for exit.
GeckoAppShell.sendEventToGeckoSync(GeckoEvent.createAppBackgroundingEvent());
// Wait for Gecko to handle our pause event sent in onPause.
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
GeckoThread.waitOnGecko();
}
if (mRestartIntent != null) {

View File

@ -612,4 +612,7 @@ public class GeckoThread extends Thread {
queueNativeCallUntil(State.PROFILE_READY, GeckoThread.class,
"speculativeConnectNative", uri);
}
@WrapForJNI @RobocopTarget
public static native void waitOnGecko();
}

View File

@ -84,7 +84,9 @@ class MemoryMonitor extends BroadcastReceiver {
if (increaseMemoryPressure(MEMORY_PRESSURE_HIGH)) {
// We need to wait on Gecko here, because if we haven't reduced
// memory usage enough when we return from this, Android will kill us.
GeckoAppShell.sendEventToGeckoSync(GeckoEvent.createNoOpEvent());
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
GeckoThread.waitOnGecko();
}
}
}

View File

@ -7,9 +7,8 @@ package org.mozilla.gecko.tests;
import java.util.Locale;
import org.mozilla.gecko.BrowserLocaleManager;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.GeckoEvent;
import org.mozilla.gecko.GeckoSharedPrefs;
import org.mozilla.gecko.GeckoThread;
import org.mozilla.gecko.Locales;
import org.mozilla.gecko.PrefsHelper;
@ -46,7 +45,7 @@ public class testOSLocale extends BaseTest {
public void fetch() throws InterruptedException {
// Wait for any pending changes to have taken. Bug 1092580.
GeckoAppShell.sendEventToGeckoSync(GeckoEvent.createNoOpEvent());
GeckoThread.waitOnGecko();
synchronized (waiter) {
PrefsHelper.getPrefs(TO_FETCH, this);
waiter.wait(MAX_WAIT_MS);

View File

@ -199,7 +199,11 @@ public:
mozilla::jni::MakeNativeMethod<GeckoThread::SpeculativeConnect_t>(
mozilla::jni::NativeStub<GeckoThread::SpeculativeConnect_t, Impl>
::template Wrap<&Impl::SpeculativeConnect>)
::template Wrap<&Impl::SpeculativeConnect>),
mozilla::jni::MakeNativeMethod<GeckoThread::WaitOnGecko_t>(
mozilla::jni::NativeStub<GeckoThread::WaitOnGecko_t, Impl>
::template Wrap<&Impl::WaitOnGecko>)
};
};

View File

@ -972,6 +972,9 @@ auto GeckoThread::SetState(mozilla::jni::Object::Param a0) -> void
constexpr char GeckoThread::SpeculativeConnect_t::name[];
constexpr char GeckoThread::SpeculativeConnect_t::signature[];
constexpr char GeckoThread::WaitOnGecko_t::name[];
constexpr char GeckoThread::WaitOnGecko_t::signature[];
constexpr char GeckoThread::ClsLoader_t::name[];
constexpr char GeckoThread::ClsLoader_t::signature[];

View File

@ -2295,6 +2295,19 @@ public:
mozilla::jni::ExceptionMode::ABORT;
};
struct WaitOnGecko_t {
typedef GeckoThread Owner;
typedef void ReturnType;
typedef void SetterType;
typedef mozilla::jni::Args<> Args;
static constexpr char name[] = "waitOnGecko";
static constexpr char signature[] =
"()V";
static const bool isStatic = true;
static const mozilla::jni::ExceptionMode exceptionMode =
mozilla::jni::ExceptionMode::ABORT;
};
struct ClsLoader_t {
typedef GeckoThread Owner;
typedef mozilla::jni::Object::LocalRef ReturnType;

View File

@ -182,6 +182,14 @@ public:
}
specConn->SpeculativeConnect(uri, nullptr);
}
static void WaitOnGecko()
{
struct NoOpEvent : nsAppShell::Event {
void Run() override {}
};
nsAppShell::SyncRunEvent(NoOpEvent());
}
};
class GeckoAppShellSupport final