зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 876ba605d62c (bug 939318) for XPCTest Failures
This commit is contained in:
Родитель
43f8d5802d
Коммит
8d84d4beb8
|
@ -10,7 +10,7 @@
|
|||
/**
|
||||
* Network link status monitoring service.
|
||||
*/
|
||||
[scriptable, uuid(a8770c10-2f54-11e4-8c21-0800200c9a66)]
|
||||
[scriptable, uuid(f7d3be87-7403-4a1e-b89f-2797776e9b08)]
|
||||
interface nsINetworkLinkService : nsISupports
|
||||
{
|
||||
/* Link type constants */
|
||||
|
@ -64,11 +64,6 @@ interface nsINetworkLinkService : nsISupports
|
|||
* isLinkUp is now false, linkStatusKnown is true.
|
||||
*/
|
||||
#define NS_NETWORK_LINK_DATA_DOWN "down"
|
||||
/**
|
||||
* isLinkUp is still true, but the network setup is modified.
|
||||
* linkStatusKnown is true.
|
||||
*/
|
||||
#define NS_NETWORK_LINK_DATA_CHANGED "changed"
|
||||
/**
|
||||
* linkStatusKnown is now false.
|
||||
*/
|
||||
|
|
|
@ -60,8 +60,8 @@ using namespace mozilla;
|
|||
nsIOService* gIOService = nullptr;
|
||||
static bool gHasWarnedUploadChannel2;
|
||||
|
||||
// A general port blacklist. Connections to these ports will not be allowed
|
||||
// unless the protocol overrides.
|
||||
// A general port blacklist. Connections to these ports will not be allowed unless
|
||||
// the protocol overrides.
|
||||
//
|
||||
// TODO: I am sure that there are more ports to be added.
|
||||
// This cut is based on the classic mozilla codebase
|
||||
|
@ -265,9 +265,10 @@ nsIOService::InitializeNetworkLinkService()
|
|||
// so let's cross our fingers!
|
||||
mManageOfflineStatus = false;
|
||||
}
|
||||
|
||||
|
||||
if (mManageOfflineStatus)
|
||||
OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN);
|
||||
TrackNetworkLinkStatusForOffline();
|
||||
else
|
||||
SetOffline(false);
|
||||
|
||||
|
@ -921,7 +922,7 @@ nsIOService::Observe(nsISupports *subject,
|
|||
if (mOfflineForProfileChange) {
|
||||
mOfflineForProfileChange = false;
|
||||
if (!mManageOfflineStatus ||
|
||||
NS_FAILED(OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN))) {
|
||||
NS_FAILED(TrackNetworkLinkStatusForOffline())) {
|
||||
SetOffline(false);
|
||||
}
|
||||
}
|
||||
|
@ -951,11 +952,11 @@ nsIOService::Observe(nsISupports *subject,
|
|||
mProxyService = nullptr;
|
||||
}
|
||||
else if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
|
||||
if (!mOfflineForProfileChange) {
|
||||
OnNetworkLinkEvent(NS_ConvertUTF16toUTF8(data).get());
|
||||
if (!mOfflineForProfileChange && mManageOfflineStatus) {
|
||||
TrackNetworkLinkStatusForOffline();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1053,25 +1054,24 @@ nsIOService::NewSimpleNestedURI(nsIURI* aURI, nsIURI** aResult)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIOService::SetManageOfflineStatus(bool aManage)
|
||||
{
|
||||
nsIOService::SetManageOfflineStatus(bool aManage) {
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// SetManageOfflineStatus must throw when we fail to go from non-managed
|
||||
// to managed. Usually because there is no link monitoring service
|
||||
// available. Failure to do this switch is detected by a failure of
|
||||
// OnNetworkLinkEvent(). When there is no network link available during
|
||||
// call to InitializeNetworkLinkService(), application is put to offline
|
||||
// mode. And when we change mMangeOfflineStatus to false on the next line
|
||||
// we get stuck on being offline even though the link becomes later
|
||||
// available.
|
||||
// to managed. Usually because there is no link monitoring service
|
||||
// available. Failure to do this switch is detected by a failure of
|
||||
// TrackNetworkLinkStatusForOffline(). When there is no network link
|
||||
// available during call to InitializeNetworkLinkService(), application is
|
||||
// put to offline mode. And when we change mMangeOfflineStatus to false
|
||||
// on the next line we get stuck on being offline even though the link
|
||||
// becomes later available.
|
||||
bool wasManaged = mManageOfflineStatus;
|
||||
mManageOfflineStatus = aManage;
|
||||
|
||||
InitializeNetworkLinkService();
|
||||
|
||||
if (mManageOfflineStatus && !wasManaged) {
|
||||
rv = OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN);
|
||||
rv = TrackNetworkLinkStatusForOffline();
|
||||
if (NS_FAILED(rv))
|
||||
mManageOfflineStatus = false;
|
||||
}
|
||||
|
@ -1084,57 +1084,41 @@ nsIOService::GetManageOfflineStatus(bool* aManage) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// input argument 'data' is already UTF8'ed
|
||||
nsresult
|
||||
nsIOService::OnNetworkLinkEvent(const char *data)
|
||||
nsIOService::TrackNetworkLinkStatusForOffline()
|
||||
{
|
||||
NS_ASSERTION(mManageOfflineStatus,
|
||||
"Don't call this unless we're managing the offline status");
|
||||
if (!mNetworkLinkService)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mShutdown)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
if (mManageOfflineStatus)
|
||||
return NS_OK;
|
||||
|
||||
if (!strcmp(data, NS_NETWORK_LINK_DATA_DOWN)) {
|
||||
// check to make sure this won't collide with Autodial
|
||||
if (mSocketTransportService) {
|
||||
bool autodialEnabled = false;
|
||||
mSocketTransportService->GetAutodialEnabled(&autodialEnabled);
|
||||
// If autodialing-on-link-down is enabled, check if the OS auto
|
||||
// dial option is set to always autodial. If so, then we are
|
||||
// always up for the purposes of offline management.
|
||||
if (autodialEnabled) {
|
||||
|
||||
// check to make sure this won't collide with Autodial
|
||||
if (mSocketTransportService) {
|
||||
bool autodialEnabled = false;
|
||||
mSocketTransportService->GetAutodialEnabled(&autodialEnabled);
|
||||
// If autodialing-on-link-down is enabled, check if the OS auto dial
|
||||
// option is set to always autodial. If so, then we are
|
||||
// always up for the purposes of offline management.
|
||||
if (autodialEnabled) {
|
||||
#if defined(XP_WIN)
|
||||
// On Windows, we should first check with the OS to see if
|
||||
// autodial is enabled. If it is enabled then we are allowed
|
||||
// to manage the offline state.
|
||||
if (nsNativeConnectionHelper::IsAutodialEnabled()) {
|
||||
return SetOffline(false);
|
||||
}
|
||||
#else
|
||||
// On Windows, we should first check with the OS
|
||||
// to see if autodial is enabled. If it is
|
||||
// enabled then we are allowed to manage the
|
||||
// offline state.
|
||||
if(nsNativeConnectionHelper::IsAutodialEnabled())
|
||||
return SetOffline(false);
|
||||
#else
|
||||
return SetOffline(false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isUp;
|
||||
if (!strcmp(data, NS_NETWORK_LINK_DATA_DOWN)) {
|
||||
isUp = false;
|
||||
} else if (!strcmp(data, NS_NETWORK_LINK_DATA_UP)) {
|
||||
isUp = true;
|
||||
} else if (!strcmp(data, NS_NETWORK_LINK_DATA_CHANGED)) {
|
||||
// CHANGED events are handled by others
|
||||
return NS_OK;
|
||||
} else if (!strcmp(data, NS_NETWORK_LINK_DATA_UNKNOWN)) {
|
||||
nsresult rv = mNetworkLinkService->GetIsLinkUp(&isUp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
NS_WARNING("Unhandled network event!");
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult rv = mNetworkLinkService->GetIsLinkUp(&isUp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return SetOffline(!isUp);
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ private:
|
|||
nsIOService();
|
||||
~nsIOService();
|
||||
|
||||
nsresult OnNetworkLinkEvent(const char *data);
|
||||
nsresult TrackNetworkLinkStatusForOffline();
|
||||
|
||||
nsresult GetCachedProtocolHandler(const char *scheme,
|
||||
nsIProtocolHandler* *hdlrResult,
|
||||
|
|
|
@ -30,15 +30,12 @@
|
|||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsNetAddr.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsINetworkLinkService.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/VisualEventTracer.h"
|
||||
#include "mozilla/net/NeckoCommon.h"
|
||||
#include "mozilla/net/ChildDNSService.h"
|
||||
#include "mozilla/net/DNSListenerProxy.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::net;
|
||||
|
@ -543,13 +540,12 @@ nsDNSService::Init()
|
|||
prefs->AddObserver("network.proxy.type", this, false);
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
observerService->AddObserver(this, "last-pb-context-exited", false);
|
||||
observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nsDNSPrefetch::Initialize(this);
|
||||
|
@ -874,21 +870,10 @@ nsDNSService::GetMyHostName(nsACString &result)
|
|||
NS_IMETHODIMP
|
||||
nsDNSService::Observe(nsISupports *subject, const char *topic, const char16_t *data)
|
||||
{
|
||||
// We are only getting called if a preference has changed or there's a
|
||||
// network link event.
|
||||
// we are only getting called if a preference has changed.
|
||||
NS_ASSERTION(strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0 ||
|
||||
strcmp(topic, "last-pb-context-exited") == 0 ||
|
||||
strcmp(topic, NS_NETWORK_LINK_TOPIC) == 0,
|
||||
"unexpected observe call");
|
||||
|
||||
if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
|
||||
nsCString converted = NS_ConvertUTF16toUTF8(data);
|
||||
const char *state = converted.get();
|
||||
if (!strcmp(state, NS_NETWORK_LINK_DATA_CHANGED)) {
|
||||
mResolver->FlushCache();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
strcmp(topic, "last-pb-context-exited") == 0,
|
||||
"unexpected observe call");
|
||||
|
||||
//
|
||||
// Shutdown and this function are both only called on the UI thread, so we don't
|
||||
|
|
|
@ -478,8 +478,10 @@ nsHostResolver::ClearPendingQueue(PRCList *aPendingQ)
|
|||
}
|
||||
|
||||
void
|
||||
nsHostResolver::FlushCache()
|
||||
nsHostResolver::Shutdown()
|
||||
{
|
||||
LOG(("Shutting down host resolver.\n"));
|
||||
|
||||
PRCList pendingQHigh, pendingQMed, pendingQLow, evictionQ;
|
||||
PR_INIT_CLIST(&pendingQHigh);
|
||||
PR_INIT_CLIST(&pendingQMed);
|
||||
|
@ -488,20 +490,23 @@ nsHostResolver::FlushCache()
|
|||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
mShutdown = true;
|
||||
|
||||
MoveCList(mHighQ, pendingQHigh);
|
||||
MoveCList(mMediumQ, pendingQMed);
|
||||
MoveCList(mLowQ, pendingQLow);
|
||||
MoveCList(mEvictionQ, evictionQ);
|
||||
mEvictionQSize = 0;
|
||||
mPendingCount = 0;
|
||||
|
||||
|
||||
if (mNumIdleThreads)
|
||||
mIdleThreadCV.NotifyAll();
|
||||
|
||||
|
||||
// empty host database
|
||||
PL_DHashTableEnumerate(&mDB, HostDB_RemoveEntry, nullptr);
|
||||
}
|
||||
|
||||
|
||||
ClearPendingQueue(&pendingQHigh);
|
||||
ClearPendingQueue(&pendingQMed);
|
||||
ClearPendingQueue(&pendingQLow);
|
||||
|
@ -514,18 +519,6 @@ nsHostResolver::FlushCache()
|
|||
NS_RELEASE(rec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHostResolver::Shutdown()
|
||||
{
|
||||
LOG(("Shutting down host resolver.\n"));
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mShutdown = true;
|
||||
}
|
||||
FlushCache();
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
|
||||
|
|
|
@ -238,11 +238,6 @@ public:
|
|||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
||||
/**
|
||||
* Flush the DNS cache.
|
||||
*/
|
||||
void FlushCache();
|
||||
|
||||
private:
|
||||
explicit nsHostResolver(uint32_t maxCacheEntries = 50, uint32_t maxCacheLifetime = 60,
|
||||
uint32_t lifetimeGracePeriod = 0);
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include "SpdyZlibReporter.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIParentalControlsService.h"
|
||||
#include "nsINetworkLinkService.h"
|
||||
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
@ -348,7 +347,6 @@ nsHttpHandler::Init()
|
|||
mObserverService->AddObserver(this, "net:failed-to-process-uri-content", true);
|
||||
mObserverService->AddObserver(this, "last-pb-context-exited", true);
|
||||
mObserverService->AddObserver(this, "browser:purge-session-history", true);
|
||||
mObserverService->AddObserver(this, NS_NETWORK_LINK_TOPIC, false);
|
||||
}
|
||||
|
||||
MakeNewRequestTokenBucket();
|
||||
|
@ -1779,8 +1777,9 @@ nsHttpHandler::Observe(nsISupports *subject,
|
|||
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
|
||||
if (prefBranch)
|
||||
PrefsChanged(prefBranch, NS_ConvertUTF16toUTF8(data).get());
|
||||
} else if (strcmp(topic, "profile-change-net-teardown") == 0 ||
|
||||
strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
||||
}
|
||||
else if (strcmp(topic, "profile-change-net-teardown") == 0 ||
|
||||
strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
||||
|
||||
mHandlerActive = false;
|
||||
|
||||
|
@ -1800,25 +1799,30 @@ nsHttpHandler::Observe(nsISupports *subject,
|
|||
|
||||
if (!mDoNotTrackEnabled) {
|
||||
Telemetry::Accumulate(Telemetry::DNT_USAGE, DONOTTRACK_VALUE_UNSET);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Telemetry::Accumulate(Telemetry::DNT_USAGE, mDoNotTrackValue);
|
||||
}
|
||||
} else if (strcmp(topic, "profile-change-net-restore") == 0) {
|
||||
}
|
||||
else if (strcmp(topic, "profile-change-net-restore") == 0) {
|
||||
// initialize connection manager
|
||||
InitConnectionMgr();
|
||||
} else if (strcmp(topic, "net:clear-active-logins") == 0) {
|
||||
}
|
||||
else if (strcmp(topic, "net:clear-active-logins") == 0) {
|
||||
mAuthCache.ClearAll();
|
||||
mPrivateAuthCache.ClearAll();
|
||||
} else if (strcmp(topic, "net:prune-dead-connections") == 0) {
|
||||
}
|
||||
else if (strcmp(topic, "net:prune-dead-connections") == 0) {
|
||||
if (mConnMgr) {
|
||||
mConnMgr->PruneDeadConnections();
|
||||
}
|
||||
} else if (strcmp(topic, "net:failed-to-process-uri-content") == 0) {
|
||||
}
|
||||
else if (strcmp(topic, "net:failed-to-process-uri-content") == 0) {
|
||||
nsCOMPtr<nsIURI> uri = do_QueryInterface(subject);
|
||||
if (uri && mConnMgr) {
|
||||
if (uri && mConnMgr)
|
||||
mConnMgr->ReportFailedToProcess(uri);
|
||||
}
|
||||
} else if (strcmp(topic, "last-pb-context-exited") == 0) {
|
||||
}
|
||||
else if (strcmp(topic, "last-pb-context-exited") == 0) {
|
||||
mPrivateAuthCache.ClearAll();
|
||||
} else if (strcmp(topic, "browser:purge-session-history") == 0) {
|
||||
if (mConnMgr && gSocketTransportService) {
|
||||
|
@ -1826,14 +1830,6 @@ nsHttpHandler::Observe(nsISupports *subject,
|
|||
&nsHttpConnectionMgr::ClearConnectionHistory);
|
||||
gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
} else if (strcmp(topic, NS_NETWORK_LINK_TOPIC) == 0) {
|
||||
nsCString converted = NS_ConvertUTF16toUTF8(data);
|
||||
const char *state = converted.get();
|
||||
if (strcmp(state, NS_NETWORK_LINK_DATA_CHANGED) == 0) {
|
||||
if (mConnMgr) {
|
||||
mConnMgr->PruneDeadConnections();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -12,11 +12,6 @@
|
|||
#include <ole2.h>
|
||||
#include <netcon.h>
|
||||
#include <objbase.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2ipdef.h>
|
||||
#include <tcpmib.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <netioapi.h>
|
||||
#include <iprtrmib.h>
|
||||
#include "plstr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
@ -34,26 +29,6 @@
|
|||
static HMODULE sNetshell;
|
||||
static decltype(NcFreeNetconProperties)* sNcFreeNetconProperties;
|
||||
|
||||
static HMODULE sIphlpapi;
|
||||
static decltype(NotifyIpInterfaceChange)* sNotifyIpInterfaceChange;
|
||||
static decltype(CancelMibChangeNotify2)* sCancelMibChangeNotify2;
|
||||
|
||||
static void InitIphlpapi(void)
|
||||
{
|
||||
if (!sIphlpapi) {
|
||||
sIphlpapi = LoadLibraryW(L"Iphlpapi.dll");
|
||||
if (sIphlpapi) {
|
||||
sNotifyIpInterfaceChange = (decltype(NotifyIpInterfaceChange)*)
|
||||
GetProcAddress(sIphlpapi, "NotifyIpInterfaceChange");
|
||||
sCancelMibChangeNotify2 = (decltype(CancelMibChangeNotify2)*)
|
||||
GetProcAddress(sIphlpapi, "CancelMibChangeNotify2");
|
||||
} else {
|
||||
NS_WARNING("Failed to load Iphlpapi.dll - cannot detect network"
|
||||
" changes!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void InitNetshellLibrary(void)
|
||||
{
|
||||
if (!sNetshell) {
|
||||
|
@ -72,12 +47,6 @@ static void FreeDynamicLibraries(void)
|
|||
FreeLibrary(sNetshell);
|
||||
sNetshell = nullptr;
|
||||
}
|
||||
if (sIphlpapi) {
|
||||
sNotifyIpInterfaceChange = nullptr;
|
||||
sCancelMibChangeNotify2 = nullptr;
|
||||
FreeLibrary(sIphlpapi);
|
||||
sIphlpapi = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsNotifyAddrListener,
|
||||
|
@ -91,7 +60,6 @@ nsNotifyAddrListener::nsNotifyAddrListener()
|
|||
, mCheckAttempted(false)
|
||||
, mShutdownEvent(nullptr)
|
||||
{
|
||||
InitIphlpapi();
|
||||
}
|
||||
|
||||
nsNotifyAddrListener::~nsNotifyAddrListener()
|
||||
|
@ -129,62 +97,36 @@ nsNotifyAddrListener::GetLinkType(uint32_t *aLinkType)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Static Callback function for NotifyIpInterfaceChange API.
|
||||
static void WINAPI OnInterfaceChange(PVOID callerContext,
|
||||
PMIB_IPINTERFACE_ROW row,
|
||||
MIB_NOTIFICATION_TYPE notificationType)
|
||||
{
|
||||
nsNotifyAddrListener *notify = static_cast<nsNotifyAddrListener*>(callerContext);
|
||||
notify->CheckLinkStatus();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNotifyAddrListener::Run()
|
||||
{
|
||||
PR_SetCurrentThreadName("Link Monitor");
|
||||
if (!sNotifyIpInterfaceChange || !sCancelMibChangeNotify2) {
|
||||
// For Windows versions which are older than Vista which lack
|
||||
// NotifyIpInterfaceChange. Note this means no IPv6 support.
|
||||
HANDLE ev = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
NS_ENSURE_TRUE(ev, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
HANDLE handles[2] = { ev, mShutdownEvent };
|
||||
OVERLAPPED overlapped = { 0 };
|
||||
bool shuttingDown = false;
|
||||
HANDLE ev = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
NS_ENSURE_TRUE(ev, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
overlapped.hEvent = ev;
|
||||
while (!shuttingDown) {
|
||||
HANDLE h;
|
||||
DWORD ret = NotifyAddrChange(&h, &overlapped);
|
||||
HANDLE handles[2] = { ev, mShutdownEvent };
|
||||
OVERLAPPED overlapped = { 0 };
|
||||
bool shuttingDown = false;
|
||||
|
||||
if (ret == ERROR_IO_PENDING) {
|
||||
ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
|
||||
if (ret == WAIT_OBJECT_0) {
|
||||
CheckLinkStatus();
|
||||
} else {
|
||||
shuttingDown = true;
|
||||
}
|
||||
overlapped.hEvent = ev;
|
||||
while (!shuttingDown) {
|
||||
HANDLE h;
|
||||
DWORD ret = NotifyAddrChange(&h, &overlapped);
|
||||
|
||||
if (ret == ERROR_IO_PENDING) {
|
||||
ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
|
||||
if (ret == WAIT_OBJECT_0) {
|
||||
CheckLinkStatus();
|
||||
} else {
|
||||
shuttingDown = true;
|
||||
}
|
||||
} else {
|
||||
shuttingDown = true;
|
||||
}
|
||||
CloseHandle(ev);
|
||||
} else {
|
||||
// Windows Vista and newer versions.
|
||||
HANDLE interfacechange;
|
||||
// The callback will simply invoke CheckLinkStatus()
|
||||
DWORD ret = sNotifyIpInterfaceChange(
|
||||
AF_UNSPEC, // IPv4 and IPv6
|
||||
(PIPINTERFACE_CHANGE_CALLBACK)OnInterfaceChange,
|
||||
this, // pass to callback
|
||||
false, // no initial notification
|
||||
&interfacechange);
|
||||
|
||||
if (ret == NO_ERROR) {
|
||||
ret = WaitForSingleObject(mShutdownEvent, INFINITE);
|
||||
}
|
||||
sCancelMibChangeNotify2(interfacechange);
|
||||
}
|
||||
CloseHandle(ev);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -247,11 +189,11 @@ nsNotifyAddrListener::Shutdown(void)
|
|||
return rv;
|
||||
}
|
||||
|
||||
/* Sends the given event. Assumes aEventID never goes out of scope (static
|
||||
* strings are ideal).
|
||||
/* Sends the given event to the UI thread. Assumes aEventID never goes out
|
||||
* of scope (static strings are ideal).
|
||||
*/
|
||||
nsresult
|
||||
nsNotifyAddrListener::SendEvent(const char *aEventID)
|
||||
nsNotifyAddrListener::SendEventToUI(const char *aEventID)
|
||||
{
|
||||
if (!aEventID)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
@ -275,12 +217,8 @@ nsNotifyAddrListener::ChangeEvent::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// Bug 465158 features an explanation for this check. ICS being "Internet
|
||||
// Connection Sharing). The description says it is always IP address
|
||||
// 192.168.0.1 for this case.
|
||||
bool
|
||||
nsNotifyAddrListener::CheckICSGateway(PIP_ADAPTER_ADDRESSES aAdapter)
|
||||
nsNotifyAddrListener::CheckIsGateway(PIP_ADAPTER_ADDRESSES aAdapter)
|
||||
{
|
||||
if (!aAdapter->FirstUnicastAddress)
|
||||
return false;
|
||||
|
@ -382,70 +320,38 @@ nsNotifyAddrListener::CheckAdaptersAddresses(void)
|
|||
{
|
||||
ULONG len = 16384;
|
||||
|
||||
PIP_ADAPTER_ADDRESSES adapterList = (PIP_ADAPTER_ADDRESSES) moz_xmalloc(len);
|
||||
PIP_ADAPTER_ADDRESSES addresses = (PIP_ADAPTER_ADDRESSES) malloc(len);
|
||||
if (!addresses)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
ULONG flags = GAA_FLAG_SKIP_DNS_SERVER|GAA_FLAG_SKIP_MULTICAST|
|
||||
GAA_FLAG_SKIP_ANYCAST;
|
||||
|
||||
DWORD ret = GetAdaptersAddresses(AF_UNSPEC, flags, nullptr, adapterList, &len);
|
||||
DWORD ret = GetAdaptersAddresses(AF_UNSPEC, 0, nullptr, addresses, &len);
|
||||
if (ret == ERROR_BUFFER_OVERFLOW) {
|
||||
free(adapterList);
|
||||
adapterList = static_cast<PIP_ADAPTER_ADDRESSES> (moz_xmalloc(len));
|
||||
|
||||
ret = GetAdaptersAddresses(AF_UNSPEC, flags, nullptr, adapterList, &len);
|
||||
free(addresses);
|
||||
addresses = (PIP_ADAPTER_ADDRESSES) malloc(len);
|
||||
if (!addresses)
|
||||
return ERROR_BUFFER_OVERFLOW;
|
||||
ret = GetAdaptersAddresses(AF_UNSPEC, 0, nullptr, addresses, &len);
|
||||
}
|
||||
|
||||
if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))) {
|
||||
free(adapterList);
|
||||
free(addresses);
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Since NotifyIpInterfaceChange() signals a change more often than we
|
||||
// think is a worthy change, we checksum the entire state of all interfaces
|
||||
// that are UP. If the checksum is the same as previous check, nothing
|
||||
// of interest changed!
|
||||
//
|
||||
ULONG sum = 0;
|
||||
|
||||
if (ret == ERROR_SUCCESS) {
|
||||
PIP_ADAPTER_ADDRESSES ptr;
|
||||
bool linkUp = false;
|
||||
|
||||
for (PIP_ADAPTER_ADDRESSES adapter = adapterList; adapter;
|
||||
adapter = adapter->Next) {
|
||||
if (adapter->OperStatus != IfOperStatusUp ||
|
||||
!adapter->FirstUnicastAddress ||
|
||||
adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK ||
|
||||
CheckICSGateway(adapter) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add chars from AdapterName to the checksum.
|
||||
for (int i = 0; adapter->AdapterName[i]; ++i) {
|
||||
sum <<= 2;
|
||||
sum += adapter->AdapterName[i];
|
||||
}
|
||||
|
||||
// Add bytes from each socket address to the checksum.
|
||||
for (PIP_ADAPTER_UNICAST_ADDRESS pip = adapter->FirstUnicastAddress;
|
||||
pip; pip = pip->Next) {
|
||||
SOCKET_ADDRESS *sockAddr = &pip->Address;
|
||||
for (int i = 0; i < sockAddr->iSockaddrLength; ++i) {
|
||||
sum += (reinterpret_cast<unsigned char *>
|
||||
(sockAddr->lpSockaddr))[i];
|
||||
}
|
||||
}
|
||||
linkUp = true;
|
||||
for (ptr = addresses; !linkUp && ptr; ptr = ptr->Next) {
|
||||
if (ptr->OperStatus == IfOperStatusUp &&
|
||||
ptr->IfType != IF_TYPE_SOFTWARE_LOOPBACK &&
|
||||
!CheckIsGateway(ptr))
|
||||
linkUp = true;
|
||||
}
|
||||
mLinkUp = linkUp;
|
||||
mStatusKnown = true;
|
||||
}
|
||||
free(adapterList);
|
||||
|
||||
if (mLinkUp) {
|
||||
/* Store the checksum only if one or more interfaces are up */
|
||||
mIPInterfaceChecksum = sum;
|
||||
}
|
||||
free(addresses);
|
||||
|
||||
CoUninitialize();
|
||||
|
||||
|
@ -462,45 +368,24 @@ nsNotifyAddrListener::CheckLinkStatus(void)
|
|||
{
|
||||
DWORD ret;
|
||||
const char *event;
|
||||
bool prevLinkUp = mLinkUp;
|
||||
ULONG prevCsum = mIPInterfaceChecksum;
|
||||
|
||||
// The CheckAdaptersAddresses call is very expensive (~650 milliseconds),
|
||||
// so we don't want to call it synchronously. Instead, we just start up
|
||||
// assuming we have a network link, but we'll report that the status is
|
||||
// unknown.
|
||||
// This call is very expensive (~650 milliseconds), so we don't want to
|
||||
// call it synchronously. Instead, we just start up assuming we have a
|
||||
// network link, but we'll report that the status is unknown.
|
||||
if (NS_IsMainThread()) {
|
||||
NS_WARNING("CheckLinkStatus called on main thread! No check "
|
||||
"performed. Assuming link is up, status is unknown.");
|
||||
mLinkUp = true;
|
||||
|
||||
if (!mStatusKnown) {
|
||||
event = NS_NETWORK_LINK_DATA_UNKNOWN;
|
||||
} else if (!prevLinkUp) {
|
||||
event = NS_NETWORK_LINK_DATA_UP;
|
||||
} else {
|
||||
// Known status and it was already UP
|
||||
event = nullptr;
|
||||
}
|
||||
|
||||
if (event) {
|
||||
SendEvent(event);
|
||||
}
|
||||
} else {
|
||||
ret = CheckAdaptersAddresses();
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
mLinkUp = true;
|
||||
}
|
||||
|
||||
if (mLinkUp && (prevCsum != mIPInterfaceChecksum)) {
|
||||
// Network is online. Topology has changed. Always send CHANGED
|
||||
// before UP.
|
||||
SendEvent(NS_NETWORK_LINK_DATA_CHANGED);
|
||||
}
|
||||
if (prevLinkUp != mLinkUp) {
|
||||
// UP/DOWN status changed, send appropriate UP/DOWN event
|
||||
SendEvent(mLinkUp ?
|
||||
NS_NETWORK_LINK_DATA_UP : NS_NETWORK_LINK_DATA_DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
if (mStatusKnown)
|
||||
event = mLinkUp ? NS_NETWORK_LINK_DATA_UP : NS_NETWORK_LINK_DATA_DOWN;
|
||||
else
|
||||
event = NS_NETWORK_LINK_DATA_UNKNOWN;
|
||||
SendEventToUI(event);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ public:
|
|||
nsNotifyAddrListener();
|
||||
|
||||
nsresult Init(void);
|
||||
void CheckLinkStatus(void);
|
||||
|
||||
protected:
|
||||
class ChangeEvent : public nsRunnable {
|
||||
|
@ -49,22 +48,16 @@ protected:
|
|||
bool mCheckAttempted;
|
||||
|
||||
nsresult Shutdown(void);
|
||||
nsresult SendEvent(const char *aEventID);
|
||||
nsresult SendEventToUI(const char *aEventID);
|
||||
|
||||
DWORD CheckAdaptersAddresses(void);
|
||||
|
||||
// Checks for an Internet Connection Sharing (ICS) gateway.
|
||||
bool CheckICSGateway(PIP_ADAPTER_ADDRESSES aAdapter);
|
||||
bool CheckIsGateway(PIP_ADAPTER_ADDRESSES aAdapter);
|
||||
bool CheckICSStatus(PWCHAR aAdapterName);
|
||||
void CheckLinkStatus(void);
|
||||
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
|
||||
HANDLE mShutdownEvent;
|
||||
|
||||
private:
|
||||
// This is a checksum of various meta data for all network interfaces
|
||||
// considered UP at last check.
|
||||
ULONG mIPInterfaceChecksum;
|
||||
};
|
||||
|
||||
#endif /* NSNOTIFYADDRLISTENER_H_ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче