Bug 1195496 - Implement speculative connection method in GeckoThread; r=snorp

One thing we do in the Fennec CLH is to make a speculative connection
based on the URI that's passed in. However, by the time the CLH runs,
we're far along into startup, and the advantage of a speculative
connection is reduced. This patch implements making speculative
connection as a method in GeckoThread, so that Fennec can make a
speculative connection without relying on the Fennec CLH.
This commit is contained in:
Jim Chen 2015-08-19 18:14:47 -04:00
parent a449ec6eca
commit 4b257d53f5
5 changed files with 104 additions and 0 deletions

View File

@ -546,4 +546,16 @@ public class GeckoThread extends Thread implements GeckoEventListener {
flushQueuedNativeCalls(newState);
return true;
}
@WrapForJNI(stubName = "SpeculativeConnect")
private static native void speculativeConnectNative(String uri);
public static void speculativeConnect(final String uri) {
// This is almost always called before Gecko loads, so we don't
// bother checking here if Gecko is actually loaded or not.
// Speculative connection depends on proxy settings,
// so the earliest it can happen is after profile is ready.
queueNativeCallUntil(State.PROFILE_READY, GeckoThread.class,
"speculativeConnectNative", uri);
}
}

View File

@ -36,6 +36,21 @@ public:
template<class Impl>
constexpr JNINativeMethod ANRReporter::Natives<Impl>::methods[];
template<class Impl>
class GeckoThread::Natives : public mozilla::jni::NativeImpl<GeckoThread, Impl>
{
public:
static constexpr JNINativeMethod methods[] = {
mozilla::jni::MakeNativeMethod<GeckoThread::SpeculativeConnect_t>(
mozilla::jni::NativeStub<GeckoThread::SpeculativeConnect_t, Impl>
::template Wrap<&Impl::SpeculativeConnect>)
};
};
template<class Impl>
constexpr JNINativeMethod GeckoThread::Natives<Impl>::methods[];
template<class Impl>
class NativeJSContainer::Natives : public mozilla::jni::NativeImpl<NativeJSContainer, Impl>
{

View File

@ -781,6 +781,9 @@ auto GeckoThread::SetState(mozilla::jni::Object::Param a0) -> void
return mozilla::jni::Method<SetState_t>::Call(nullptr, nullptr, a0);
}
constexpr char GeckoThread::SpeculativeConnect_t::name[];
constexpr char GeckoThread::SpeculativeConnect_t::signature[];
constexpr char GeckoThread::ClsLoader_t::name[];
constexpr char GeckoThread::ClsLoader_t::signature[];

View File

@ -1856,6 +1856,22 @@ public:
static auto SetState(mozilla::jni::Object::Param) -> void;
public:
struct SpeculativeConnect_t {
typedef GeckoThread Owner;
typedef void ReturnType;
typedef void SetterType;
typedef mozilla::jni::Args<
mozilla::jni::String::Param> Args;
static constexpr char name[] = "speculativeConnectNative";
static constexpr char signature[] =
"(Ljava/lang/String;)V";
static const bool isStatic = true;
static const bool isMultithreaded = false;
static const mozilla::jni::ExceptionMode exceptionMode =
mozilla::jni::ExceptionMode::ABORT;
};
public:
struct ClsLoader_t {
typedef GeckoThread Owner;
@ -1892,6 +1908,8 @@ public:
static auto MsgQueue(mozilla::jni::Object::Param) -> void;
public:
template<class Impl> class Natives;
};
class GeckoThread::State : public mozilla::jni::Class<State>

View File

@ -24,7 +24,10 @@
#include "nsIDOMWakeLockListener.h"
#include "nsIPowerManagerService.h"
#include "nsINetworkLinkService.h"
#include "nsISpeculativeConnect.h"
#include "nsIURIFixup.h"
#include "nsCategoryManagerUtils.h"
#include "nsCDefaultURIFixup.h"
#include "mozilla/HangMonitor.h"
#include "mozilla/Services.h"
@ -35,6 +38,7 @@
#include "AndroidBridge.h"
#include "AndroidBridgeUtilities.h"
#include "GeneratedJNINatives.h"
#include <android/log.h>
#include <pthread.h>
#include <wchar.h>
@ -128,6 +132,57 @@ NS_IMPL_ISUPPORTS(WakeLockListener, nsIDOMMozWakeLockListener)
nsCOMPtr<nsIPowerManagerService> sPowerManagerService = nullptr;
StaticRefPtr<WakeLockListener> sWakeLockListener;
namespace {
already_AddRefed<nsIURI>
ResolveURI(const nsCString& uriStr)
{
nsCOMPtr<nsIIOService> ioServ = do_GetIOService();
nsCOMPtr<nsIURI> uri;
if (NS_SUCCEEDED(ioServ->NewURI(uriStr, nullptr,
nullptr, getter_AddRefs(uri)))) {
return uri.forget();
}
nsCOMPtr<nsIURIFixup> fixup = do_GetService(NS_URIFIXUP_CONTRACTID);
if (fixup && NS_SUCCEEDED(
fixup->CreateFixupURI(uriStr, 0, nullptr, getter_AddRefs(uri)))) {
return uri.forget();
}
return nullptr;
}
} // namespace
class GeckoThreadNatives final
: public widget::GeckoThread::Natives<GeckoThreadNatives>
{
public:
static void SpeculativeConnect(jni::String::Param uriStr)
{
if (!NS_IsMainThread()) {
// We will be on the main thread if the call was queued on the Java
// side during startup. Otherwise, the call was not queued, which
// means Gecko is already sufficiently loaded, and we don't really
// care about speculative connections at this point.
return;
}
nsCOMPtr<nsIIOService> ioServ = do_GetIOService();
nsCOMPtr<nsISpeculativeConnect> specConn = do_QueryInterface(ioServ);
if (!specConn) {
return;
}
nsCOMPtr<nsIURI> uri = ResolveURI(nsCString(uriStr));
if (!uri) {
return;
}
specConn->SpeculativeConnect(uri, nullptr);
}
};
nsAppShell::nsAppShell()
: mQueueLock("nsAppShell.mQueueLock"),
mCondLock("nsAppShell.mCondLock"),
@ -143,6 +198,7 @@ nsAppShell::nsAppShell()
if (jni::IsAvailable()) {
// Initialize JNI and Set the corresponding state in GeckoThread.
AndroidBridge::ConstructBridge();
GeckoThreadNatives::Init();
mozilla::ANRReporter::Init();
widget::GeckoThread::SetState(widget::GeckoThread::State::JNI_READY());