Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow embedders to provide user agent string #25672

Closed
wants to merge 8 commits into from
@@ -182,6 +182,48 @@ pub trait EmbedderMethods {

/// Register services with a WebXR Registry.
fn register_webxr(&mut self, _: &mut webxr::MainThreadRegistry) {}

/// Returns the default user agent string
fn default_user_agent_string(&self) -> &'static str {
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const UA_STRING: &'static str =
"Mozilla/5.0 (X11; Linux x86_64; rv:72.0) Servo/1.0 Firefox/72.0";
#[cfg(all(target_os = "linux", not(target_arch = "x86_64")))]
const UA_STRING: &'static str =
"Mozilla/5.0 (X11; Linux i686; rv:72.0) Servo/1.0 Firefox/72.0";

#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
const UA_STRING: &'static str =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Servo/1.0 Firefox/72.0";
#[cfg(all(target_os = "windows", not(target_arch = "x86_64")))]
const UA_STRING: &'static str =
"Mozilla/5.0 (Windows NT 10.0; rv:72.0) Servo/1.0 Firefox/72.0";

#[cfg(all(target_os = "macos"))]

This comment has been minimized.

@paulrouget

paulrouget Feb 7, 2020

Contributor

I don’t think the all is necessary here.

const UA_STRING: &'static str =
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:72.0) Servo/1.0 Firefox/72.0";

#[cfg(target_os = "android")]
const UA_STRING: &'static str =
"Mozilla/5.0 (Android; Mobile; rv:68.0) Servo/1.0 Firefox/68.0";

#[cfg(target_os = "ios")]
const UA_STRING: &'static str =
"Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X; rv:72.0) Servo/1.0 Firefox/72.0";

#[cfg(not(any(
target_os = "linux",
target_os = "windows",
target_os = "macos",
target_os = "android",
target_os = "ios"
)))]
// Use OS X user agent as fallback
const UA_STRING: &'static str =
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:72.0) Servo/1.0 Firefox/72.0";

This comment has been minimized.

@paulrouget

paulrouget Feb 7, 2020

Contributor

That’s fine because it’s what we’ve been doing until now. But maybe we should just not have a fallback. Once we support a new platform, we would let it fail at compile time.


UA_STRING
}
}

#[derive(Clone, Copy, Debug)]
@@ -10,7 +10,6 @@ use euclid::Size2D;
use getopts::{Matches, Options};
use servo_geometry::DeviceIndependentPixel;
use servo_url::ServoUrl;
use std::borrow::Cow;
use std::default::Default;
use std::env;
use std::fs::{self, File};
@@ -130,9 +129,6 @@ pub struct Opts {
/// The initial requested size of the window.
pub initial_window_size: Size2D<u32, DeviceIndependentPixel>,

/// An optional string allowing the user agent to be set for testing.
pub user_agent: Cow<'static, str>,

/// Whether we're running in multiprocess mode.
pub multiprocess: bool,

@@ -470,51 +466,6 @@ pub fn multiprocess() -> bool {
MULTIPROCESS.load(Ordering::Relaxed)
}

enum UserAgent {
Desktop,
Android,
#[allow(non_camel_case_types)]
iOS,
}

fn default_user_agent_string(agent: UserAgent) -> &'static str {
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const DESKTOP_UA_STRING: &'static str =
"Mozilla/5.0 (X11; Linux x86_64; rv:72.0) Servo/1.0 Firefox/72.0";
#[cfg(all(target_os = "linux", not(target_arch = "x86_64")))]
const DESKTOP_UA_STRING: &'static str =
"Mozilla/5.0 (X11; Linux i686; rv:72.0) Servo/1.0 Firefox/72.0";

#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
const DESKTOP_UA_STRING: &'static str =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Servo/1.0 Firefox/72.0";
#[cfg(all(target_os = "windows", not(target_arch = "x86_64")))]
const DESKTOP_UA_STRING: &'static str =
"Mozilla/5.0 (Windows NT 10.0; rv:72.0) Servo/1.0 Firefox/72.0";

#[cfg(not(any(target_os = "linux", target_os = "windows")))]
// Neither Linux nor Windows, so maybe OS X, and if not then OS X is an okay fallback.
const DESKTOP_UA_STRING: &'static str =
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:72.0) Servo/1.0 Firefox/72.0";

