From 48af174d85967e25070ac56138fd583f27d1d782 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Tue, 20 Jul 2021 10:33:30 -0700 Subject: [PATCH 1/3] wip --- BUILD.gn | 1 + shell/browser/api/electron_api_web_contents.cc | 4 ++++ shell/browser/electron_browser_client.cc | 5 +++++ shell/browser/electron_browser_client.h | 1 + shell/browser/electron_browser_context.cc | 5 ++--- shell/browser/electron_browser_context.h | 2 +- 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 6377bfe92c5e7..e682fca545f46 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -348,6 +348,7 @@ source_set("electron_lib") { "//chrome/app:command_ids", "//chrome/app/resources:platform_locale_settings", "//components/certificate_transparency", + "//components/embedder_support:browser_util", "//components/language/core/browser", "//components/net_log", "//components/network_hints/browser", diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 00bcf096ac420..967578d342cb1 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -641,9 +641,11 @@ WebContents::WebContents(v8::Isolate* isolate, auto session = Session::CreateFrom(isolate, GetBrowserContext()); session_.Reset(isolate, session.ToV8()); + /* web_contents->SetUserAgentOverride(blink::UserAgentOverride::UserAgentOnly( GetBrowserContext()->GetUserAgent()), false); + */ web_contents->SetUserData(kElectronApiWebContentsKey, std::make_unique(GetWeakPtr())); InitZoomController(web_contents, gin::Dictionary::CreateEmpty(isolate)); @@ -846,9 +848,11 @@ void WebContents::InitWithSessionAndOptions( AutofillDriverFactory::CreateForWebContents(web_contents()); + /* web_contents()->SetUserAgentOverride(blink::UserAgentOverride::UserAgentOnly( GetBrowserContext()->GetUserAgent()), false); + */ if (IsGuest()) { NativeWindow* owner_window = nullptr; diff --git a/shell/browser/electron_browser_client.cc b/shell/browser/electron_browser_client.cc index 4a0af0243ddfe..f1998cd7cf1f7 100644 --- a/shell/browser/electron_browser_client.cc +++ b/shell/browser/electron_browser_client.cc @@ -23,6 +23,7 @@ #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" +#include "components/embedder_support/user_agent_utils.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "chrome/browser/browser_process.h" @@ -1095,6 +1096,10 @@ void ElectronBrowserClient::SetUserAgent(const std::string& user_agent) { user_agent_override_ = user_agent; } +blink::UserAgentMetadata ElectronBrowserClient::GetUserAgentMetadata() { + return embedder_support::GetUserAgentMetadata(); +} + void ElectronBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories( int frame_tree_node_id, ukm::SourceIdObj ukm_source_id, diff --git a/shell/browser/electron_browser_client.h b/shell/browser/electron_browser_client.h index 7e7131ebd67fc..1304f61095270 100644 --- a/shell/browser/electron_browser_client.h +++ b/shell/browser/electron_browser_client.h @@ -89,6 +89,7 @@ class ElectronBrowserClient : public content::ContentBrowserClient, std::string GetUserAgent() override; void SetUserAgent(const std::string& user_agent); + blink::UserAgentMetadata GetUserAgentMetadata() override; content::SerialDelegate* GetSerialDelegate() override; diff --git a/shell/browser/electron_browser_context.cc b/shell/browser/electron_browser_context.cc index eab48d04d41e8..e863e77a9feaf 100644 --- a/shell/browser/electron_browser_context.cc +++ b/shell/browser/electron_browser_context.cc @@ -113,8 +113,6 @@ ElectronBrowserContext::ElectronBrowserContext(const std::string& partition, protocol_registry_(base::WrapUnique(new ProtocolRegistry)), in_memory_(in_memory), ssl_config_(network::mojom::SSLConfig::New()) { - user_agent_ = ElectronBrowserClient::Get()->GetUserAgent(); - // Read options. base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); use_cache_ = !command_line->HasSwitch(switches::kDisableHttpCache); @@ -306,7 +304,8 @@ ElectronBrowserContext::GetSpecialStoragePolicy() { } std::string ElectronBrowserContext::GetUserAgent() const { - return user_agent_; + return user_agent_.value_or(ElectronBrowserClient::Get()->GetUserAgent()); + } predictors::PreconnectManager* ElectronBrowserContext::GetPreconnectManager() { diff --git a/shell/browser/electron_browser_context.h b/shell/browser/electron_browser_context.h index ca2c513ddf880..6e8143ba4ba15 100644 --- a/shell/browser/electron_browser_context.h +++ b/shell/browser/electron_browser_context.h @@ -181,7 +181,7 @@ class ElectronBrowserContext : public content::BrowserContext { std::unique_ptr preconnect_manager_; std::unique_ptr protocol_registry_; - std::string user_agent_; + absl::optional user_agent_; base::FilePath path_; bool in_memory_ = false; bool use_cache_ = true; From 81d2c4fd5cbcc8e610fa89ebcc778a717771d1ee Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 8 Jun 2022 15:27:23 -0700 Subject: [PATCH 2/3] fix session-wide UA overrides --- .../browser/api/electron_api_web_contents.cc | 28 ++++----- shell/browser/electron_browser_context.cc | 4 ++ shell/browser/electron_browser_context.h | 1 + spec-main/chromium-spec.ts | 62 +++++++++++++++++++ 4 files changed, 81 insertions(+), 14 deletions(-) diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 23cca4283bcd6..8f33ec9719a95 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -12,6 +12,7 @@ #include #include +#include "components/embedder_support/user_agent_utils.h" #include "base/containers/id_map.h" #include "base/files/file_util.h" #include "base/json/json_reader.h" @@ -661,11 +662,9 @@ WebContents::WebContents(v8::Isolate* isolate, auto session = Session::CreateFrom(isolate, GetBrowserContext()); session_.Reset(isolate, session.ToV8()); - /* - web_contents->SetUserAgentOverride(blink::UserAgentOverride::UserAgentOnly( - GetBrowserContext()->GetUserAgent()), - false); - */ + absl::optional user_agent_override = GetBrowserContext()->GetUserAgentOverride(); + if (user_agent_override) + SetUserAgent(*user_agent_override); web_contents->SetUserData(kElectronApiWebContentsKey, std::make_unique(GetWeakPtr())); InitZoomController(web_contents, gin::Dictionary::CreateEmpty(isolate)); @@ -871,11 +870,9 @@ void WebContents::InitWithSessionAndOptions( AutofillDriverFactory::CreateForWebContents(web_contents()); - /* - web_contents()->SetUserAgentOverride(blink::UserAgentOverride::UserAgentOnly( - GetBrowserContext()->GetUserAgent()), - false); - */ + absl::optional user_agent_override = GetBrowserContext()->GetUserAgentOverride(); + if (user_agent_override) + SetUserAgent(*user_agent_override); if (IsGuest()) { NativeWindow* owner_window = nullptr; @@ -2153,8 +2150,7 @@ void WebContents::LoadURL(const GURL& url, std::string user_agent; if (options.Get("userAgent", &user_agent)) - web_contents()->SetUserAgentOverride( - blink::UserAgentOverride::UserAgentOnly(user_agent), false); + SetUserAgent(user_agent); std::string extra_headers; if (options.Get("extraHeaders", &extra_headers)) @@ -2369,8 +2365,12 @@ void WebContents::ForcefullyCrashRenderer() { } void WebContents::SetUserAgent(const std::string& user_agent) { - web_contents()->SetUserAgentOverride( - blink::UserAgentOverride::UserAgentOnly(user_agent), false); + blink::UserAgentOverride ua_override; + ua_override.ua_string_override = user_agent; + if (!user_agent.empty()) + ua_override.ua_metadata_override = embedder_support::GetUserAgentMetadata(); + + web_contents()->SetUserAgentOverride(ua_override, false); } std::string WebContents::GetUserAgent() { diff --git a/shell/browser/electron_browser_context.cc b/shell/browser/electron_browser_context.cc index 02ce52ffdeb2b..30e2a98fbab09 100644 --- a/shell/browser/electron_browser_context.cc +++ b/shell/browser/electron_browser_context.cc @@ -307,6 +307,10 @@ std::string ElectronBrowserContext::GetUserAgent() const { } +absl::optional ElectronBrowserContext::GetUserAgentOverride() const { + return user_agent_; +} + predictors::PreconnectManager* ElectronBrowserContext::GetPreconnectManager() { if (!preconnect_manager_.get()) { preconnect_manager_ = diff --git a/shell/browser/electron_browser_context.h b/shell/browser/electron_browser_context.h index 64ab3fe8c76c1..c585859ce038f 100644 --- a/shell/browser/electron_browser_context.h +++ b/shell/browser/electron_browser_context.h @@ -85,6 +85,7 @@ class ElectronBrowserContext : public content::BrowserContext { void SetUserAgent(const std::string& user_agent); std::string GetUserAgent() const; + absl::optional GetUserAgentOverride() const; bool CanUseHttpCache() const; int GetMaxCacheSize() const; ResolveProxyHelper* GetResolveProxyHelper(); diff --git a/spec-main/chromium-spec.ts b/spec-main/chromium-spec.ts index d6bc5cd897a85..f47c1b9b2a63d 100644 --- a/spec-main/chromium-spec.ts +++ b/spec-main/chromium-spec.ts @@ -1508,6 +1508,68 @@ describe('chromium features', () => { expect(focus).to.be.false(); }); }); + + describe('navigator.userAgentData', () => { + // These tests are done on an http server because navigator.userAgentData + // requires a secure context. + let server: http.Server; + let serverUrl: string; + before(async () => { + server = http.createServer((req, res) => { + res.setHeader('Content-Type', 'text/html'); + res.end(''); + }); + await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); + serverUrl = `http://localhost:${(server.address() as any).port}`; + }); + after(() => { + server.close(); + }); + + describe('is not empty', () => { + it('by default', async () => { + const w = new BrowserWindow({ show: false }); + await w.loadURL(serverUrl); + const platform = await w.webContents.executeJavaScript('navigator.userAgentData.platform'); + expect(platform).not.to.be.empty(); + }); + + it('when there is a session-wide UA override', async () => { + const ses = session.fromPartition(`${Math.random()}`); + ses.setUserAgent('foobar'); + const w = new BrowserWindow({ show: false, webPreferences: { session: ses } }); + await w.loadURL(serverUrl); + const platform = await w.webContents.executeJavaScript('navigator.userAgentData.platform'); + expect(platform).not.to.be.empty(); + }); + + it('when there is a WebContents-specific UA override', async () => { + const w = new BrowserWindow({ show: false }); + w.webContents.setUserAgent('foo'); + await w.loadURL(serverUrl); + const platform = await w.webContents.executeJavaScript('navigator.userAgentData.platform'); + expect(platform).not.to.be.empty(); + }); + + it('when there is a WebContents-specific UA override at load time', async () => { + const w = new BrowserWindow({ show: false }); + await w.loadURL(serverUrl, { + userAgent: 'foo' + }); + const platform = await w.webContents.executeJavaScript('navigator.userAgentData.platform'); + expect(platform).not.to.be.empty(); + }); + }); + + describe('brand list', () => { + it('contains chromium', async () => { + const w = new BrowserWindow({ show: false }); + await w.loadURL(serverUrl); + const brands = await w.webContents.executeJavaScript('navigator.userAgentData.brands'); + expect(brands.map((b: any) => b.brand)).to.include('Chromium'); + }); + }); + }); }); describe('font fallback', () => { From 07f7fdef2b84490bb2b2fada884545fb1faa6bd3 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 8 Jun 2022 15:31:02 -0700 Subject: [PATCH 3/3] lint --- shell/browser/api/electron_api_web_contents.cc | 8 +++++--- shell/browser/electron_browser_client.cc | 2 +- shell/browser/electron_browser_context.cc | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 8f33ec9719a95..017897b29b7d1 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -12,7 +12,6 @@ #include #include -#include "components/embedder_support/user_agent_utils.h" #include "base/containers/id_map.h" #include "base/files/file_util.h" #include "base/json/json_reader.h" @@ -30,6 +29,7 @@ #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/views/eye_dropper/eye_dropper.h" #include "chrome/common/pref_names.h" +#include "components/embedder_support/user_agent_utils.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/security_state/content/content_utils.h" @@ -662,7 +662,8 @@ WebContents::WebContents(v8::Isolate* isolate, auto session = Session::CreateFrom(isolate, GetBrowserContext()); session_.Reset(isolate, session.ToV8()); - absl::optional user_agent_override = GetBrowserContext()->GetUserAgentOverride(); + absl::optional user_agent_override = + GetBrowserContext()->GetUserAgentOverride(); if (user_agent_override) SetUserAgent(*user_agent_override); web_contents->SetUserData(kElectronApiWebContentsKey, @@ -870,7 +871,8 @@ void WebContents::InitWithSessionAndOptions( AutofillDriverFactory::CreateForWebContents(web_contents()); - absl::optional user_agent_override = GetBrowserContext()->GetUserAgentOverride(); + absl::optional user_agent_override = + GetBrowserContext()->GetUserAgentOverride(); if (user_agent_override) SetUserAgent(*user_agent_override); diff --git a/shell/browser/electron_browser_client.cc b/shell/browser/electron_browser_client.cc index 0a559eb213ce2..fe5a2da4a87a7 100644 --- a/shell/browser/electron_browser_client.cc +++ b/shell/browser/electron_browser_client.cc @@ -25,12 +25,12 @@ #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "components/embedder_support/user_agent_utils.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_version.h" +#include "components/embedder_support/user_agent_utils.h" #include "components/net_log/chrome_net_log.h" #include "components/network_hints/common/network_hints.mojom.h" #include "content/browser/keyboard_lock/keyboard_lock_service_impl.h" // nogncheck diff --git a/shell/browser/electron_browser_context.cc b/shell/browser/electron_browser_context.cc index 30e2a98fbab09..66643c4731e99 100644 --- a/shell/browser/electron_browser_context.cc +++ b/shell/browser/electron_browser_context.cc @@ -304,10 +304,10 @@ ElectronBrowserContext::GetSpecialStoragePolicy() { std::string ElectronBrowserContext::GetUserAgent() const { return user_agent_.value_or(ElectronBrowserClient::Get()->GetUserAgent()); - } -absl::optional ElectronBrowserContext::GetUserAgentOverride() const { +absl::optional ElectronBrowserContext::GetUserAgentOverride() + const { return user_agent_; }