diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 84cd904023a4d..4a1291aa80008 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -1271,6 +1271,14 @@ void App::EnableSandbox(mate::Arguments* args) { command_line->AppendSwitch(switches::kEnableSandbox); } +void App::SetUserAgentFallback(const std::string& user_agent) { + AtomBrowserClient::Get()->SetUserAgent(user_agent); +} + +std::string App::GetUserAgentFallback() { + return AtomBrowserClient::Get()->GetUserAgent(); +} + #if defined(OS_MACOSX) bool App::MoveToApplicationsFolder(mate::Arguments* args) { return ui::cocoa::AtomBundleMover::Move(args); @@ -1448,6 +1456,8 @@ void App::BuildPrototype(v8::Isolate* isolate, #if defined(OS_MACOSX) .SetProperty("dock", &App::GetDockAPI) #endif + .SetProperty("userAgentFallback", &App::GetUserAgentFallback, + &App::SetUserAgentFallback) .SetMethod("enableSandbox", &App::EnableSandbox); } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 2473edcafb60a..bfbf84d58aa65 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -210,6 +210,8 @@ class App : public AtomBrowserClient::Delegate, v8::Local GetGPUInfo(v8::Isolate* isolate, const std::string& info_type); void EnableSandbox(mate::Arguments* args); + void SetUserAgentFallback(const std::string& user_agent); + std::string GetUserAgentFallback(); #if defined(OS_MACOSX) bool MoveToApplicationsFolder(mate::Arguments* args); diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index edfbe4666fb97..0b10d75f93f66 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -924,7 +924,13 @@ std::string AtomBrowserClient::GetProduct() const { } std::string AtomBrowserClient::GetUserAgent() const { - return GetApplicationUserAgent(); + if (user_agent_override_.empty()) + return GetApplicationUserAgent(); + return user_agent_override_; +} + +void AtomBrowserClient::SetUserAgent(const std::string& user_agent) { + user_agent_override_ = user_agent; } void AtomBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories( diff --git a/atom/browser/atom_browser_client.h b/atom/browser/atom_browser_client.h index bfbf9118aae0b..338a8c18c1532 100644 --- a/atom/browser/atom_browser_client.h +++ b/atom/browser/atom_browser_client.h @@ -64,6 +64,9 @@ class AtomBrowserClient : public content::ContentBrowserClient, // content::ContentBrowserClient: bool ShouldEnableStrictSiteIsolation() override; + std::string GetUserAgent() const override; + void SetUserAgent(const std::string& user_agent); + protected: void RenderProcessWillLaunch( content::RenderProcessHost* host, @@ -157,7 +160,6 @@ class AtomBrowserClient : public content::ContentBrowserClient, std::vector GetNetworkContextsParentDirectory() override; bool ShouldBypassCORB(int render_process_id) const override; std::string GetProduct() const override; - std::string GetUserAgent() const override; void RegisterNonNetworkNavigationURLLoaderFactories( int frame_tree_node_id, NonNetworkURLLoaderFactoryMap* factories) override; @@ -236,6 +238,8 @@ class AtomBrowserClient : public content::ContentBrowserClient, mutable base::Lock process_preferences_lock_; std::map process_preferences_; + std::string user_agent_override_ = ""; + DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient); }; diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index 186cdaf5c470b..a931b058bec50 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -7,6 +7,7 @@ #include #include "atom/browser/atom_blob_reader.h" +#include "atom/browser/atom_browser_client.h" #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/atom_download_manager_delegate.h" #include "atom/browser/atom_paths.h" @@ -67,7 +68,7 @@ AtomBrowserContext::AtomBrowserContext(const std::string& partition, storage_policy_(new SpecialStoragePolicy), in_memory_(in_memory), weak_factory_(this) { - user_agent_ = GetApplicationUserAgent(); + user_agent_ = AtomBrowserClient::Get()->GetUserAgent(); // Read options. base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); diff --git a/atom/browser/net/system_network_context_manager.cc b/atom/browser/net/system_network_context_manager.cc index 3882a213ad2de..52e4f2673f15a 100644 --- a/atom/browser/net/system_network_context_manager.cc +++ b/atom/browser/net/system_network_context_manager.cc @@ -7,6 +7,7 @@ #include #include +#include "atom/browser/atom_browser_client.h" #include "atom/browser/io_thread.h" #include "atom/common/application_info.h" #include "atom/common/options_switches.h" @@ -245,7 +246,8 @@ SystemNetworkContextManager::CreateNetworkContextParams() { network_context_params->context_name = std::string("system"); - network_context_params->user_agent = atom::GetApplicationUserAgent(); + network_context_params->user_agent = + atom::AtomBrowserClient::Get()->GetUserAgent(); network_context_params->http_cache_enabled = false; diff --git a/docs/api/app.md b/docs/api/app.md index 0ecb666580919..b79adc83a43a4 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -1373,6 +1373,15 @@ On macOS, setting this with any nonzero integer shows on the dock icon. On Linux **Note:** Unity launcher requires the existence of a `.desktop` file to work, for more information please read [Desktop Environment Integration][unity-requirement]. +### `app.userAgentFallback` + +A `String` which is the user agent string Electron will use as a global fallback. + +This is the user agent that will be used when no user agent is set at the +`webContents` or `session` level. Useful for ensuring your entire +app has the same user agent. Set to a custom value as early as possible +in your apps initialization to ensure that your overridden value is used. + ### `app.isPackaged` A `Boolean` property that returns `true` if the app is packaged, `false` otherwise. For many apps, this property can be used to distinguish development and production environments. diff --git a/spec-main/api-app-spec.ts b/spec-main/api-app-spec.ts index 4bcf7f4bdd318..40958954809ff 100644 --- a/spec-main/api-app-spec.ts +++ b/spec-main/api-app-spec.ts @@ -1310,6 +1310,30 @@ describe('default behavior', () => { expect(result).to.equal(true) }) }) + + describe('user agent fallback', () => { + let initialValue: string + + before(() => { + initialValue = app.userAgentFallback! + }) + + it('should have a reasonable default', () => { + expect(initialValue).to.include(`Electron/${process.versions.electron}`) + expect(initialValue).to.include(`Chrome/${process.versions.chrome}`) + }) + + it('should be overridable', () => { + app.userAgentFallback = 'test-agent/123' + expect(app.userAgentFallback).to.equal('test-agent/123') + }) + + it('should be restorable', () => { + app.userAgentFallback = 'test-agent/123' + app.userAgentFallback = '' + expect(app.userAgentFallback).to.equal(initialValue) + }) + }) }) async function runTestApp (name: string, ...args: any[]) { diff --git a/spec-main/index.js b/spec-main/index.js index 7e744b959b231..dd193a9c767b7 100644 --- a/spec-main/index.js +++ b/spec-main/index.js @@ -80,6 +80,6 @@ app.whenReady().then(() => { process.exit(runner.failures) }) } - const runner = (isCI) ? mocha.run(cb) : mocha.forbidOnly().run(cb) + const runner = (isCI) ? mocha.forbidOnly().run(cb) : mocha.run(cb) }) })