From 57147d1b8d1352e8f49d6086b9957869d0d1e75a Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Wed, 31 May 2023 17:06:25 +0200 Subject: [PATCH] fix: `navigator.connection` not working as intended (#38491) * fix: navigator.connection not working as intended * chore: make network quality methods private --- shell/browser/browser_process_impl.cc | 21 +++++++++++++++++ shell/browser/browser_process_impl.h | 10 ++++++++ shell/browser/electron_browser_main_parts.cc | 2 ++ spec/chromium-spec.ts | 24 ++++++++++++++++++++ 4 files changed, 57 insertions(+) diff --git a/shell/browser/browser_process_impl.cc b/shell/browser/browser_process_impl.cc index 29beeab14f14..d9c6a89a25ba 100644 --- a/shell/browser/browser_process_impl.cc +++ b/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" @@ -125,6 +127,10 @@ void BrowserProcessImpl::PreCreateThreads() { SystemNetworkContextManager::CreateInstance(local_state_.get()); } +void BrowserProcessImpl::PreMainMessageLoopRun() { + CreateNetworkQualityObserver(); +} + void BrowserProcessImpl::PostMainMessageLoopRun() { if (local_state_) local_state_->CommitPendingWrite(); @@ -333,3 +339,18 @@ void BrowserProcessImpl::SetGeolocationManager( std::unique_ptr geolocation_manager) { geolocation_manager_ = std::move(geolocation_manager); } + +network::NetworkQualityTracker* BrowserProcessImpl::GetNetworkQualityTracker() { + if (!network_quality_tracker_) { + network_quality_tracker_ = std::make_unique( + 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_); +} diff --git a/shell/browser/browser_process_impl.h b/shell/browser/browser_process_impl.h index 8109f5f6542c..a70822f6d6c3 100644 --- a/shell/browser/browser_process_impl.h +++ b/shell/browser/browser_process_impl.h @@ -19,6 +19,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" @@ -45,6 +46,7 @@ class BrowserProcessImpl : public BrowserProcess { BuildState* GetBuildState() override; void PostEarlyInitialization(); void PreCreateThreads(); + void PreMainMessageLoopRun(); void PostDestroyThreads() {} void PostMainMessageLoopRun(); @@ -113,6 +115,9 @@ class BrowserProcessImpl : public BrowserProcess { std::unique_ptr geolocation_manager) override; private: + void CreateNetworkQualityObserver(); + network::NetworkQualityTracker* GetNetworkQualityTracker(); + #if BUILDFLAG(ENABLE_PRINTING) std::unique_ptr print_job_manager_; #endif @@ -121,6 +126,11 @@ class BrowserProcessImpl : public BrowserProcess { std::string locale_; std::string system_locale_; embedder_support::OriginTrialsSettingsStorage origin_trials_settings_storage_; + + std::unique_ptr network_quality_tracker_; + std::unique_ptr< + network::NetworkQualityTracker::RTTAndThroughputEstimatesObserver> + network_quality_observer_; }; #endif // ELECTRON_SHELL_BROWSER_BROWSER_PROCESS_IMPL_H_ diff --git a/shell/browser/electron_browser_main_parts.cc b/shell/browser/electron_browser_main_parts.cc index 97df7fe7f0d5..ae820127614a 100644 --- a/shell/browser/electron_browser_main_parts.cc +++ b/shell/browser/electron_browser_main_parts.cc @@ -537,6 +537,8 @@ int ElectronBrowserMainParts::PreMainMessageLoopRun() { // Notify observers that main thread message loop was initialized. Browser::Get()->PreMainMessageLoopRun(); + fake_browser_process_->PreMainMessageLoopRun(); + return GetExitCode(); } diff --git a/spec/chromium-spec.ts b/spec/chromium-spec.ts index 88f5e9238fd7..ceffda8549ce 100644 --- a/spec/chromium-spec.ts +++ b/spec/chromium-spec.ts @@ -1970,6 +1970,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.