Bug 1540573 - P3. Expose network link type on ContentChild for use in content process. r=snorp
☠☠ backed out by e5ce38e989b8 ☠ ☠
authorChris Pearce <cpearce@mozilla.com>
Wed, 01 May 2019 23:46:23 +0000
changeset 472229 3496ca48f6e0f4abe6a2d5df947e604a0aeda6d2
parent 472228 2c4303b175ec5aa10beb766daf0bc8962e13d649
child 472230 814c94b260288ec39dc4dc552a552d953e8c1d76
push id84530
push usercpearce@mozilla.com
push dateThu, 02 May 2019 01:20:23 +0000
treeherderautoland@599e6e06599d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1540573
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1540573 - P3. Expose network link type on ContentChild for use in content process. r=snorp In GeckoView the nsINetworkLinkService doesn't work in the content process, as we don't seem to have an AndroidBridge there, so just maintain the network connection type on the ContentChild. (I had considered keeping this on the NeckoChild, but the creation of that is initiated from the content process side, and there's not an easy and clean way to have the parent process send us the connection type after construction of the NeckoParent, other than have the NeckoChild request it either synchronously, or doing it async and hoping it's not asked for the value before the response comes in.) Differential Revision: https://phabricator.services.mozilla.com/D26232
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/media/VideoUtils.cpp
dom/media/VideoUtils.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2024,16 +2024,27 @@ mozilla::ipc::IPCResult ContentChild::Re
   }
 
   static_cast<loader::ScriptCacheChild*>(actor)->Init(fd, wantCacheData);
   return IPC_OK();
 }
 
 PNeckoChild* ContentChild::AllocPNeckoChild() { return new NeckoChild(); }
 
+mozilla::ipc::IPCResult ContentChild::RecvNetworkLinkTypeChange(
+    const uint32_t& aType) {
+  mNetworkLinkType = aType;
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (obs) {
+    obs->NotifyObservers(nullptr, "contentchild:network-link-type-changed",
+                         nullptr);
+  }
+  return IPC_OK();
+}
+
 bool ContentChild::DeallocPNeckoChild(PNeckoChild* necko) {
   delete necko;
   return true;
 }
 
 PPrintingChild* ContentChild::AllocPPrintingChild() {
   // The ContentParent should never attempt to allocate the nsPrintingProxy,
   // which implements PPrintingChild. Instead, the nsPrintingProxy service is
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -484,16 +484,19 @@ class ContentChild final : public PConte
 
   mozilla::ipc::IPCResult RecvActivate(PBrowserChild* aTab);
 
   mozilla::ipc::IPCResult RecvDeactivate(PBrowserChild* aTab);
 
   mozilla::ipc::IPCResult RecvRefreshScreens(
       nsTArray<ScreenDetails>&& aScreens);
 
+  mozilla::ipc::IPCResult RecvNetworkLinkTypeChange(const uint32_t& aType);
+  uint32_t NetworkLinkType() const { return mNetworkLinkType; }
+
   // Get the directory for IndexedDB files. We query the parent for this and
   // cache the value
   nsString& GetIndexedDBPath();
 
   ContentParentId GetID() const { return mID; }
 
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   uint32_t GetChromeMainThreadId() const { return mMainChromeTid; }
@@ -805,16 +808,18 @@ class ContentChild final : public PConte
   mozilla::Atomic<bool> mShuttingDown;
 
 #ifdef NIGHTLY_BUILD
   // NOTE: This member is atomic because it can be accessed from
   // off-main-thread.
   mozilla::Atomic<uint32_t> mPendingInputEvents;
 #endif
 
+  uint32_t mNetworkLinkType = 0;
+
   DISALLOW_EVIL_CONSTRUCTORS(ContentChild);
 };
 
 uint64_t NextWindowID();
 
 }  // namespace dom
 }  // namespace mozilla
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -153,16 +153,17 @@
 #include "nsIGfxInfo.h"
 #include "nsIIdleService.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsILocalStorageManager.h"
 #include "nsIMemoryInfoDumper.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMozBrowserFrame.h"
 #include "nsIMutable.h"
+#include "nsINetworkLinkService.h"
 #include "nsIObserverService.h"
 #include "nsIParentChannel.h"
 #include "nsIRemoteWindowContext.h"
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISearchService.h"
 #include "nsIServiceWorkerManager.h"
 #include "nsISiteSecurityService.h"
@@ -609,16 +610,17 @@ static const char* sObserverTopics[] = {
     "a11y-init-or-shutdown",
 #endif
     "cacheservice:empty-cache",
     "intl:app-locales-changed",
     "intl:requested-locales-changed",
     "cookie-changed",
     "private-cookie-changed",
     "clear-site-data-reload-needed",
+    NS_NETWORK_LINK_TYPE_TOPIC,
 };
 
 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
 bool ContentParent::sEarlySandboxInit = false;
 #endif
 
 // PreallocateProcess is called by the PreallocatedProcessManager.
 // ContentParent then takes this process back within GetNewOrUsedBrowserProcess.
@@ -3115,20 +3117,40 @@ ContentParent::Observe(nsISupports* aSub
       cs->RemoveCookie(xpcCookie);
     } else if ((!nsCRT::strcmp(aData, u"added")) ||
                (!nsCRT::strcmp(aData, u"changed"))) {
       cs->AddCookie(xpcCookie);
     }
   } else if (!strcmp(aTopic, "clear-site-data-reload-needed")) {
     // Rebroadcast "clear-site-data-reload-needed".
     Unused << SendClearSiteDataReloadNeeded(nsString(aData));
-  }
+  } else if (!strcmp(aTopic, NS_NETWORK_LINK_TYPE_TOPIC)) {
+    UpdateNetworkLinkType();
+  }
+
   return NS_OK;
 }
 
