Bug 1540573 - P3. Expose network link type on ContentChild for use in content process. r=snorp
authorChris Pearce <cpearce@mozilla.com>
Mon, 06 May 2019 22:41:25 +0000
changeset 534695 b78948e4f480ea6b99f2c689fe048256590b8769
parent 534694 d029091d7fd831b30cbc4a660c03f962b20fa44e
child 534696 bcbb8c779852193d99648b9a109daf5ffe17058a
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [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; }
@@ -806,16 +809,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.
@@ -3119,20 +3121,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
@@ -1210,16 +1210,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