netwerk/system/mac/nsNetworkLinkService.mm

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsNetworkLinkService.h"
     7 #include "nsCOMPtr.h"
     8 #include "nsIObserverService.h"
     9 #include "nsServiceManagerUtils.h"
    10 #include "nsString.h"
    11 #include "nsCRT.h"
    13 #import <Cocoa/Cocoa.h>
    14 #import <netinet/in.h>
    16 NS_IMPL_ISUPPORTS(nsNetworkLinkService,
    17                   nsINetworkLinkService,
    18                   nsIObserver)
    20 nsNetworkLinkService::nsNetworkLinkService()
    21     : mLinkUp(true)
    22     , mStatusKnown(false)
    23     , mReachability(NULL)
    24     , mCFRunLoop(NULL)
    25 {
    26 }
    28 nsNetworkLinkService::~nsNetworkLinkService()
    29 {
    30 }
    32 NS_IMETHODIMP
    33 nsNetworkLinkService::GetIsLinkUp(bool *aIsUp)
    34 {
    35     *aIsUp = mLinkUp;
    36     return NS_OK;
    37 }
    39 NS_IMETHODIMP
    40 nsNetworkLinkService::GetLinkStatusKnown(bool *aIsUp)
    41 {
    42     *aIsUp = mStatusKnown;
    43     return NS_OK;
    44 }
    46 NS_IMETHODIMP
    47 nsNetworkLinkService::GetLinkType(uint32_t *aLinkType)
    48 {
    49   NS_ENSURE_ARG_POINTER(aLinkType);
    51   // XXX This function has not yet been implemented for this platform
    52   *aLinkType = nsINetworkLinkService::LINK_TYPE_UNKNOWN;
    53   return NS_OK;
    54 }
    56 NS_IMETHODIMP
    57 nsNetworkLinkService::Observe(nsISupports *subject,
    58                               const char *topic,
    59                               const char16_t *data)
    60 {
    61     if (!strcmp(topic, "xpcom-shutdown")) {
    62         Shutdown();
    63     }
    65     return NS_OK;
    66 }
    68 nsresult
    69 nsNetworkLinkService::Init(void)
    70 {
    71     nsresult rv;
    73     nsCOMPtr<nsIObserverService> observerService =
    74         do_GetService("@mozilla.org/observer-service;1", &rv);
    75     NS_ENSURE_SUCCESS(rv, rv);
    77     rv = observerService->AddObserver(this, "xpcom-shutdown", false);
    78     NS_ENSURE_SUCCESS(rv, rv);
    80     // If the network reachability API can reach 0.0.0.0 without
    81     // requiring a connection, there is a network interface available.
    82     struct sockaddr_in addr;
    83     bzero(&addr, sizeof(addr));
    84     addr.sin_len = sizeof(addr);
    85     addr.sin_family = AF_INET;
    86     mReachability =
    87         ::SCNetworkReachabilityCreateWithAddress(NULL,
    88                                                  (struct sockaddr *)&addr);
    89     if (!mReachability) {
    90         return NS_ERROR_NOT_AVAILABLE;
    91     }
    93     SCNetworkReachabilityContext context = {0, this, NULL, NULL, NULL};
    94     if (!::SCNetworkReachabilitySetCallback(mReachability,
    95                                             ReachabilityChanged,
    96                                             &context)) {
    97         NS_WARNING("SCNetworkReachabilitySetCallback failed.");
    98         ::CFRelease(mReachability);
    99         mReachability = NULL;
   100         return NS_ERROR_NOT_AVAILABLE;
   101     }
   103     // Get the current run loop.  This service is initialized at startup,
   104     // so we shouldn't run in to any problems with modal dialog run loops.
   105     mCFRunLoop = [[NSRunLoop currentRunLoop] getCFRunLoop];
   106     if (!mCFRunLoop) {
   107         NS_WARNING("Could not get current run loop.");
   108         ::CFRelease(mReachability);
   109         mReachability = NULL;
   110         return NS_ERROR_NOT_AVAILABLE;
   111     }
   112     ::CFRetain(mCFRunLoop);
   114     if (!::SCNetworkReachabilityScheduleWithRunLoop(mReachability, mCFRunLoop,
   115                                                     kCFRunLoopDefaultMode)) {
   116         NS_WARNING("SCNetworkReachabilityScheduleWIthRunLoop failed.");
   117         ::CFRelease(mReachability);
   118         mReachability = NULL;
   119         ::CFRelease(mCFRunLoop);
   120         mCFRunLoop = NULL;
   121         return NS_ERROR_NOT_AVAILABLE;
   122     }
   124     UpdateReachability();
   126     return NS_OK;
   127 }
   129 nsresult
   130 nsNetworkLinkService::Shutdown()
   131 {
   132     if (!::SCNetworkReachabilityUnscheduleFromRunLoop(mReachability,
   133                                                       mCFRunLoop,
   134                                                       kCFRunLoopDefaultMode)) {
   135         NS_WARNING("SCNetworkReachabilityUnscheduleFromRunLoop failed.");
   136     }
   138     ::CFRelease(mReachability);
   139     mReachability = NULL;
   141     ::CFRelease(mCFRunLoop);
   142     mCFRunLoop = NULL;
   144     return NS_OK;
   145 }
   147 void
   148 nsNetworkLinkService::UpdateReachability()
   149 {
   150     if (!mReachability) {
   151         return;
   152     }
   154     SCNetworkConnectionFlags flags;
   155     if (!::SCNetworkReachabilityGetFlags(mReachability, &flags)) {
   156         mStatusKnown = false;
   157         return;
   158     }
   160     bool reachable = (flags & kSCNetworkFlagsReachable) != 0;
   161     bool needsConnection = (flags & kSCNetworkFlagsConnectionRequired) != 0;
   163     mLinkUp = (reachable && !needsConnection);
   164     mStatusKnown = true;
   165 }
   167 void
   168 nsNetworkLinkService::SendEvent()
   169 {
   170     nsCOMPtr<nsIObserverService> observerService =
   171         do_GetService("@mozilla.org/observer-service;1");
   172     if (!observerService)
   173         return;
   175     const char *event;
   176     if (!mStatusKnown)
   177         event = NS_NETWORK_LINK_DATA_UNKNOWN;
   178     else
   179         event = mLinkUp ? NS_NETWORK_LINK_DATA_UP
   180                         : NS_NETWORK_LINK_DATA_DOWN;
   182     observerService->NotifyObservers(static_cast<nsINetworkLinkService*>(this),
   183                                      NS_NETWORK_LINK_TOPIC,
   184                                      NS_ConvertASCIItoUTF16(event).get());
   185 }
   187 /* static */
   188 void
   189 nsNetworkLinkService::ReachabilityChanged(SCNetworkReachabilityRef target,
   190                                           SCNetworkConnectionFlags flags,
   191                                           void *info)
   192 {
   193     nsNetworkLinkService *service =
   194         static_cast<nsNetworkLinkService*>(info);
   196     service->UpdateReachability();
   197     service->SendEvent();
   198 }

mercurial