/* 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/. */
nsresult CaptivePortalService::PerformCheck() {
LOG(
("CaptivePortalService::PerformCheck mRequestInProgress:%d " "mInitialized:%d mStarted:%d\n",
mRequestInProgress, mInitialized, mStarted)); // Don't issue another request if last one didn't complete if (mRequestInProgress || !mInitialized || !mStarted) { return NS_OK;
} if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) { return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
} // Instantiating CaptiveDetect.sys.mjs before the JS engine is ready will // lead to a crash (see bug 1800603) // We can remove this restriction when we rewrite the detector in // C++ or rust (bug 1809886). if (!XPCJSRuntime::Get()) { return NS_ERROR_NOT_INITIALIZED;
}
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
nsresult rv; if (!mCaptivePortalDetector) {
mCaptivePortalDetector =
do_CreateInstance("@mozilla.org/toolkit/captive-detector;1", &rv); if (NS_FAILED(rv)) {
LOG(("Unable to get a captive portal detector\n")); return rv;
}
}
nsresult CaptivePortalService::RearmTimer() {
LOG(("CaptivePortalService::RearmTimer\n")); // Start a timer to recheck
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); if (mTimer) {
mTimer->Cancel();
}
if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
mTimer = nullptr; return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
}
// If we have successfully determined the state, and we have never detected // a captive portal, we don't need to keep polling, but will rely on events // to trigger detection. if (mState == NOT_CAPTIVE) { return NS_OK;
}
if (!mTimer) {
mTimer = NS_NewTimer();
}
if (mTimer && mDelay > 0) {
LOG(("CaptivePortalService - Reloading timer with delay %u\n", mDelay)); return mTimer->InitWithCallback(this, mDelay, nsITimer::TYPE_ONE_SHOT);
}
// Only the main process service should actually do anything. The service in // the content process only mirrors the CP state in the main process. if (XRE_GetProcessType() != GeckoProcessType_Default) { return NS_OK;
}
// Clear the state in case anyone queries the state while detection is off.
mState = UNKNOWN; return NS_OK;
}
void CaptivePortalService::SetStateInChild(int32_t aState) { // This should only be called in the content process, from ContentChild.cpp // in order to mirror the captive portal state set in the chrome process.
MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default);
if (XRE_GetProcessType() != GeckoProcessType_Default) { // Doesn't do anything if called in the content process. return NS_OK;
}
// This is called for user activity. We need to reset the slack count, // so the checks continue to be quite frequent.
mSlackCount = 0;
mDelay = mMinInterval;
//----------------------------------------------------------------------------- // CaptivePortalService::nsITimer // This callback gets called every mDelay miliseconds // It issues a checkCaptivePortal operation if one isn't already in progress //-----------------------------------------------------------------------------
NS_IMETHODIMP
CaptivePortalService::Notify(nsITimer* aTimer) {
LOG(("CaptivePortalService::Notify\n"));
MOZ_ASSERT(aTimer == mTimer);
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
PerformCheck();
// This is needed because we don't want to always make requests very often. // Every 10 checks, we the delay is increased mBackoffFactor times // to a maximum delay of mMaxInterval
mSlackCount++; if (mSlackCount % 10 == 0) {
mDelay = mDelay * mBackoffFactor;
} if (mDelay > mMaxInterval) {
mDelay = mMaxInterval;
}
// Note - if mDelay is 0, the timer will not be rearmed.
RearmTimer();
//----------------------------------------------------------------------------- // CaptivePortalService::nsIObserver //-----------------------------------------------------------------------------
NS_IMETHODIMP
CaptivePortalService::Observe(nsISupports* aSubject, constchar* aTopic, const char16_t* aData) { if (XRE_GetProcessType() != GeckoProcessType_Default) { // Doesn't do anything if called in the content process. return NS_OK;
}
LOG(("CaptivePortalService::Observe() topic=%s\n", aTopic)); if (!strcmp(aTopic, kOpenCaptivePortalLoginEvent)) { // A redirect or altered content has been detected. // The user needs to log in. We are in a captive portal.
StateTransition(LOCKED_PORTAL);
mLastChecked = TimeStamp::Now();
mEverBeenCaptive = true;
} elseif (!strcmp(aTopic, kCaptivePortalLoginSuccessEvent)) { // The user has successfully logged in. We have connectivity.
StateTransition(UNLOCKED_PORTAL);
mLastChecked = TimeStamp::Now();
mSlackCount = 0;
mDelay = mMinInterval;
RearmTimer();
} elseif (!strcmp(aTopic, kAbortCaptivePortalLoginEvent)) { // The login has been aborted
StateTransition(UNKNOWN);
mLastChecked = TimeStamp::Now();
mSlackCount = 0;
} elseif (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
Stop(); return NS_OK;
}
// Send notification so that the captive portal state is mirrored in the // content process.
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService(); if (observerService) {
nsCOMPtr<nsICaptivePortalService> cps(this);
observerService->NotifyObservers(cps, NS_IPC_CAPTIVE_PORTAL_SET_STATE,
nullptr);
}
//----------------------------------------------------------------------------- // CaptivePortalService::nsICaptivePortalCallback //-----------------------------------------------------------------------------
NS_IMETHODIMP
CaptivePortalService::Prepare() {
LOG(("CaptivePortalService::Prepare\n"));
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) { return NS_OK;
} // XXX: Finish preparation shouldn't be called until dns and routing is // available. if (mCaptivePortalDetector) {
mCaptivePortalDetector->FinishPreparation(kInterfaceName);
} return NS_OK;
}
// Note: this callback gets called when: // 1. the request is completed, and content is valid (success == true) // 2. when the request is aborted or times out (success == false)
if (success) { if (mEverBeenCaptive) {
StateTransition(UNLOCKED_PORTAL);
NotifyConnectivityAvailable(true);
} else {
StateTransition(NOT_CAPTIVE);
NotifyConnectivityAvailable(false);
}
}
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.