+void ContentParent::UpdateNetworkLinkType() {
+  nsresult rv;
+  nsCOMPtr<nsINetworkLinkService> nls =
+      do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID, &rv);
+  if (NS_FAILED(rv)) {
+    return;
+  }
+
+  uint32_t linkType = nsINetworkLinkService::LINK_TYPE_UNKNOWN;
+  rv = nls->GetLinkType(&linkType);
+  if (NS_FAILED(rv)) {
+    return;
+  }
+
+  Unused << SendNetworkLinkTypeChange(linkType);
+}
+
 NS_IMETHODIMP
 ContentParent::GetInterface(const nsIID& aIID, void** aResult) {
   NS_ENSURE_ARG_POINTER(aResult);
 
   if (aIID.Equals(NS_GET_IID(nsIMessageSender))) {
     nsCOMPtr<nsIMessageSender> mm = GetMessageManager();
     mm.forget(aResult);
     return NS_OK;
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -1208,16 +1208,18 @@ class ContentParent final : public PCont
 
   bool IsRecordingOrReplaying() const {
     return mRecordReplayState != eNotRecordingOrReplaying;
   }
 
   void OnBrowsingContextGroupSubscribe(BrowsingContextGroup* aGroup);
   void OnBrowsingContextGroupUnsubscribe(BrowsingContextGroup* aGroup);
 
+  void UpdateNetworkLinkType();
+
  private:
   // Released in ActorDestroy; deliberately not exposed to the CC.
   RefPtr<ContentParent> mSelfRef;
 
   // If you add strong pointers to cycle collected objects here, be sure to
   // release these objects in ShutDownProcess.  See the comment there for more
   // details.
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -425,16 +425,18 @@ child:
       Endpoint<PCompositorManagerChild> compositor,
       Endpoint<PImageBridgeChild> bridge,
       Endpoint<PVRManagerChild> vr,
       Endpoint<PVideoDecoderManagerChild> video,
       uint32_t[] namespaces);
 
     async AudioDefaultDeviceChange();
 
+    async NetworkLinkTypeChange(uint32_t type);
+
     // Re-create the rendering stack for a device reset.
     async ReinitRenderingForDeviceReset();
 
     /**
      * Enable system-level sandboxing features, if available.  Can
      * usually only be performed zero or one times.  The child may
      * abnormally exit if this fails; the details are OS-specific.
      */
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -9,28 +9,31 @@
 
 #include "CubebUtils.h"
 #include "ImageContainer.h"
 #include "MediaContainerType.h"
 #include "MediaResource.h"
 #include "TimeUnits.h"
 #include "VorbisUtils.h"
 #include "mozilla/Base64.h"
+#include "mozilla/dom/ContentChild.h"
 #include "mozilla/SharedThreadPool.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/SystemGroup.h"
 #include "mozilla/TaskCategory.h"
 #include "mozilla/TaskQueue.h"
 #include "mozilla/Telemetry.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsContentTypeParser.h"
 #include "nsIConsoleService.h"
+#include "nsINetworkLinkService.h"
 #include "nsIRandomGenerator.h"
 #include "nsIServiceManager.h"
 #include "nsMathUtils.h"
+#include "nsNetCID.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 
 using layers::PlanarYCbCrImage;
 using media::TimeUnit;
 
@@ -707,9 +710,51 @@ UniquePtr<TrackInfo> CreateTrackInfoWith
       if (maybeSamplerate && *maybeSamplerate > 0) {
         audioInfo->mRate = *maybeSamplerate;
       }
     }
   }
   return trackInfo;
 }
 
+bool OnCellularConnection() {
+  uint32_t linkType = nsINetworkLinkService::LINK_TYPE_UNKNOWN;
+  if (XRE_IsContentProcess()) {
+    mozilla::dom::ContentChild* cpc =
+        mozilla::dom::ContentChild::GetSingleton();
+    if (!cpc) {
+      NS_WARNING("Can't get ContentChild singleton in content process!");
+      return false;
+    }
+    linkType = cpc->NetworkLinkType();
+  } else {
+    nsresult rv;
+    nsCOMPtr<nsINetworkLinkService> nls =
+        do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID, &rv);
+    if (NS_FAILED(rv)) {
+      NS_WARNING("Can't get nsINetworkLinkService.");
+      return false;
+    }
+
+    rv = nls->GetLinkType(&linkType);
+    if (NS_FAILED(rv)) {
+      NS_WARNING("Can't get network link type.");
+      return false;
+    }
+  }
+
+  switch (linkType) {
+    case nsINetworkLinkService::LINK_TYPE_UNKNOWN:
+    case nsINetworkLinkService::LINK_TYPE_ETHERNET:
+    case nsINetworkLinkService::LINK_TYPE_USB:
+    case nsINetworkLinkService::LINK_TYPE_WIFI:
+      return false;
+    case nsINetworkLinkService::LINK_TYPE_WIMAX:
+    case nsINetworkLinkService::LINK_TYPE_2G:
+    case nsINetworkLinkService::LINK_TYPE_3G:
+    case nsINetworkLinkService::LINK_TYPE_4G:
+      return true;
+  }
+
+  return false;
+}
+
 }  // end namespace mozilla
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -540,11 +540,15 @@ static bool StringListContains(const Lis
 
 inline void AppendStringIfNotEmpty(nsACString& aDest, nsACString&& aSrc) {
   if (!aSrc.IsEmpty()) {
     aDest.Append(NS_LITERAL_CSTRING("\n"));
     aDest.Append(aSrc);
   }
 }
 
+// Returns true if we're running on a cellular connection; 2G, 3G, etc.
+// Main thread only.
+bool OnCellularConnection();
+
 }  // end namespace mozilla
 
 #endif