match agent {
UserAgent::Desktop => DESKTOP_UA_STRING,
UserAgent::Android => "Mozilla/5.0 (Android; Mobile; rv:68.0) Servo/1.0 Firefox/68.0",
UserAgent::iOS => {
"Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X; rv:72.0) Servo/1.0 Firefox/72.0"
},
}
}

#[cfg(target_os = "android")]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Android;

#[cfg(target_os = "ios")]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::iOS;

#[cfg(not(any(target_os = "android", target_os = "ios")))]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Desktop;

pub fn default_opts() -> Opts {
Opts {
is_running_problem_test: false,
@@ -543,7 +494,6 @@ pub fn default_opts() -> Opts {
devtools_port: None,
webdriver_port: None,
initial_window_size: Size2D::new(1024, 740),
user_agent: default_user_agent_string(DEFAULT_USER_AGENT).into(),
multiprocess: false,
random_pipeline_closure_probability: None,
random_pipeline_closure_seed: None,
@@ -662,12 +612,6 @@ pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingR
"7000",
);
opts.optopt("", "resolution", "Set window resolution.", "1024x740");
opts.optopt(
"u",
"user-agent",
"Set custom user agent string (or ios / android / desktop for platform default)",
"NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)",
);
opts.optflag("M", "multiprocess", "Run in multiprocess mode");
opts.optflag("S", "sandbox", "Run in a sandbox if multiprocess");
opts.optopt(
@@ -911,14 +855,6 @@ pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingR
MULTIPROCESS.store(true, Ordering::SeqCst)
}

let user_agent = match opt_match.opt_str("u") {
Some(ref ua) if ua == "ios" => default_user_agent_string(UserAgent::iOS).into(),
Some(ref ua) if ua == "android" => default_user_agent_string(UserAgent::Android).into(),
Some(ref ua) if ua == "desktop" => default_user_agent_string(UserAgent::Desktop).into(),
Some(ua) => ua.into(),
None => default_user_agent_string(DEFAULT_USER_AGENT).into(),
};

This comment has been minimized.

@paulrouget

paulrouget Feb 7, 2020

Contributor

This still needs to be possible.


let user_stylesheets = opt_match
.opt_strs("user-stylesheet")
.iter()
@@ -963,7 +899,6 @@ pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingR
devtools_port: devtools_port,
webdriver_port: webdriver_port,
initial_window_size: initial_window_size,
user_agent: user_agent,
multiprocess: opt_match.opt_present("M"),
sandbox: opt_match.opt_present("S"),
random_pipeline_closure_probability: random_pipeline_closure_probability,
@@ -160,7 +160,7 @@ use servo_config::{opts, pref};
use servo_rand::{random, Rng, ServoRng, SliceRandom};
use servo_remutex::ReentrantMutex;
use servo_url::{Host, ImmutableOrigin, ServoUrl};
use std::borrow::ToOwned;
use std::borrow::{Cow, ToOwned};
use std::collections::hash_map::Entry;
use std::collections::{HashMap, HashSet, VecDeque};
use std::marker::PhantomData;
@@ -491,6 +491,9 @@ pub struct Constellation<Message, LTF, STF> {

/// Pipeline ID of the active media session.
active_media_session: Option<PipelineId>,

/// User agent string
pub user_agent: Cow<'static, str>,
}

/// State needed to construct a constellation.
@@ -547,6 +550,9 @@ pub struct InitialConstellationState {

/// Mechanism to force the compositor to process events.
pub event_loop_waker: Option<Box<dyn EventLoopWaker>>,

/// User agent string
pub user_agent: Cow<'static, str>,
}

/// Data needed for webdriver
@@ -980,6 +986,7 @@ where
player_context: state.player_context,
event_loop_waker: state.event_loop_waker,
active_media_session: None,
user_agent: state.user_agent,
};

constellation.run();
@@ -1227,6 +1234,7 @@ where
webxr_registry: self.webxr_registry.clone(),
player_context: self.player_context.clone(),
event_loop_waker: self.event_loop_waker.as_ref().map(|w| (*w).clone_box()),
user_agent: self.user_agent.clone(),
});

