mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
allow for a service worker manager per origin
This commit is contained in:
parent
9972aee81f
commit
db217d5575
11 changed files with 405 additions and 245 deletions
|
@ -2,14 +2,53 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use embedder_traits::resources;
|
||||
use crate::pipeline::UnprivilegedPipelineContent;
|
||||
use crate::serviceworker::ServiceWorkerUnprivilegedContent;
|
||||
#[cfg(all(
|
||||
not(target_os = "windows"),
|
||||
not(target_os = "ios"),
|
||||
not(target_os = "android"),
|
||||
not(target_arch = "arm"),
|
||||
not(target_arch = "aarch64")
|
||||
))]
|
||||
use gaol::profile::{Operation, PathPattern, Profile};
|
||||
use std::path::PathBuf;
|
||||
use ipc_channel::Error;
|
||||
use servo_config::opts::Opts;
|
||||
use servo_config::prefs::PrefValue;
|
||||
use std::collections::HashMap;
|
||||
#[cfg(not(windows))]
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::process;
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum UnprivilegedContent {
|
||||
Pipeline(UnprivilegedPipelineContent),
|
||||
ServiceWorker(ServiceWorkerUnprivilegedContent),
|
||||
}
|
||||
|
||||
impl UnprivilegedContent {
|
||||
pub fn opts(&self) -> Opts {
|
||||
match self {
|
||||
UnprivilegedContent::Pipeline(content) => content.opts(),
|
||||
UnprivilegedContent::ServiceWorker(content) => content.opts(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prefs(&self) -> HashMap<String, PrefValue> {
|
||||
match self {
|
||||
UnprivilegedContent::Pipeline(content) => content.prefs(),
|
||||
UnprivilegedContent::ServiceWorker(content) => content.prefs(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Our content process sandbox profile on Mac. As restrictive as possible.
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn content_process_sandbox_profile() -> Profile {
|
||||
use embedder_traits::resources;
|
||||
use gaol::platform;
|
||||
use std::path::PathBuf;
|
||||
|
||||
let mut operations = vec![
|
||||
Operation::FileReadAll(PathPattern::Literal(PathBuf::from("/dev/urandom"))),
|
||||
|
@ -46,8 +85,18 @@ pub fn content_process_sandbox_profile() -> Profile {
|
|||
}
|
||||
|
||||
/// Our content process sandbox profile on Linux. As restrictive as possible.
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(all(
|
||||
not(target_os = "macos"),
|
||||
not(target_os = "windows"),
|
||||
not(target_os = "ios"),
|
||||
not(target_os = "android"),
|
||||
not(target_arch = "arm"),
|
||||
not(target_arch = "aarch64")
|
||||
))]
|
||||
pub fn content_process_sandbox_profile() -> Profile {
|
||||
use embedder_traits::resources;
|
||||
use std::path::PathBuf;
|
||||
|
||||
let mut operations = vec![Operation::FileReadAll(PathPattern::Literal(PathBuf::from(
|
||||
"/dev/urandom",
|
||||
)))];
|
||||
|
@ -65,3 +114,150 @@ pub fn content_process_sandbox_profile() -> Profile {
|
|||
|
||||
Profile::new(operations).expect("Failed to create sandbox profile!")
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "windows",
|
||||
target_os = "ios",
|
||||
target_os = "android",
|
||||
target_arch = "arm",
|
||||
target_arch = "aarch64",
|
||||
))]
|
||||
pub fn content_process_sandbox_profile() {
|
||||
error!("Sandboxed multiprocess is not supported on this platform.");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_arch = "arm",
|
||||
all(target_arch = "aarch64", not(target_os = "windows"))
|
||||
))]
|
||||
pub fn spawn_multiprocess(content: UnprivilegedContent) -> Result<(), Error> {
|
||||
use ipc_channel::ipc::{IpcOneShotServer, IpcSender};
|
||||
// Note that this function can panic, due to process creation,
|
||||
// avoiding this panic would require a mechanism for dealing
|
||||
// with low-resource scenarios.
|
||||
let (server, token) = IpcOneShotServer::<IpcSender<UnprivilegedContent>>::new()
|
||||
.expect("Failed to create IPC one-shot server.");
|
||||
|
||||
let path_to_self = env::current_exe().expect("Failed to get current executor.");
|
||||
let mut child_process = process::Command::new(path_to_self);
|
||||
setup_common(&mut child_process, token);
|
||||
let _ = child_process
|
||||
.spawn()
|
||||
.expect("Failed to start unsandboxed child process!");
|
||||
|
||||
let (_receiver, sender) = server.accept().expect("Server failed to accept.");
|
||||
sender.send(content)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(target_os = "windows"),
|
||||
not(target_os = "ios"),
|
||||
not(target_os = "android"),
|
||||
not(target_arch = "arm"),
|
||||
not(target_arch = "aarch64")
|
||||
))]
|
||||
pub fn spawn_multiprocess(content: UnprivilegedContent) -> Result<(), Error> {
|
||||
use gaol::sandbox::{self, Sandbox, SandboxMethods};
|
||||
use ipc_channel::ipc::{IpcOneShotServer, IpcSender};
|
||||
|
||||
impl CommandMethods for sandbox::Command {
|
||||
fn arg<T>(&mut self, arg: T)
|
||||
where
|
||||
T: AsRef<OsStr>,
|
||||
{
|
||||
self.arg(arg);
|
||||
}
|
||||
|
||||
fn env<T, U>(&mut self, key: T, val: U)
|
||||
where
|
||||
T: AsRef<OsStr>,
|
||||
U: AsRef<OsStr>,
|
||||
{
|
||||
self.env(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
// Note that this function can panic, due to process creation,
|
||||
// avoiding this panic would require a mechanism for dealing
|
||||
// with low-resource scenarios.
|
||||
let (server, token) = IpcOneShotServer::<IpcSender<UnprivilegedContent>>::new()
|
||||
.expect("Failed to create IPC one-shot server.");
|
||||
|
||||
// If there is a sandbox, use the `gaol` API to create the child process.
|
||||
if content.opts().sandbox {
|
||||
let mut command = sandbox::Command::me().expect("Failed to get current sandbox.");
|
||||
setup_common(&mut command, token);
|
||||
|
||||
let profile = content_process_sandbox_profile();
|
||||
let _ = Sandbox::new(profile)
|
||||
.start(&mut command)
|
||||
.expect("Failed to start sandboxed child process!");
|
||||
} else {
|
||||
let path_to_self = env::current_exe().expect("Failed to get current executor.");
|
||||
let mut child_process = process::Command::new(path_to_self);
|
||||
setup_common(&mut child_process, token);
|
||||
let _ = child_process
|
||||
.spawn()
|
||||
.expect("Failed to start unsandboxed child process!");
|
||||
}
|
||||
|
||||
let (_receiver, sender) = server.accept().expect("Server failed to accept.");
|
||||
sender.send(content)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "ios"))]
|
||||
pub fn spawn_multiprocess(_content: UnprivilegedContent) -> Result<(), Error> {
|
||||
error!("Multiprocess is not supported on Windows or iOS.");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn setup_common<C: CommandMethods>(command: &mut C, token: String) {
|
||||
C::arg(command, "--content-process");
|
||||
C::arg(command, token);
|
||||
|
||||
if let Ok(value) = env::var("RUST_BACKTRACE") {
|
||||
C::env(command, "RUST_BACKTRACE", value);
|
||||
}
|
||||
|
||||
if let Ok(value) = env::var("RUST_LOG") {
|
||||
C::env(command, "RUST_LOG", value);
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to unify commands launched as multiprocess with or without a sandbox.
|
||||
trait CommandMethods {
|
||||
/// A command line argument.
|
||||
fn arg<T>(&mut self, arg: T)
|
||||
where
|
||||
T: AsRef<OsStr>;
|
||||
|
||||
/// An environment variable.
|
||||
fn env<T, U>(&mut self, key: T, val: U)
|
||||
where
|
||||
T: AsRef<OsStr>,
|
||||
U: AsRef<OsStr>;
|
||||
}
|
||||
|
||||
impl CommandMethods for process::Command {
|
||||
fn arg<T>(&mut self, arg: T)
|
||||
where
|
||||
T: AsRef<OsStr>,
|
||||
{
|
||||
self.arg(arg);
|
||||
}
|
||||
|
||||
fn env<T, U>(&mut self, key: T, val: U)
|
||||
where
|
||||
T: AsRef<OsStr>,
|
||||
U: AsRef<OsStr>,
|
||||
{
|
||||
self.env(key, val);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue