Browse Source

fix: `navigator.connection` not working as intended (#39100)

fix: navigator.connection not working as intended
Shelley Vohr 1 year ago
parent
commit
549221d0f1

+ 21 - 0
shell/browser/browser_process_impl.cc

@@ -25,6 +25,8 @@
 #include "components/proxy_config/proxy_config_dictionary.h"
 #include "components/proxy_config/proxy_config_pref_names.h"
 #include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/network_quality_observer_factory.h"
+#include "content/public/browser/network_service_instance.h"
 #include "content/public/common/content_switches.h"
 #include "electron/fuses.h"
 #include "extensions/common/constants.h"
@@ -130,6 +132,10 @@ void BrowserProcessImpl::PreCreateThreads() {
     SystemNetworkContextManager::CreateInstance(local_state_.get());
 }
 
+void BrowserProcessImpl::PreMainMessageLoopRun() {
+  CreateNetworkQualityObserver();
+}
+
 void BrowserProcessImpl::PostMainMessageLoopRun() {
   if (local_state_)
     local_state_->CommitPendingWrite();
@@ -324,3 +330,18 @@ printing::PrintJobManager* BrowserProcessImpl::print_job_manager() {
 StartupData* BrowserProcessImpl::startup_data() {
   return nullptr;
 }
+
+network::NetworkQualityTracker* BrowserProcessImpl::GetNetworkQualityTracker() {
+  if (!network_quality_tracker_) {
+    network_quality_tracker_ = std::make_unique<network::NetworkQualityTracker>(
+        base::BindRepeating(&content::GetNetworkService));
+  }
+  return network_quality_tracker_.get();
+}
+
+void BrowserProcessImpl::CreateNetworkQualityObserver() {
+  DCHECK(!network_quality_observer_);
+  network_quality_observer_ =
+      content::CreateNetworkQualityObserver(GetNetworkQualityTracker());
+  DCHECK(network_quality_observer_);
+}

+ 9 - 0
shell/browser/browser_process_impl.h

@@ -18,6 +18,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/prefs/value_map_pref_store.h"
 #include "printing/buildflags/buildflags.h"
+#include "services/network/public/cpp/network_quality_tracker.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "shell/browser/net/system_network_context_manager.h"
 
@@ -46,6 +47,7 @@ class BrowserProcessImpl : public BrowserProcess {
   GetBreadcrumbPersistentStorageManager() override;
   void PostEarlyInitialization();
   void PreCreateThreads();
+  void PreMainMessageLoopRun();
   void PostDestroyThreads() {}
   void PostMainMessageLoopRun();
 
@@ -109,12 +111,19 @@ class BrowserProcessImpl : public BrowserProcess {
   StartupData* startup_data() override;
 
  private:
+  void CreateNetworkQualityObserver();
+  network::NetworkQualityTracker* GetNetworkQualityTracker();
 #if BUILDFLAG(ENABLE_PRINTING)
   std::unique_ptr<printing::PrintJobManager> print_job_manager_;
 #endif
   std::unique_ptr<PrefService> local_state_;
   std::string locale_;
   std::string system_locale_;
+
+  std::unique_ptr<network::NetworkQualityTracker> network_quality_tracker_;
+  std::unique_ptr<
+      network::NetworkQualityTracker::RTTAndThroughputEstimatesObserver>
+      network_quality_observer_;
 };
 
 #endif  // ELECTRON_SHELL_BROWSER_BROWSER_PROCESS_IMPL_H_

+ 2 - 0
shell/browser/electron_browser_main_parts.cc

@@ -525,6 +525,8 @@ int ElectronBrowserMainParts::PreMainMessageLoopRun() {
   // Notify observers that main thread message loop was initialized.
   Browser::Get()->PreMainMessageLoopRun();
 
+  fake_browser_process_->PreMainMessageLoopRun();
+
   return GetExitCode();
 }
 

+ 24 - 0
spec/chromium-spec.ts

@@ -1988,6 +1988,30 @@ describe('chromium features', () => {
     });
   });
 
+  // https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation
+  describe('navigator.connection', () => {
+    it('returns the correct value', async () => {
+      const w = new BrowserWindow({ show: false });
+
+      w.webContents.session.enableNetworkEmulation({
+        latency: 500,
+        downloadThroughput: 6400,
+        uploadThroughput: 6400
+      });
+
+      await w.loadURL(`file://${fixturesPath}/pages/blank.html`);
+      const rtt = await w.webContents.executeJavaScript('navigator.connection.rtt');
+      expect(rtt).to.be.a('number');
+
+      const downlink = await w.webContents.executeJavaScript('navigator.connection.downlink');
+      expect(downlink).to.be.a('number');
+
+      const effectiveTypes = ['slow-2g', '2g', '3g', '4g'];
+      const effectiveType = await w.webContents.executeJavaScript('navigator.connection.effectiveType');
+      expect(effectiveTypes).to.include(effectiveType);
+    });
+  });
+
   describe('navigator.userAgentData', () => {
     // These tests are done on an http server because navigator.userAgentData
     // requires a secure context.