let pipeline = match result {
@@ -40,6 +40,7 @@ use script_traits::{ScriptThreadFactory, TimerSchedulerMsg, WindowSizeData};
use servo_config::opts::{self, Opts};
use servo_config::{prefs, prefs::PrefValue};
use servo_url::ServoUrl;
use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
#[cfg(not(windows))]
use std::env;
@@ -204,6 +205,9 @@ pub struct InitialPipelineState {

/// Mechanism to force the compositor to process events.
pub event_loop_waker: Option<Box<dyn EventLoopWaker>>,

/// User agent string
pub user_agent: Cow<'static, str>,
}

pub struct NewPipeline {
@@ -307,6 +311,7 @@ impl Pipeline {
webvr_chan: state.webvr_chan,
webxr_registry: state.webxr_registry,
player_context: state.player_context,
user_agent: state.user_agent,
};

// Spawn the child process.
@@ -514,6 +519,7 @@ pub struct UnprivilegedPipelineContent {
webvr_chan: Option<IpcSender<WebVRMsg>>,
webxr_registry: webxr_api::Registry,
player_context: WindowGLContext,
user_agent: Cow<'static, str>,
}

impl UnprivilegedPipelineContent {
@@ -570,6 +576,7 @@ impl UnprivilegedPipelineContent {
layout_is_busy: layout_thread_busy_flag.clone(),
player_context: self.player_context.clone(),
event_loop_waker,
user_agent: self.user_agent,
},
self.load_data.clone(),
self.opts.profile_script_events,
@@ -582,7 +589,6 @@ impl UnprivilegedPipelineContent {
self.opts.userscripts,
self.opts.headless,
self.opts.replace_surrogates,
self.opts.user_agent,
);

LTF::create(
@@ -741,7 +741,6 @@ impl ScriptThreadFactory for ScriptThread {
userscripts_path: Option<String>,
headless: bool,
replace_surrogates: bool,
user_agent: Cow<'static, str>,
) -> (Sender<message::Msg>, Receiver<message::Msg>) {
let (script_chan, script_port) = unbounded();

@@ -763,6 +762,7 @@ impl ScriptThreadFactory for ScriptThread {
let mem_profiler_chan = state.mem_profiler_chan.clone();
let window_size = state.window_size;
let layout_is_busy = state.layout_is_busy.clone();
let user_agent = state.user_agent.clone();

let script_thread = ScriptThread::new(
state,
@@ -683,6 +683,8 @@ pub struct InitialScriptState {
pub player_context: WindowGLContext,
/// Mechanism to force the compositor to process events.
pub event_loop_waker: Option<Box<dyn EventLoopWaker>>,
/// An optional string allowing the user agent to be set for testing.
pub user_agent: Cow<'static, str>,
}

/// This trait allows creating a `ScriptThread` without depending on the `script`
@@ -702,7 +704,6 @@ pub trait ScriptThreadFactory {
userscripts_path: Option<String>,
headless: bool,
replace_surrogates: bool,
user_agent: Cow<'static, str>,
) -> (Sender<Self::Message>, Receiver<Self::Message>);
}

@@ -860,7 +861,7 @@ pub struct WorkerGlobalScopeInit {
pub origin: ImmutableOrigin,
/// True if headless mode
pub is_headless: bool,
/// An optional string allowing the user agnet to be set for testing.
/// User agent string
pub user_agent: Cow<'static, str>,
}

@@ -506,7 +506,7 @@ where
// pipelines, including the script and layout threads, as well
// as the navigation context.
let (constellation_chan, sw_senders) = create_constellation(
opts.user_agent.clone(),
embedder.default_user_agent_string().into(),
opts.config_dir.clone(),
embedder_proxy.clone(),
compositor_proxy.clone(),
@@ -857,7 +857,7 @@ fn create_constellation(
BluetoothThreadFactory::new(embedder_proxy.clone());

let (public_resource_threads, private_resource_threads) = new_resource_threads(
user_agent,
user_agent.clone(),
devtools_chan.clone(),
time_profiler_chan.clone(),
mem_profiler_chan.clone(),
@@ -891,6 +891,7 @@ fn create_constellation(
glplayer_threads,
player_context,
event_loop_waker,
user_agent,
};
let (constellation_chan, from_swmanager_sender) = Constellation::<
script_layout_interface::message::Msg,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.