/* -*- Mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
class GeckoThreadSupport final
: public java::GeckoThread::Natives<GeckoThreadSupport> { // When this number goes above 0, the app is paused. When less than or // equal to zero, the app is resumed. static int32_t sPauseCount;
public: staticvoid SpeculativeConnect(jni::String::Param aUriStr) { 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;
}
sPauseCount++; // If sPauseCount is now 1, we just crossed the threshold from "resumed" // "paused". so we should notify observers and so on. if (sPauseCount != 1) { return;
}
// We really want to send a notification like profile-before-change, // but profile-before-change ends up shutting some things down instead // of flushing data
Preferences* prefs = static_cast<Preferences*>(Preferences::GetService()); if (prefs) { // Force a main thread blocking save
prefs->SavePrefFileBlocking();
}
}
sPauseCount--; // If sPauseCount is now 0, we just crossed the threshold from "paused" // to "resumed", so we should notify observers and so on. if (sPauseCount != 0) { return;
}
// We didn't return from one of our own activities, so restore // to foreground status
nsCOMPtr<nsIObserverService> obsServ =
mozilla::services::GetObserverService();
obsServ->NotifyObservers(nullptr, "application-foreground", nullptr);
}
class GeckoAppShellSupport final
: public java::GeckoAppShell::Natives<GeckoAppShellSupport> { public: staticvoid ReportJavaCrash(const jni::Class::LocalRef& aCls,
jni::Throwable::Param aException,
jni::String::Param aStack) { if (!jni::ReportException(aCls.Env(), aException.Get(), aStack.Get())) { // Only crash below if crash reporter is initialized and annotation // succeeded. Otherwise try other means of reporting the crash in // Java. return;
}
switch (aType) { // Bug 938035, transfer HAL data for orientation sensor to meet w3c // spec, ex: HAL report alpha=90 means East but alpha=90 means West // in w3c spec case hal::SENSOR_ORIENTATION:
values.AppendElement(360.0f - aX);
values.AppendElement(-aY);
values.AppendElement(-aZ); break;
case hal::SENSOR_LINEAR_ACCELERATION: case hal::SENSOR_ACCELERATION: case hal::SENSOR_GYROSCOPE:
values.AppendElement(aX);
values.AppendElement(aY);
values.AppendElement(aZ); break;
case hal::SENSOR_LIGHT:
values.AppendElement(aX); break;
case hal::SENSOR_ROTATION_VECTOR: case hal::SENSOR_GAME_ROTATION_VECTOR:
values.AppendElement(aX);
values.AppendElement(aY);
values.AppendElement(aZ);
values.AppendElement(aW); break;
default:
__android_log_print(ANDROID_LOG_ERROR, "Gecko", "Unknown sensor type %d", aType);
}
if (PastShutdownPhase(ShutdownPhase::XPCOMShutdown)) { return;
}
nsBaseAppShell::OnSystemTimezoneChange();
}
};
class XPCOMEventTargetWrapper final
: public java::XPCOMEventTarget::Natives<XPCOMEventTargetWrapper> { public: // Wraps a java runnable into an XPCOM runnable and dispatches it to mTarget. void DispatchNative(mozilla::jni::Object::Param aJavaRunnable) { if (AppShutdown::GetCurrentShutdownPhase() >=
ShutdownPhase::XPCOMShutdownThreads) { // No point in trying to dispatch this if we're already shutting down. return;
}
java::XPCOMEventTarget::JNIRunnable::GlobalRef r =
java::XPCOMEventTarget::JNIRunnable::Ref::From(aJavaRunnable);
mTarget->Dispatch(NS_NewRunnableFunction( "XPCOMEventTargetWrapper::DispatchNative",
[runnable = std::move(r)]() { runnable->Run(); }));
}
if (!XRE_IsParentProcess()) { if (jni::IsAvailable()) {
GeckoThreadSupport::Init();
GeckoAppShellSupport::Init();
XPCOMEventTargetWrapper::Init();
mozilla::widget::Telemetry::Init();
if (XRE_IsGPUProcess()) {
mozilla::gl::AndroidSurfaceTexture::Init();
}
// Set the corresponding state in GeckoThread.
java::GeckoThread::SetState(java::GeckoThread::State::RUNNING());
} return;
}
if (jni::IsAvailable()) {
ScreenManager& screenManager = ScreenManager::GetSingleton();
screenManager.SetHelper(mozilla::MakeUnique<ScreenHelperAndroid>());
// Initialize JNI and Set the corresponding state in GeckoThread.
AndroidBridge::ConstructBridge();
GeckoAppShellSupport::Init();
GeckoThreadSupport::Init();
XPCOMEventTargetWrapper::Init();
mozilla::GeckoBatteryManager::Init();
mozilla::GeckoNetworkManager::Init();
mozilla::GeckoProcessManager::Init();
mozilla::GeckoSystemStateListener::Init();
mozilla::widget::Telemetry::Init();
mozilla::widget::ImageDecoderSupport::Init();
mozilla::widget::WebExecutorSupport::Init();
mozilla::widget::Base64UtilsSupport::Init();
nsWindow::InitNatives();
mozilla::gl::AndroidSurfaceTexture::Init();
if (sPowerManagerService) {
sWakeLockListener = new WakeLockListener();
} else {
NS_WARNING( "Failed to retrieve PowerManagerService, wakelocks will be broken!");
}
}
nsAppShell::~nsAppShell() {
{ // Release any thread waiting for a sync call to finish.
MutexAutoLock lock(*sAppShellLock);
sAppShell = nullptr;
mSyncRunFinished.NotifyAll();
}
while (mEventQueue.Pop(/* mayWait */ false)) {
NS_WARNING("Discarded event on shutdown");
}
if (sPowerManagerService) {
sPowerManagerService->RemoveWakeLockListener(sWakeLockListener);
if (sPowerManagerService)
sPowerManagerService->AddWakeLockListener(sWakeLockListener);
return rv;
}
NS_IMETHODIMP
nsAppShell::Exit(void) {
{ // Release any thread waiting for a sync call to finish.
mozilla::MutexAutoLock shellLock(*sAppShellLock);
mSyncRunQuit = true;
mSyncRunFinished.NotifyAll();
} // We need to ensure no observers stick around after XPCOM shuts down // or we'll see crashes, as the app shell outlives XPConnect.
mObserversHash.Clear(); return nsBaseAppShell::Exit();
}
if (!strcmp(aTopic, "browser-delayed-startup-finished")) {
NS_CreateServicesFromCategory("browser-delayed-startup-finished", nullptr, "browser-delayed-startup-finished");
} elseif (!strcmp(aTopic, "geckoview-startup-complete")) { if (jni::IsAvailable()) {
java::GeckoThread::CheckAndSetState(
java::GeckoThread::State::PROFILE_READY(),
java::GeckoThread::State::RUNNING());
}
} elseif (!strcmp(aTopic, "profile-after-change")) { if (jni::IsAvailable()) {
java::GeckoThread::SetState(java::GeckoThread::State::PROFILE_READY());
// Gecko on Android follows the Android app model where it never // stops until it is killed by the system or told explicitly to // quit. Therefore, we should *not* exit Gecko when there is no // window or the last window is closed. nsIAppStartup::Quit will // still force Gecko to exit.
nsCOMPtr<nsIAppStartup> appStartup = components::AppStartup::Service(); if (appStartup) {
appStartup->EnterLastWindowClosingSurvivalArea();
}
}
removeObserver = true;
} elseif (!strcmp(aTopic, "chrome-document-loaded")) { // Set the global ready state and enable the window event dispatcher // for this particular GeckoView.
nsCOMPtr<dom::Document> doc = do_QueryInterface(aSubject);
MOZ_ASSERT(doc); if (const RefPtr<nsWindow> window = nsWindow::From(doc->GetWindow())) {
window->OnGeckoViewReady();
}
} elseif (!strcmp(aTopic, "quit-application")) { if (jni::IsAvailable()) { constbool restarting = aData && u"restart"_ns.Equals(aData);
java::GeckoThread::SetState(restarting
? java::GeckoThread::State::RESTARTING()
: java::GeckoThread::State::EXITING());
}
removeObserver = true;
} elseif (!strcmp(aTopic, "quit-application-granted")) { if (jni::IsAvailable()) { // We are told explicitly to quit, perhaps due to // nsIAppStartup::Quit being called. We should release our hold on // nsIAppStartup and let it continue to quit.
nsCOMPtr<nsIAppStartup> appStartup = components::AppStartup::Service(); if (appStartup) {
appStartup->ExitLastWindowClosingSurvivalArea();
}
}
removeObserver = true;
} elseif (!strcmp(aTopic, "content-document-global-created")) { // Associate the PuppetWidget of the newly-created BrowserChild with a // GeckoEditableChild instance.
MOZ_ASSERT(!XRE_IsParentProcess());
if (!curEvent && mayWait) { // This processes messages in the Android Looper. Note that we only // get here if the normal Gecko event loop has been awoken // (bug 750713). Looper messages effectively have the lowest // priority because we only process them before we're about to // wait for new events. if (jni::IsAvailable() && XRE_IsParentProcess() &&
AndroidBridge::Bridge()->PumpMessageLoop()) { returntrue;
}
bool nsAppShell::SyncRunEvent(
Event&& event, UniquePtr<Event> (*eventFactory)(UniquePtr<Event>&&), const TimeDuration timeout) { // Perform the call on the Gecko thread in a separate lambda, and wait // on the monitor on the current thread.
MOZ_ASSERT(!NS_IsMainThread());
// This is the lock to check that app shell is still alive, // and to wait on for the sync call to complete.
mozilla::MutexAutoLock shellLock(*sAppShellLock);
nsAppShell* const appShell = sAppShell;
if (MOZ_UNLIKELY(!appShell)) { // Post-shutdown. returnfalse;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.