aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock55
-rw-r--r--components/canvas/canvas_data.rs35
-rw-r--r--components/canvas/canvas_paint_thread.rs43
-rw-r--r--components/canvas/webgl_thread.rs8
-rw-r--r--components/canvas_traits/lib.rs2
-rw-r--r--components/compositing/Cargo.toml1
-rw-r--r--components/compositing/compositor.rs161
-rw-r--r--components/compositing/compositor_thread.rs29
-rw-r--r--components/constellation/constellation.rs148
-rw-r--r--components/constellation/pipeline.rs1
-rw-r--r--components/gfx/font_cache_thread.rs42
-rw-r--r--components/gfx_traits/Cargo.toml2
-rw-r--r--components/gfx_traits/lib.rs14
-rw-r--r--components/layout/display_list/builder.rs10
-rw-r--r--components/layout/display_list/items.rs6
-rw-r--r--components/layout/display_list/webrender_helpers.rs10
-rw-r--r--components/layout/flow.rs20
-rw-r--r--components/layout/fragment.rs6
-rw-r--r--components/layout/inline.rs5
-rw-r--r--components/layout/traversal.rs4
-rw-r--r--components/layout_2020/display_list/stacking_context.rs30
-rw-r--r--components/layout_2020/flow/inline.rs4
-rw-r--r--components/layout_2020/flow/mod.rs6
-rw-r--r--components/layout_thread/lib.rs20
-rw-r--r--components/layout_thread_2020/lib.rs20
-rw-r--r--components/layout_traits/lib.rs1
-rw-r--r--components/net/connector.rs114
-rw-r--r--components/net/fetch/methods.rs58
-rw-r--r--components/net/http_loader.rs20
-rw-r--r--components/net/resource_thread.rs30
-rw-r--r--components/net/tests/fetch.rs95
-rw-r--r--components/net/tests/main.rs9
-rw-r--r--components/net/websocket_loader.rs15
-rw-r--r--components/net_traits/Cargo.toml1
-rw-r--r--components/net_traits/lib.rs16
-rw-r--r--components/net_traits/request.rs6
-rw-r--r--components/script/dom/htmlmediaelement.rs10
-rw-r--r--components/script/dom/servoparser/mod.rs12
-rw-r--r--components/script/dom/webidls/XMLHttpRequest.webidl7
-rw-r--r--components/script/dom/xmlhttprequest.rs40
-rw-r--r--components/script_traits/lib.rs38
-rw-r--r--components/servo/Cargo.toml2
-rw-r--r--components/servo/lib.rs69
-rw-r--r--resources/badcert.html22
-rw-r--r--resources/servo.css4
-rw-r--r--servo-tidy.toml1
-rw-r--r--tests/wpt/metadata/MANIFEST.json40
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-animation.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-interposed.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-hidden-and-border-radius.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-scroll.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-with-transparent-pixels.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blending-with-sibling.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-both-parent-and-blended-with-3D-transform.html.ini3
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-canvas-parent.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-canvas-sibling.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-iframe-parent.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-iframe-sibling.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-image.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-intermediate-element-overflow-hidden-and-border-radius.html.ini1
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-mask.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-overflowing-child-of-blended-element.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-overflowing-child.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-element-overflow-scroll-blended-position-fixed.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-element-overflow-scroll.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-3D-transform.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-border-radius.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-text.html.ini3
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-script.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-sibling-with-3D-transform.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-simple.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-stacking-context-creates-isolation.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-with-transform-and-preserve-3D.html.ini2
-rw-r--r--tests/wpt/metadata/css/compositing/root-element-blend-mode.html.ini2
-rw-r--r--tests/wpt/mozilla/meta/MANIFEST.json17
-rw-r--r--tests/wpt/mozilla/meta/css/inline_block_baseline_a.html.ini3
-rw-r--r--tests/wpt/mozilla/tests/css/stacking-context-empty-ref.html1
-rw-r--r--tests/wpt/mozilla/tests/css/stacking-context-empty.html14
-rw-r--r--tests/wpt/web-platform-tests/xhr/send-data-es-object.any.js1
-rw-r--r--tests/wpt/web-platform-tests/xhr/send-data-readablestream.any.js27
-rw-r--r--tests/wpt/web-platform-tests/xhr/setrequestheader-content-type.htm18
81 files changed, 926 insertions, 502 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2ef3a70babd..59001b76b45 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -413,9 +413,9 @@ dependencies = [
[[package]]
name = "brotli-decompressor"
-version = "2.3.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a9f2b517b96b19d8f91c1ff5b1cf498e688850b32eae5d58e02d15c4d4fdc0c"
+checksum = "1052e1c3b8d4d80eb84a8b94f0a1498797b5fb96314c001156a1c761940ef4ec"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
@@ -755,6 +755,7 @@ dependencies = [
name = "compositing"
version = "0.0.1"
dependencies = [
+ "app_units",
"canvas",
"crossbeam-channel",
"embedder_traits",
@@ -1637,9 +1638,12 @@ checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc"
[[package]]
name = "futures-task"
-version = "0.3.4"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27"
+checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626"
+dependencies = [
+ "once_cell",
+]
[[package]]
name = "futures-util"
@@ -1892,10 +1896,12 @@ dependencies = [
name = "gfx_traits"
version = "0.0.1"
dependencies = [
+ "app_units",
"malloc_size_of",
"malloc_size_of_derive",
"range",
"serde",
+ "webrender_api",
]
[[package]]
@@ -3018,6 +3024,7 @@ dependencies = [
name = "libservo"
version = "0.0.1"
dependencies = [
+ "app_units",
"background_hang_monitor",
"bluetooth",
"bluetooth_traits",
@@ -3034,6 +3041,7 @@ dependencies = [
"euclid",
"gaol",
"gfx",
+ "gfx_traits",
"gleam 0.11.0",
"gstreamer",
"ipc-channel",
@@ -3606,6 +3614,7 @@ dependencies = [
"pixels",
"serde",
"servo_arc",
+ "servo_rand",
"servo_url",
"std_test_override",
"time",
@@ -3616,12 +3625,9 @@ dependencies = [
[[package]]
name = "new_debug_unreachable"
-version = "1.0.1"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
-dependencies = [
- "unreachable",
-]
+checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]]
name = "nix"
@@ -3758,6 +3764,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2"
[[package]]
+name = "once_cell"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
+
+[[package]]
name = "opaque-debug"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3928,7 +3940,7 @@ dependencies = [
[[package]]
name = "peek-poke"
version = "0.2.0"
-source = "git+https://github.com/servo/webrender#01082a9091ab98c392af8934d04271eb1dd546df"
+source = "git+https://github.com/servo/webrender#de3999583ab20aad7c57ea35a3e0394ed45be627"
dependencies = [
"euclid",
"peek-poke-derive 0.2.1 (git+https://github.com/servo/webrender)",
@@ -3946,7 +3958,7 @@ dependencies = [
[[package]]
name = "peek-poke-derive"
version = "0.2.1"
-source = "git+https://github.com/servo/webrender#01082a9091ab98c392af8934d04271eb1dd546df"
+source = "git+https://github.com/servo/webrender#de3999583ab20aad7c57ea35a3e0394ed45be627"
dependencies = [
"proc-macro2 1.0.17",
"quote 1.0.2",
@@ -4413,15 +4425,6 @@ checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
[[package]]
name = "ron"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "ron"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5"
@@ -6401,7 +6404,7 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.61.0"
-source = "git+https://github.com/servo/webrender#01082a9091ab98c392af8934d04271eb1dd546df"
+source = "git+https://github.com/servo/webrender#de3999583ab20aad7c57ea35a3e0394ed45be627"
dependencies = [
"base64 0.10.1",
"bincode",
@@ -6427,7 +6430,7 @@ dependencies = [
"num-traits",
"plane-split",
"rayon",
- "ron 0.1.7",
+ "ron",
"serde",
"serde_json",
"smallvec 1.3.0",
@@ -6443,7 +6446,7 @@ dependencies = [
[[package]]
name = "webrender_api"
version = "0.61.0"
-source = "git+https://github.com/servo/webrender#01082a9091ab98c392af8934d04271eb1dd546df"
+source = "git+https://github.com/servo/webrender#de3999583ab20aad7c57ea35a3e0394ed45be627"
dependencies = [
"app_units",
"bitflags",
@@ -6464,7 +6467,7 @@ dependencies = [
[[package]]
name = "webrender_build"
version = "0.0.1"
-source = "git+https://github.com/servo/webrender#01082a9091ab98c392af8934d04271eb1dd546df"
+source = "git+https://github.com/servo/webrender#de3999583ab20aad7c57ea35a3e0394ed45be627"
dependencies = [
"bitflags",
"lazy_static",
@@ -6544,7 +6547,7 @@ dependencies = [
"naga",
"parking_lot 0.10.2",
"peek-poke 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "ron 0.5.1",
+ "ron",
"serde",
"smallvec 1.3.0",
"spirv_headers",
@@ -6644,7 +6647,7 @@ dependencies = [
[[package]]
name = "wr_malloc_size_of"
version = "0.0.1"
-source = "git+https://github.com/servo/webrender#01082a9091ab98c392af8934d04271eb1dd546df"
+source = "git+https://github.com/servo/webrender#de3999583ab20aad7c57ea35a3e0394ed45be627"
dependencies = [
"app_units",
"euclid",
diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs
index 9c3aae1d0be..1a4d1ccfc98 100644
--- a/components/canvas/canvas_data.rs
+++ b/components/canvas/canvas_data.rs
@@ -2,7 +2,7 @@
* 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 crate::canvas_paint_thread::AntialiasMode;
+use crate::canvas_paint_thread::{AntialiasMode, ImageUpdate, WebrenderApi};
use crate::raqote_backend::Repetition;
use canvas_traits::canvas::*;
use cssparser::RGBA;
@@ -13,7 +13,6 @@ use num_traits::ToPrimitive;
use std::marker::PhantomData;
use std::mem;
use std::sync::Arc;
-use webrender::api::DirtyRect;
use webrender_api::units::RectExt as RectExt_;
/// The canvas data stores a state machine for the current status of
@@ -367,8 +366,7 @@ pub struct CanvasData<'a> {
path_state: Option<PathState>,
state: CanvasPaintState<'a>,
saved_states: Vec<CanvasPaintState<'a>>,
- webrender_api: webrender_api::RenderApi,
- webrender_doc: webrender_api::DocumentId,
+ webrender_api: Box<dyn WebrenderApi>,
image_key: Option<webrender_api::ImageKey>,
/// An old webrender image key that can be deleted when the next epoch ends.
old_image_key: Option<webrender_api::ImageKey>,
@@ -384,22 +382,19 @@ fn create_backend() -> Box<dyn Backend> {
impl<'a> CanvasData<'a> {
pub fn new(
size: Size2D<u64>,
- webrender_api_sender: webrender_api::RenderApiSender,
- webrender_doc: webrender_api::DocumentId,
+ webrender_api: Box<dyn WebrenderApi>,
antialias: AntialiasMode,
canvas_id: CanvasId,
) -> CanvasData<'a> {
let backend = create_backend();
let draw_target = backend.create_drawtarget(size);
- let webrender_api = webrender_api_sender.create_api();
CanvasData {
backend,
drawtarget: draw_target,
path_state: None,
state: CanvasPaintState::new(antialias),
saved_states: vec![],
- webrender_api: webrender_api,
- webrender_doc,
+ webrender_api,
image_key: None,
old_image_key: None,
very_old_image_key: None,
@@ -979,27 +974,28 @@ impl<'a> CanvasData<'a> {
let data = self.drawtarget.snapshot_data_owned();
let data = webrender_api::ImageData::Raw(Arc::new(data));
- let mut txn = webrender_api::Transaction::new();
+ let mut updates = vec![];
match self.image_key {
Some(image_key) => {
debug!("Updating image {:?}.", image_key);
- txn.update_image(image_key, descriptor, data, &DirtyRect::All);
+ updates.push(ImageUpdate::Update(image_key, descriptor, data));
},
None => {
- self.image_key = Some(self.webrender_api.generate_image_key());
+ let key = self.webrender_api.generate_key();
+ updates.push(ImageUpdate::Add(key, descriptor, data));
+ self.image_key = Some(key);
debug!("New image {:?}.", self.image_key);
- txn.add_image(self.image_key.unwrap(), descriptor, data, None);
},
}
if let Some(image_key) =
mem::replace(&mut self.very_old_image_key, self.old_image_key.take())
{
- txn.delete_image(image_key);
+ updates.push(ImageUpdate::Delete(image_key));
}
- self.webrender_api.send_transaction(self.webrender_doc, txn);
+ self.webrender_api.update_images(updates);
let data = CanvasImageData {
image_key: self.image_key.unwrap(),
@@ -1110,16 +1106,15 @@ impl<'a> CanvasData<'a> {
impl<'a> Drop for CanvasData<'a> {
fn drop(&mut self) {
- let mut txn = webrender_api::Transaction::new();
-
+ let mut updates = vec![];
if let Some(image_key) = self.old_image_key.take() {
- txn.delete_image(image_key);
+ updates.push(ImageUpdate::Delete(image_key));
}
if let Some(image_key) = self.very_old_image_key.take() {
- txn.delete_image(image_key);
+ updates.push(ImageUpdate::Delete(image_key));
}
- self.webrender_api.send_transaction(self.webrender_doc, txn);
+ self.webrender_api.update_images(updates);
}
}
diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs
index f73d8f7b9a8..6832a5cddc8 100644
--- a/components/canvas/canvas_paint_thread.rs
+++ b/components/canvas/canvas_paint_thread.rs
@@ -12,35 +12,52 @@ use ipc_channel::router::ROUTER;
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::thread;
+use webrender_api::{ImageData, ImageDescriptor, ImageKey};
pub enum AntialiasMode {
Default,
None,
}
+pub enum ImageUpdate {
+ Add(ImageKey, ImageDescriptor, ImageData),
+ Update(ImageKey, ImageDescriptor, ImageData),
+ Delete(ImageKey),
+}
+
+pub trait WebrenderApi {
+ fn generate_key(&self) -> webrender_api::ImageKey;
+ fn update_images(&self, updates: Vec<ImageUpdate>);
+ fn clone(&self) -> Box<dyn WebrenderApi>;
+}
+
pub struct CanvasPaintThread<'a> {
canvases: HashMap<CanvasId, CanvasData<'a>>,
next_canvas_id: CanvasId,
+ webrender_api: Box<dyn WebrenderApi>,
}
impl<'a> CanvasPaintThread<'a> {
- fn new() -> CanvasPaintThread<'a> {
+ fn new(webrender_api: Box<dyn WebrenderApi>) -> CanvasPaintThread<'a> {
CanvasPaintThread {
canvases: HashMap::new(),
next_canvas_id: CanvasId(0),
+ webrender_api,
}
}
/// Creates a new `CanvasPaintThread` and returns an `IpcSender` to
/// communicate with it.
- pub fn start() -> (Sender<ConstellationCanvasMsg>, IpcSender<CanvasMsg>) {
+ pub fn start(
+ webrender_api: Box<dyn WebrenderApi + Send>,
+ ) -> (Sender<ConstellationCanvasMsg>, IpcSender<CanvasMsg>) {
let (ipc_sender, ipc_receiver) = ipc::channel::<CanvasMsg>().unwrap();
let msg_receiver = ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(ipc_receiver);
let (create_sender, create_receiver) = unbounded();
thread::Builder::new()
.name("CanvasThread".to_owned())
.spawn(move || {
- let mut canvas_paint_thread = CanvasPaintThread::new();
+ let mut canvas_paint_thread = CanvasPaintThread::new(webrender_api);
loop {
select! {
recv(msg_receiver) -> msg => {
@@ -74,16 +91,9 @@ impl<'a> CanvasPaintThread<'a> {
Ok(ConstellationCanvasMsg::Create {
id_sender: creator,
size,
- webrender_sender: webrenderer_api_sender,
- webrender_doc,
antialias
}) => {
- let canvas_id = canvas_paint_thread.create_canvas(
- size,
- webrenderer_api_sender,
- webrender_doc,
- antialias,
- );
+ let canvas_id = canvas_paint_thread.create_canvas(size, antialias);
creator.send(canvas_id).unwrap();
},
Ok(ConstellationCanvasMsg::Exit) => break,
@@ -101,13 +111,7 @@ impl<'a> CanvasPaintThread<'a> {
(create_sender, ipc_sender)
}
- pub fn create_canvas(
- &mut self,
- size: Size2D<u64>,
- webrender_api_sender: webrender_api::RenderApiSender,
- webrender_doc: webrender_api::DocumentId,
- antialias: bool,
- ) -> CanvasId {
+ pub fn create_canvas(&mut self, size: Size2D<u64>, antialias: bool) -> CanvasId {
let antialias = if antialias {
AntialiasMode::Default
} else {
@@ -119,8 +123,7 @@ impl<'a> CanvasPaintThread<'a> {
let canvas_data = CanvasData::new(
size,
- webrender_api_sender,
- webrender_doc,
+ self.webrender_api.clone(),
antialias,
canvas_id.clone(),
);
diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs
index 9b7b4ed4683..0d8bc69cb77 100644
--- a/components/canvas/webgl_thread.rs
+++ b/components/canvas/webgl_thread.rs
@@ -655,7 +655,7 @@ impl WebGLThread {
);
let image_key = Self::create_wr_external_image(
- &self.webrender_api,
+ &mut self.webrender_api,
self.webrender_doc,
size.to_i32(),
has_alpha,
@@ -718,7 +718,7 @@ impl WebGLThread {
.contains(ContextAttributeFlags::ALPHA);
let texture_target = current_wr_texture_target(&self.device);
Self::update_wr_external_image(
- &self.webrender_api,
+ &mut self.webrender_api,
self.webrender_doc,
size.to_i32(),
has_alpha,
@@ -1021,7 +1021,7 @@ impl WebGLThread {
/// Creates a `webrender_api::ImageKey` that uses shared textures.
fn create_wr_external_image(
- webrender_api: &webrender_api::RenderApi,
+ webrender_api: &mut webrender_api::RenderApi,
webrender_doc: webrender_api::DocumentId,
size: Size2D<i32>,
alpha: bool,
@@ -1041,7 +1041,7 @@ impl WebGLThread {
/// Updates a `webrender_api::ImageKey` that uses shared textures.
fn update_wr_external_image(
- webrender_api: &webrender_api::RenderApi,
+ webrender_api: &mut webrender_api::RenderApi,
webrender_doc: webrender_api::DocumentId,
size: Size2D<i32>,
alpha: bool,
diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs
index ec510e6281d..467eb432e0f 100644
--- a/components/canvas_traits/lib.rs
+++ b/components/canvas_traits/lib.rs
@@ -26,8 +26,6 @@ pub enum ConstellationCanvasMsg {
Create {
id_sender: Sender<CanvasId>,
size: Size2D<u64>,
- webrender_sender: webrender_api::RenderApiSender,
- webrender_doc: webrender_api::DocumentId,
antialias: bool,
},
Exit,
diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml
index 027d16233bf..97419f37752 100644
--- a/components/compositing/Cargo.toml
+++ b/components/compositing/Cargo.toml
@@ -16,6 +16,7 @@ default = []
gl = ["gleam", "pixels"]
[dependencies]
+app_units = "0.7"
canvas = { path = "../canvas" }
crossbeam-channel = "0.4"
embedder_traits = { path = "../embedder_traits" }
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index c3c545af4bb..f1f0149ec6b 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -3,7 +3,9 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::compositor_thread::CompositorReceiver;
-use crate::compositor_thread::{InitialCompositorState, Msg};
+use crate::compositor_thread::{
+ InitialCompositorState, Msg, WebrenderCanvasMsg, WebrenderFontMsg, WebrenderMsg,
+};
#[cfg(feature = "gl")]
use crate::gl;
use crate::touch::{TouchAction, TouchHandler};
@@ -11,10 +13,11 @@ use crate::windowing::{
self, EmbedderCoordinates, MouseWindowEvent, WebRenderDebugOption, WindowMethods,
};
use crate::{CompositionPipeline, ConstellationMsg, SendableFrameTree};
+use canvas::canvas_paint_thread::ImageUpdate;
use crossbeam_channel::Sender;
use embedder_traits::Cursor;
use euclid::{Point2D, Rect, Scale, Vector2D};
-use gfx_traits::Epoch;
+use gfx_traits::{Epoch, FontData};
#[cfg(feature = "gl")]
use image::{DynamicImage, ImageFormat};
use ipc_channel::ipc;
@@ -40,8 +43,6 @@ use std::fs::{create_dir_all, File};
use std::io::Write;
use std::num::NonZeroU32;
use std::rc::Rc;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::Arc;
use style_traits::viewport::ViewportConstraints;
use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
use time::{now, precise_time_ns, precise_time_s};
@@ -218,7 +219,7 @@ pub struct IOCompositor<Window: WindowMethods + ?Sized> {
/// True if a WR frame render has been requested. Screenshots
/// taken before the render is complete will not reflect the
/// most up to date rendering.
- waiting_on_pending_frame: Arc<AtomicBool>,
+ waiting_on_pending_frame: bool,
}
#[derive(Clone, Copy)]
@@ -334,7 +335,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
is_running_problem_test,
exit_after_load,
convert_mouse_to_touch,
- waiting_on_pending_frame: state.pending_wr_frame,
+ waiting_on_pending_frame: false,
}
}
@@ -443,7 +444,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
},
(Msg::Recomposite(reason), ShutdownState::NotShuttingDown) => {
- self.waiting_on_pending_frame.store(false, Ordering::SeqCst);
+ self.waiting_on_pending_frame = false;
self.composition_request = CompositionRequest::CompositeNow(reason)
},
@@ -474,7 +475,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
self.ready_to_save_state,
ReadyState::WaitingForConstellationReply
);
- if is_ready && !self.waiting_on_pending_frame.load(Ordering::SeqCst) {
+ if is_ready && !self.waiting_on_pending_frame {
self.ready_to_save_state = ReadyState::ReadyToSaveImage;
if self.is_running_problem_test {
println!("ready to save image!");
@@ -569,6 +570,10 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
}
},
+ (Msg::Webrender(msg), ShutdownState::NotShuttingDown) => {
+ self.handle_webrender_message(msg);
+ },
+
// When we are shutting_down, we need to avoid performing operations
// such as Paint that may crash because we have begun tearing down
// the rest of our resources.
@@ -578,6 +583,146 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
true
}
+ /// Accept messages from content processes that need to be relayed to the WebRender
+ /// instance in the parent process.
+ fn handle_webrender_message(&mut self, msg: WebrenderMsg) {
+ match msg {
+ WebrenderMsg::Layout(script_traits::WebrenderMsg::SendInitialTransaction(pipeline)) => {
+ self.waiting_on_pending_frame = true;
+ let mut txn = webrender_api::Transaction::new();
+ txn.set_display_list(
+ webrender_api::Epoch(0),
+ None,
+ Default::default(),
+ (pipeline, Default::default(), Default::default()),
+ false,
+ );
+ self.webrender_api
+ .send_transaction(self.webrender_document, txn);
+ },
+
+ WebrenderMsg::Layout(script_traits::WebrenderMsg::SendScrollNode(
+ point,
+ scroll_id,
+ clamping,
+ )) => {
+ let mut txn = webrender_api::Transaction::new();
+ txn.scroll_node_with_id(point, scroll_id, clamping);
+ self.webrender_api
+ .send_transaction(self.webrender_document, txn);
+ },
+
+ WebrenderMsg::Layout(script_traits::WebrenderMsg::SendDisplayList(
+ epoch,
+ size,
+ pipeline,
+ size2,
+ data,
+ descriptor,
+ )) => {
+ self.waiting_on_pending_frame = true;
+ let mut txn = webrender_api::Transaction::new();
+ txn.set_display_list(
+ epoch,
+ None,
+ size,
+ (
+ pipeline,
+ size2,
+ webrender_api::BuiltDisplayList::from_data(data, descriptor),
+ ),
+ true,
+ );
+ txn.generate_frame();
+ self.webrender_api
+ .send_transaction(self.webrender_document, txn);
+ },
+
+ WebrenderMsg::Layout(script_traits::WebrenderMsg::HitTest(
+ pipeline,
+ point,
+ flags,
+ sender,
+ )) => {
+ let result =
+ self.webrender_api
+ .hit_test(self.webrender_document, pipeline, point, flags);
+ let _ = sender.send(result);
+ },
+
+ WebrenderMsg::Layout(script_traits::WebrenderMsg::GenerateImageKey(sender)) |
+ WebrenderMsg::Net(net_traits::WebrenderImageMsg::GenerateImageKey(sender)) => {
+ let _ = sender.send(self.webrender_api.generate_image_key());
+ },
+
+ WebrenderMsg::Layout(script_traits::WebrenderMsg::UpdateImages(updates)) => {
+ let mut txn = webrender_api::Transaction::new();
+ for update in updates {
+ match update {
+ script_traits::ImageUpdate::AddImage(key, desc, data) => {
+ txn.add_image(key, desc, data, None)
+ },
+ script_traits::ImageUpdate::DeleteImage(key) => txn.delete_image(key),
+ script_traits::ImageUpdate::UpdateImage(key, desc, data) => {
+ txn.update_image(key, desc, data, &webrender_api::DirtyRect::All)
+ },
+ }
+ }
+ self.webrender_api
+ .send_transaction(self.webrender_document, txn);
+ },
+
+ WebrenderMsg::Net(net_traits::WebrenderImageMsg::AddImage(key, desc, data)) => {
+ let mut txn = webrender_api::Transaction::new();
+ txn.add_image(key, desc, data, None);
+ self.webrender_api
+ .send_transaction(self.webrender_document, txn);
+ },
+
+ WebrenderMsg::Font(WebrenderFontMsg::AddFontInstance(font_key, size, sender)) => {
+ let key = self.webrender_api.generate_font_instance_key();
+ let mut txn = webrender_api::Transaction::new();
+ txn.add_font_instance(key, font_key, size, None, None, Vec::new());
+ self.webrender_api
+ .send_transaction(self.webrender_document, txn);
+ let _ = sender.send(key);
+ },
+
+ WebrenderMsg::Font(WebrenderFontMsg::AddFont(data, sender)) => {
+ let font_key = self.webrender_api.generate_font_key();
+ let mut txn = webrender_api::Transaction::new();
+ match data {
+ FontData::Raw(bytes) => txn.add_raw_font(font_key, bytes, 0),
+ FontData::Native(native_font) => txn.add_native_font(font_key, native_font),
+ }
+ self.webrender_api
+ .send_transaction(self.webrender_document, txn);
+ let _ = sender.send(font_key);
+ },
+
+ WebrenderMsg::Canvas(WebrenderCanvasMsg::GenerateKey(sender)) => {
+ let _ = sender.send(self.webrender_api.generate_image_key());
+ },
+
+ WebrenderMsg::Canvas(WebrenderCanvasMsg::UpdateImages(updates)) => {
+ let mut txn = webrender_api::Transaction::new();
+ for update in updates {
+ match update {
+ ImageUpdate::Add(key, descriptor, data) => {
+ txn.add_image(key, descriptor, data, None)
+ },
+ ImageUpdate::Update(key, descriptor, data) => {
+ txn.update_image(key, descriptor, data, &webrender_api::DirtyRect::All)
+ },
+ ImageUpdate::Delete(key) => txn.delete_image(key),
+ }
+ }
+ self.webrender_api
+ .send_transaction(self.webrender_document, txn);
+ },
+ }
+ }
+
/// Sets or unsets the animations-running flag for the given pipeline, and schedules a
/// recomposite if necessary.
fn change_running_animations_state(
diff --git a/components/compositing/compositor_thread.rs b/components/compositing/compositor_thread.rs
index cbd715af0dd..01fb92a544e 100644
--- a/components/compositing/compositor_thread.rs
+++ b/components/compositing/compositor_thread.rs
@@ -6,6 +6,7 @@
use crate::compositor::CompositingReason;
use crate::{ConstellationMsg, SendableFrameTree};
+use canvas::canvas_paint_thread::ImageUpdate;
use crossbeam_channel::{Receiver, Sender};
use embedder_traits::EventLoopWaker;
use euclid::Rect;
@@ -18,8 +19,6 @@ use profile_traits::time;
use script_traits::{AnimationState, EventResult, MouseButton, MouseEventType};
use std::fmt::{Debug, Error, Formatter};
use std::rc::Rc;
-use std::sync::atomic::AtomicBool;
-use std::sync::Arc;
use style_traits::viewport::ViewportConstraints;
use style_traits::CSSPixel;
use webrender_api;
@@ -122,6 +121,30 @@ pub enum Msg {
GetScreenSize(IpcSender<DeviceIntSize>),
/// Get screen available size.
GetScreenAvailSize(IpcSender<DeviceIntSize>),
+
+ /// Webrender operations requested from non-compositor threads.
+ Webrender(WebrenderMsg),
+}
+
+pub enum WebrenderFontMsg {
+ AddFontInstance(
+ webrender_api::FontKey,
+ app_units::Au,
+ Sender<webrender_api::FontInstanceKey>,
+ ),
+ AddFont(gfx_traits::FontData, Sender<webrender_api::FontKey>),
+}
+
+pub enum WebrenderCanvasMsg {
+ GenerateKey(Sender<webrender_api::ImageKey>),
+ UpdateImages(Vec<ImageUpdate>),
+}
+
+pub enum WebrenderMsg {
+ Layout(script_traits::WebrenderMsg),
+ Net(net_traits::WebrenderImageMsg),
+ Font(WebrenderFontMsg),
+ Canvas(WebrenderCanvasMsg),
}
impl Debug for Msg {
@@ -148,6 +171,7 @@ impl Debug for Msg {
Msg::GetClientWindow(..) => write!(f, "GetClientWindow"),
Msg::GetScreenSize(..) => write!(f, "GetScreenSize"),
Msg::GetScreenAvailSize(..) => write!(f, "GetScreenAvailSize"),
+ Msg::Webrender(..) => write!(f, "Webrender"),
}
}
}
@@ -171,5 +195,4 @@ pub struct InitialCompositorState {
pub webrender_surfman: WebrenderSurfman,
pub webrender_gl: Rc<dyn gleam::gl::Gl>,
pub webxr_main_thread: webxr::MainThreadRegistry,
- pub pending_wr_frame: Arc<AtomicBool>,
}
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index d7408ac549e..1ea79bc3209 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -109,6 +109,7 @@ use canvas_traits::webgl::WebGLThreads;
use canvas_traits::ConstellationCanvasMsg;
use compositing::compositor_thread::CompositorProxy;
use compositing::compositor_thread::Msg as ToCompositorMsg;
+use compositing::compositor_thread::WebrenderMsg;
use compositing::{ConstellationMsg as FromCompositorMsg, SendableFrameTree};
use crossbeam_channel::{after, never, unbounded, Receiver, Sender};
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg};
@@ -171,7 +172,6 @@ use std::marker::PhantomData;
use std::mem::replace;
use std::process;
use std::rc::{Rc, Weak};
-use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
use style_traits::viewport::ViewportConstraints;
@@ -384,10 +384,6 @@ pub struct Constellation<Message, LTF, STF, SWF> {
/// A single WebRender document the constellation operates on.
webrender_document: webrender_api::DocumentId,
- /// A channel for the constellation to send messages to the
- /// WebRender thread.
- webrender_api_sender: webrender_api::RenderApiSender,
-
/// A channel for content processes to send messages that will
/// be relayed to the WebRender thread.
webrender_api_ipc_sender: script_traits::WebrenderIpcSender,
@@ -537,9 +533,6 @@ pub struct InitialConstellationState {
/// Webrender document ID.
pub webrender_document: webrender_api::DocumentId,
- /// Webrender API.
- pub webrender_api_sender: webrender_api::RenderApiSender,
-
/// Entry point to create and get channels to a WebGLThread.
pub webgl_threads: Option<WebGLThreads>,
@@ -554,9 +547,6 @@ pub struct InitialConstellationState {
/// Mechanism to force the compositor to process events.
pub event_loop_waker: Option<Box<dyn EventLoopWaker>>,
- /// A flag share with the compositor to indicate that a WR frame is in progress.
- pub pending_wr_frame: Arc<AtomicBool>,
-
/// User agent string to report in network requests.
pub user_agent: Cow<'static, str>,
}
@@ -726,113 +716,6 @@ where
mpsc_receiver
}
-enum WebrenderMsg {
- Layout(script_traits::WebrenderMsg),
- Net(net_traits::WebrenderImageMsg),
-}
-
-/// Accept messages from content processes that need to be relayed to the WebRender
-/// instance in the parent process.
-fn handle_webrender_message(
- pending_wr_frame: &AtomicBool,
- webrender_api: &webrender_api::RenderApi,
- webrender_doc: webrender_api::DocumentId,
- msg: WebrenderMsg,
-) {
- match msg {
- WebrenderMsg::Layout(script_traits::WebrenderMsg::SendInitialTransaction(
- doc,
- pipeline,
- )) => {
- pending_wr_frame.store(true, Ordering::SeqCst);
- let mut txn = webrender_api::Transaction::new();
- txn.set_display_list(
- webrender_api::Epoch(0),
- None,
- Default::default(),
- (pipeline, Default::default(), Default::default()),
- false,
- );
- webrender_api.send_transaction(doc, txn);
- },
-
- WebrenderMsg::Layout(script_traits::WebrenderMsg::SendScrollNode(
- doc,
- point,
- scroll_id,
- clamping,
- )) => {
- let mut txn = webrender_api::Transaction::new();
- txn.scroll_node_with_id(point, scroll_id, clamping);
- webrender_api.send_transaction(doc, txn);
- },
-
- WebrenderMsg::Layout(script_traits::WebrenderMsg::SendDisplayList(
- doc,
- epoch,
- size,
- pipeline,
- size2,
- data,
- descriptor,
- )) => {
- pending_wr_frame.store(true, Ordering::SeqCst);
- let mut txn = webrender_api::Transaction::new();
- txn.set_display_list(
- epoch,
- None,
- size,
- (
- pipeline,
- size2,
- webrender_api::BuiltDisplayList::from_data(data, descriptor),
- ),
- true,
- );
- txn.generate_frame();
- webrender_api.send_transaction(doc, txn);
- },
-
- WebrenderMsg::Layout(script_traits::WebrenderMsg::HitTest(
- doc,
- pipeline,
- point,
- flags,
- sender,
- )) => {
- let result = webrender_api.hit_test(doc, pipeline, point, flags);
- let _ = sender.send(result);
- },
-
- WebrenderMsg::Layout(script_traits::WebrenderMsg::GenerateImageKey(sender)) |
- WebrenderMsg::Net(net_traits::WebrenderImageMsg::GenerateImageKey(sender)) => {
- let _ = sender.send(webrender_api.generate_image_key());
- },
-
- WebrenderMsg::Layout(script_traits::WebrenderMsg::UpdateImages(updates)) => {
- let mut txn = webrender_api::Transaction::new();
- for update in updates {
- match update {
- script_traits::ImageUpdate::AddImage(key, desc, data) => {
- txn.add_image(key, desc, data, None)
- },
- script_traits::ImageUpdate::DeleteImage(key) => txn.delete_image(key),
- script_traits::ImageUpdate::UpdateImage(key, desc, data) => {
- txn.update_image(key, desc, data, &webrender_api::DirtyRect::All)
- },
- }
- }
- webrender_api.send_transaction(webrender_doc, txn);
- },
-
- WebrenderMsg::Net(net_traits::WebrenderImageMsg::AddImage(key, desc, data)) => {
- let mut txn = webrender_api::Transaction::new();
- txn.add_image(key, desc, data, None);
- webrender_api.send_transaction(webrender_doc, txn);
- },
- }
-}
-
impl<Message, LTF, STF, SWF> Constellation<Message, LTF, STF, SWF>
where
LTF: LayoutThreadFactory<Message = Message>,
@@ -931,32 +814,23 @@ where
let (webrender_image_ipc_sender, webrender_image_ipc_receiver) =
ipc::channel().expect("ipc channel failure");
- let webrender_api = state.webrender_api_sender.create_api();
- let webrender_doc = state.webrender_document;
- let pending_wr_frame_clone = state.pending_wr_frame.clone();
+ let compositor_proxy = state.compositor_proxy.clone();
ROUTER.add_route(
webrender_ipc_receiver.to_opaque(),
Box::new(move |message| {
- handle_webrender_message(
- &pending_wr_frame_clone,
- &webrender_api,
- webrender_doc,
+ let _ = compositor_proxy.send(ToCompositorMsg::Webrender(
WebrenderMsg::Layout(message.to().expect("conversion failure")),
- )
+ ));
}),
);
- let webrender_api = state.webrender_api_sender.create_api();
- let pending_wr_frame_clone = state.pending_wr_frame.clone();
+ let compositor_proxy = state.compositor_proxy.clone();
ROUTER.add_route(
webrender_image_ipc_receiver.to_opaque(),
Box::new(move |message| {
- handle_webrender_message(
- &pending_wr_frame_clone,
- &webrender_api,
- webrender_doc,
+ let _ = compositor_proxy.send(ToCompositorMsg::Webrender(
WebrenderMsg::Net(message.to().expect("conversion failure")),
- )
+ ));
}),
);
@@ -1009,7 +883,6 @@ where
scheduler_receiver,
document_states: HashMap::new(),
webrender_document: state.webrender_document,
- webrender_api_sender: state.webrender_api_sender,
webrender_api_ipc_sender: script_traits::WebrenderIpcSender::new(
webrender_ipc_sender,
),
@@ -1474,10 +1347,10 @@ where
))
}
recv(self.swmanager_receiver) -> msg => {
- msg.expect("Unexpected panic channel panic in constellation").map(Request::FromSWManager)
+ msg.expect("Unexpected SW channel panic in constellation").map(Request::FromSWManager)
}
recv(self.scheduler_receiver) -> msg => {
- msg.expect("Unexpected panic channel panic in constellation").map(Request::Timer)
+ msg.expect("Unexpected schedule channel panic in constellation").map(Request::Timer)
}
recv(scheduler_timeout) -> _ => {
// Note: by returning, we go back to the top,
@@ -4386,14 +4259,11 @@ where
size: UntypedSize2D<u64>,
response_sender: IpcSender<(IpcSender<CanvasMsg>, CanvasId)>,
) {
- let webrender_api = self.webrender_api_sender.clone();
let (canvas_id_sender, canvas_id_receiver) = unbounded();
if let Err(e) = self.canvas_chan.send(ConstellationCanvasMsg::Create {
id_sender: canvas_id_sender,
size,
- webrender_sender: webrender_api,
- webrender_doc: self.webrender_document,
antialias: self.enable_canvas_antialiasing,
}) {
return warn!("Create canvas paint thread failed ({})", e);
diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs
index f4c2aefdc73..4fa5d6e2fd9 100644
--- a/components/constellation/pipeline.rs
+++ b/components/constellation/pipeline.rs
@@ -606,7 +606,6 @@ impl UnprivilegedPipelineContent {
self.time_profiler_chan,
self.mem_profiler_chan,
self.webrender_api_sender,
- self.webrender_document,
paint_time_metrics,
layout_thread_busy_flag.clone(),
self.opts.load_webfonts_synchronously,
diff --git a/components/gfx/font_cache_thread.rs b/components/gfx/font_cache_thread.rs
index 48d4c9e2889..45eead2357d 100644
--- a/components/gfx/font_cache_thread.rs
+++ b/components/gfx/font_cache_thread.rs
@@ -12,6 +12,7 @@ use crate::platform::font_list::system_default_family;
use crate::platform::font_list::SANS_SERIF_FONT_FAMILY;
use crate::platform::font_template::FontTemplateData;
use app_units::Au;
+use gfx_traits::{FontData, WebrenderApi};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use net_traits::request::{Destination, RequestBuilder};
use net_traits::{fetch_async, CoreResourceThread, FetchResponseMsg};
@@ -135,9 +136,8 @@ struct FontCache {
web_families: HashMap<LowercaseString, FontTemplates>,
font_context: FontContextHandle,
core_resource_thread: CoreResourceThread,
- webrender_api: webrender_api::RenderApi,
+ webrender_api: Box<dyn WebrenderApi>,
webrender_fonts: HashMap<Atom, webrender_api::FontKey>,
- webrender_doc: webrender_api::DocumentId,
font_instances: HashMap<(webrender_api::FontKey, Au), webrender_api::FontInstanceKey>,
}
@@ -181,19 +181,11 @@ impl FontCache {
},
Command::GetFontInstance(font_key, size, result) => {
let webrender_api = &self.webrender_api;
- let doc = self.webrender_doc;
-
- let instance_key =
- *self
- .font_instances
- .entry((font_key, size))
- .or_insert_with(|| {
- let key = webrender_api.generate_font_instance_key();
- let mut txn = webrender_api::Transaction::new();
- txn.add_font_instance(key, font_key, size, None, None, Vec::new());
- webrender_api.send_transaction(doc, txn);
- key
- });
+
+ let instance_key = *self
+ .font_instances
+ .entry((font_key, size))
+ .or_insert_with(|| webrender_api.add_font_instance(font_key, size));
let _ = result.send(instance_key);
},
@@ -391,21 +383,17 @@ impl FontCache {
fn get_font_template_info(&mut self, template: Arc<FontTemplateData>) -> FontTemplateInfo {
let webrender_api = &self.webrender_api;
- let doc = self.webrender_doc;
let webrender_fonts = &mut self.webrender_fonts;
let font_key = *webrender_fonts
.entry(template.identifier.clone())
.or_insert_with(|| {
- let font_key = webrender_api.generate_font_key();
- let mut txn = webrender_api::Transaction::new();
- match (template.bytes_if_in_memory(), template.native_font()) {
- (Some(bytes), _) => txn.add_raw_font(font_key, bytes, 0),
- (None, Some(native_font)) => txn.add_native_font(font_key, native_font),
- (None, None) => txn.add_raw_font(font_key, template.bytes(), 0),
- }
- webrender_api.send_transaction(doc, txn);
- font_key
+ let font = match (template.bytes_if_in_memory(), template.native_font()) {
+ (Some(bytes), _) => FontData::Raw(bytes),
+ (None, Some(native_font)) => FontData::Native(native_font),
+ (None, None) => FontData::Raw(template.bytes()),
+ };
+ webrender_api.add_font(font)
});
FontTemplateInfo {
@@ -444,8 +432,7 @@ pub struct FontCacheThread {
impl FontCacheThread {
pub fn new(
core_resource_thread: CoreResourceThread,
- webrender_api: webrender_api::RenderApi,
- webrender_doc: webrender_api::DocumentId,
+ webrender_api: Box<dyn WebrenderApi + Send>,
) -> FontCacheThread {
let (chan, port) = ipc::channel().unwrap();
@@ -465,7 +452,6 @@ impl FontCacheThread {
font_context: FontContextHandle::new(),
core_resource_thread,
webrender_api,
- webrender_doc,
webrender_fonts: HashMap::new(),
font_instances: HashMap::new(),
};
diff --git a/components/gfx_traits/Cargo.toml b/components/gfx_traits/Cargo.toml
index ff83cc79406..5d7acdd1b61 100644
--- a/components/gfx_traits/Cargo.toml
+++ b/components/gfx_traits/Cargo.toml
@@ -11,7 +11,9 @@ name = "gfx_traits"
path = "lib.rs"
[dependencies]
+app_units = "0.7"
malloc_size_of = { path = "../malloc_size_of" }
malloc_size_of_derive = "0.1"
range = { path = "../range" }
serde = "1.0"
+webrender_api = { git = "https://github.com/servo/webrender" }
diff --git a/components/gfx_traits/lib.rs b/components/gfx_traits/lib.rs
index 165059c7996..447be6e5dc2 100644
--- a/components/gfx_traits/lib.rs
+++ b/components/gfx_traits/lib.rs
@@ -103,3 +103,17 @@ pub fn node_id_from_scroll_id(id: usize) -> Option<usize> {
}
None
}
+
+pub enum FontData {
+ Raw(Vec<u8>),
+ Native(webrender_api::NativeFontHandle),
+}
+
+pub trait WebrenderApi {
+ fn add_font_instance(
+ &self,
+ font_key: webrender_api::FontKey,
+ size: app_units::Au,
+ ) -> webrender_api::FontInstanceKey;
+ fn add_font(&self, data: FontData) -> webrender_api::FontKey;
+}
diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs
index 9d5f1e100ab..0be8183e2a7 100644
--- a/components/layout/display_list/builder.rs
+++ b/components/layout/display_list/builder.rs
@@ -1571,6 +1571,11 @@ impl Fragment {
return;
}
+ // If this fragment takes up no space, we don't need to build any display items for it.
+ if self.has_non_invertible_transform() {
+ return;
+ }
+
debug!(
"Fragment::build_display_list at rel={:?}, abs={:?}: {:?}",
self.border_box, stacking_relative_border_box, self
@@ -2376,6 +2381,11 @@ impl BlockFlow {
state: &mut StackingContextCollectionState,
flags: StackingContextCollectionFlags,
) {
+ // This block flow produces no stacking contexts if it takes up no space.
+ if self.has_non_invertible_transform() {
+ return;
+ }
+
let mut preserved_state = SavedStackingContextCollectionState::new(state);
let stacking_context_type = self.stacking_context_type(flags);
diff --git a/components/layout/display_list/items.rs b/components/layout/display_list/items.rs
index 27b4ec1fa88..4800abe7e53 100644
--- a/components/layout/display_list/items.rs
+++ b/components/layout/display_list/items.rs
@@ -217,6 +217,12 @@ impl StackingContext {
parent_clipping_and_scrolling: ClippingAndScrolling,
established_reference_frame: Option<ClipScrollNodeIndex>,
) -> StackingContext {
+ if let Some(ref t) = transform {
+ // These are used as scale values by webrender, and it can't handle
+ // divisors of 0 when scaling.
+ assert_ne!(t.m11, 0.);
+ assert_ne!(t.m22, 0.);
+ }
StackingContext {
id,
context_type,
diff --git a/components/layout/display_list/webrender_helpers.rs b/components/layout/display_list/webrender_helpers.rs
index dd187cf3704..9495b2ab166 100644
--- a/components/layout/display_list/webrender_helpers.rs
+++ b/components/layout/display_list/webrender_helpers.rs
@@ -234,6 +234,12 @@ impl DisplayItem {
builder.push_iter(&stacking_context.filters);
}
+ // TODO(jdm): WebRender now requires us to create stacking context items
+ // with the IS_BLEND_CONTAINER flag enabled if any children
+ // of the stacking context have a blend mode applied.
+ // This will require additional tracking during layout
+ // before we start collecting stacking contexts so that
+ // information will be available when we reach this point.
let wr_item = PushStackingContextDisplayItem {
origin: bounds.origin,
spatial_id,
@@ -243,9 +249,7 @@ impl DisplayItem {
mix_blend_mode: stacking_context.mix_blend_mode,
clip_id: None,
raster_space: RasterSpace::Screen,
- // TODO(pcwalton): Enable picture caching?
- cache_tiles: false,
- is_backdrop_root: false,
+ flags: Default::default(),
},
};
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index c2d01b7f9f9..acea20ad4d4 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -273,6 +273,22 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
might_have_floats_in_or_out
}
+ fn has_non_invertible_transform(&self) -> bool {
+ if !self.class().is_block_like() ||
+ self.as_block()
+ .fragment
+ .style
+ .get_box()
+ .transform
+ .0
+ .is_empty()
+ {
+ return false;
+ }
+
+ self.as_block().fragment.has_non_invertible_transform()
+ }
+
fn get_overflow_in_parent_coordinates(&self) -> Overflow {
// FIXME(#2795): Get the real container size.
let container_size = Size2D::zero();
@@ -1160,7 +1176,9 @@ impl BaseFlow {
state: &mut StackingContextCollectionState,
) {
for kid in self.children.iter_mut() {
- kid.collect_stacking_contexts(state);
+ if !kid.has_non_invertible_transform() {
+ kid.collect_stacking_contexts(state);
+ }
}
}
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 062db9c0a7e..10c0fb072cc 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -2730,6 +2730,12 @@ impl Fragment {
self.style().get_box().perspective != Perspective::None
}
+ /// Returns true if this fragment has a transform applied that causes it to take up no space.
+ pub fn has_non_invertible_transform(&self) -> bool {
+ self.transform_matrix(&Rect::default())
+ .map_or(false, |matrix| !matrix.is_invertible())
+ }
+
/// Returns true if this fragment establishes a new stacking context and false otherwise.
pub fn establishes_stacking_context(&self) -> bool {
// Text fragments shouldn't create stacking contexts.
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index dfdb20e309b..ee9980c4f1a 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -1871,6 +1871,11 @@ impl Flow for InlineFlow {
let previous_cb_clipping_and_scrolling = state.containing_block_clipping_and_scrolling;
for fragment in self.fragments.fragments.iter_mut() {
+ // If a particular fragment would establish a stacking context but has a transform
+ // applied that causes it to take up no space, we can skip it entirely.
+ if fragment.has_non_invertible_transform() {
+ continue;
+ }
state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling;
let abspos_containing_block = fragment.style.get_box().position != Position::Static;
diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs
index 88a6514433b..5c66004bc1a 100644
--- a/components/layout/traversal.rs
+++ b/components/layout/traversal.rs
@@ -346,6 +346,10 @@ pub struct BuildDisplayList<'a> {
impl<'a> BuildDisplayList<'a> {
#[inline]
pub fn traverse(&mut self, flow: &mut dyn Flow) {
+ if flow.has_non_invertible_transform() {
+ return;
+ }
+
let parent_stacking_context_id = self.state.current_stacking_context_id;
self.state.current_stacking_context_id = flow.base().stacking_context_id;
diff --git a/components/layout_2020/display_list/stacking_context.rs b/components/layout_2020/display_list/stacking_context.rs
index fce6fb6caec..371b20e25ac 100644
--- a/components/layout_2020/display_list/stacking_context.rs
+++ b/components/layout_2020/display_list/stacking_context.rs
@@ -234,6 +234,12 @@ impl StackingContext {
));
}
+ // TODO(jdm): WebRender now requires us to create stacking context items
+ // with the IS_BLEND_CONTAINER flag enabled if any children
+ // of the stacking context have a blend mode applied.
+ // This will require additional tracking during layout
+ // before we start collecting stacking contexts so that
+ // information will be available when we reach this point.
builder.wr.push_stacking_context(
LayoutPoint::zero(), // origin
self.spatial_id,
@@ -245,8 +251,7 @@ impl StackingContext {
&vec![], // filter_datas
&vec![], // filter_primitives
wr::RasterSpace::Screen,
- false, // cache_tiles,
- false, // false
+ wr::StackingContextFlags::empty(),
);
true
@@ -447,6 +452,14 @@ impl Fragment {
return;
}
+ // If this fragment has a transform applied that makes it take up no spae
+ // then we don't need to create any stacking contexts for it.
+ let has_non_invertible_transform =
+ fragment.has_non_invertible_transform(&containing_block_info.rect.to_untyped());
+ if has_non_invertible_transform {
+ return;
+ }
+
fragment.build_stacking_context_tree(
fragment_ref,
builder,
@@ -775,6 +788,15 @@ impl BoxFragment {
})
}
+ /// Returns true if the given style contains a transform that is not invertible.
+ fn has_non_invertible_transform(&self, containing_block: &Rect<Length>) -> bool {
+ let list = &self.style.get_box().transform;
+ match list.to_transform_3d_matrix(Some(containing_block)) {
+ Ok(t) => !t.0.is_invertible(),
+ Err(_) => false,
+ }
+ }
+
/// Returns the 4D matrix representing this fragment's transform.
pub fn calculate_transform_matrix(
&self,
@@ -783,6 +805,10 @@ impl BoxFragment {
let list = &self.style.get_box().transform;
let transform =
LayoutTransform::from_untyped(&list.to_transform_3d_matrix(Some(&border_rect)).ok()?.0);
+ // WebRender will end up dividing by the scale value of this transform, so we
+ // want to ensure we don't feed it a divisor of 0.
+ assert_ne!(transform.m11, 0.);
+ assert_ne!(transform.m22, 0.);
let transform_origin = &self.style.get_box().transform_origin;
let transform_origin_x = transform_origin
diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs
index 6676cb39f1e..f3d0e45e3b7 100644
--- a/components/layout_2020/flow/inline.rs
+++ b/components/layout_2020/flow/inline.rs
@@ -275,7 +275,7 @@ impl InlineFormattingContext {
loop {
if let Some(child) = ifc.current_nesting_level.remaining_boxes.next() {
- match &*child.borrow() {
+ match &mut *child.borrow_mut() {
InlineLevelBox::InlineBox(inline) => {
let partial = inline.start_layout(child.clone(), &mut ifc);
ifc.partial_inline_boxes_stack.push(partial)
@@ -529,7 +529,7 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> {
fn layout_atomic(
layout_context: &LayoutContext,
ifc: &mut InlineFormattingContextState,
- atomic: &IndependentFormattingContext,
+ atomic: &mut IndependentFormattingContext,
) {
let pbm = atomic.style.padding_border_margin(&ifc.containing_block);
let margin = pbm.margin.auto_is(Length::zero);
diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs
index 2443e91a0c8..be56a3e2226 100644
--- a/components/layout_2020/flow/mod.rs
+++ b/components/layout_2020/flow/mod.rs
@@ -206,7 +206,7 @@ fn layout_block_level_children(
.iter()
.enumerate()
.map(|(tree_rank, box_)| {
- let mut fragment = box_.borrow().layout(
+ let mut fragment = box_.borrow_mut().layout(
layout_context,
positioning_context,
containing_block,
@@ -226,7 +226,7 @@ fn layout_block_level_children(
.mapfold_reduce_into(
positioning_context,
|positioning_context, (tree_rank, box_)| {
- box_.borrow().layout(
+ box_.borrow_mut().layout(
layout_context,
positioning_context,
containing_block,
@@ -259,7 +259,7 @@ fn layout_block_level_children(
impl BlockLevelBox {
fn layout(
- &self,
+ &mut self,
layout_context: &LayoutContext,
positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock,
diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs
index 2217bcaf621..6819027564c 100644
--- a/components/layout_thread/lib.rs
+++ b/components/layout_thread/lib.rs
@@ -212,9 +212,6 @@ pub struct LayoutThread {
/// Webrender interface.
webrender_api: WebrenderIpcSender,
- /// Webrender document.
- webrender_document: webrender_api::DocumentId,
-
/// Paint time metrics.
paint_time_metrics: PaintTimeMetrics,
@@ -276,7 +273,6 @@ impl LayoutThreadFactory for LayoutThread {
time_profiler_chan: profile_time::ProfilerChan,
mem_profiler_chan: profile_mem::ProfilerChan,
webrender_api_sender: WebrenderIpcSender,
- webrender_document: webrender_api::DocumentId,
paint_time_metrics: PaintTimeMetrics,
busy: Arc<AtomicBool>,
load_webfonts_synchronously: bool,
@@ -325,7 +321,6 @@ impl LayoutThreadFactory for LayoutThread {
time_profiler_chan,
mem_profiler_chan.clone(),
webrender_api_sender,
- webrender_document,
paint_time_metrics,
busy,
load_webfonts_synchronously,
@@ -495,7 +490,6 @@ impl LayoutThread {
time_profiler_chan: profile_time::ProfilerChan,
mem_profiler_chan: profile_mem::ProfilerChan,
webrender_api: WebrenderIpcSender,
- webrender_document: webrender_api::DocumentId,
paint_time_metrics: PaintTimeMetrics,
busy: Arc<AtomicBool>,
load_webfonts_synchronously: bool,
@@ -510,7 +504,7 @@ impl LayoutThread {
dump_flow_tree: bool,
) -> LayoutThread {
// Let webrender know about this pipeline by sending an empty display list.
- webrender_api.send_initial_transaction(webrender_document, id.to_webrender());
+ webrender_api.send_initial_transaction(id.to_webrender());
let device = Device::new(
MediaType::screen(),
@@ -553,7 +547,6 @@ impl LayoutThread {
epoch: Cell::new(Epoch(1)),
viewport_size: Size2D::new(Au(0), Au(0)),
webrender_api,
- webrender_document,
stylist: Stylist::new(device, QuirksMode::NoQuirks),
rw_data: Arc::new(Mutex::new(LayoutThreadData {
constellation_chan: constellation_chan,
@@ -773,7 +766,6 @@ impl LayoutThread {
let point = Point2D::new(-state.scroll_offset.x, -state.scroll_offset.y);
self.webrender_api.send_scroll_node(
- self.webrender_document,
webrender_api::units::LayoutPoint::from_untyped(point),
state.scroll_id,
webrender_api::ScrollClamping::ToContentBounds,
@@ -882,7 +874,6 @@ impl LayoutThread {
self.time_profiler_chan.clone(),
self.mem_profiler_chan.clone(),
self.webrender_api.clone(),
- self.webrender_document,
info.paint_time_metrics,
info.layout_is_busy,
self.load_webfonts_synchronously,
@@ -1171,12 +1162,8 @@ impl LayoutThread {
self.paint_time_metrics
.maybe_observe_paint_time(self, epoch, is_contentful.0);
- self.webrender_api.send_display_list(
- self.webrender_document,
- epoch,
- viewport_size,
- builder.finalize(),
- );
+ self.webrender_api
+ .send_display_list(epoch, viewport_size, builder.finalize());
},
);
}
@@ -1578,7 +1565,6 @@ impl LayoutThread {
let client_point = webrender_api::units::WorldPoint::from_untyped(client_point);
let results = self.webrender_api.hit_test(
- self.webrender_document,
Some(self.id.to_webrender()),
client_point,
flags,
diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs
index fd0d22fc67b..3bb0a7a3353 100644
--- a/components/layout_thread_2020/lib.rs
+++ b/components/layout_thread_2020/lib.rs
@@ -191,9 +191,6 @@ pub struct LayoutThread {
/// Webrender interface.
webrender_api: WebrenderIpcSender,
- /// Webrender document.
- webrender_document: webrender_api::DocumentId,
-
/// Paint time metrics.
paint_time_metrics: PaintTimeMetrics,
@@ -245,7 +242,6 @@ impl LayoutThreadFactory for LayoutThread {
time_profiler_chan: profile_time::ProfilerChan,
mem_profiler_chan: profile_mem::ProfilerChan,
webrender_api_sender: WebrenderIpcSender,
- webrender_document: webrender_api::DocumentId,
paint_time_metrics: PaintTimeMetrics,
busy: Arc<AtomicBool>,
load_webfonts_synchronously: bool,
@@ -294,7 +290,6 @@ impl LayoutThreadFactory for LayoutThread {
time_profiler_chan,
mem_profiler_chan.clone(),
webrender_api_sender,
- webrender_document,
paint_time_metrics,
busy,
load_webfonts_synchronously,
@@ -463,7 +458,6 @@ impl LayoutThread {
time_profiler_chan: profile_time::ProfilerChan,
mem_profiler_chan: profile_mem::ProfilerChan,
webrender_api_sender: WebrenderIpcSender,
- webrender_document: webrender_api::DocumentId,
paint_time_metrics: PaintTimeMetrics,
busy: Arc<AtomicBool>,
load_webfonts_synchronously: bool,
@@ -477,7 +471,7 @@ impl LayoutThread {
trace_layout: bool,
) -> LayoutThread {
// Let webrender know about this pipeline by sending an empty display list.
- webrender_api_sender.send_initial_transaction(webrender_document, id.to_webrender());
+ webrender_api_sender.send_initial_transaction(id.to_webrender());
// The device pixel ratio is incorrect (it does not have the hidpi value),
// but it will be set correctly when the initial reflow takes place.
@@ -521,7 +515,6 @@ impl LayoutThread {
epoch: Cell::new(Epoch(1)),
viewport_size: Size2D::new(Au(0), Au(0)),
webrender_api: webrender_api_sender,
- webrender_document,
stylist: Stylist::new(device, QuirksMode::NoQuirks),
rw_data: Arc::new(Mutex::new(LayoutThreadData {
constellation_chan: constellation_chan,
@@ -737,7 +730,6 @@ impl LayoutThread {
let point = Point2D::new(-state.scroll_offset.x, -state.scroll_offset.y);
self.webrender_api.send_scroll_node(
- self.webrender_document,
webrender_api::units::LayoutPoint::from_untyped(point),
state.scroll_id,
webrender_api::ScrollClamping::ToContentBounds,
@@ -823,7 +815,6 @@ impl LayoutThread {
self.time_profiler_chan.clone(),
self.mem_profiler_chan.clone(),
self.webrender_api.clone(),
- self.webrender_document,
info.paint_time_metrics,
info.layout_is_busy,
self.load_webfonts_synchronously,
@@ -1231,7 +1222,6 @@ impl LayoutThread {
let client_point = webrender_api::units::WorldPoint::from_untyped(client_point);
let results = self.webrender_api.hit_test(
- self.webrender_document,
Some(self.id.to_webrender()),
client_point,
flags,
@@ -1349,12 +1339,8 @@ impl LayoutThread {
self.viewport_size.width.to_f32_px(),
self.viewport_size.height.to_f32_px(),
));
- self.webrender_api.send_display_list(
- self.webrender_document,
- epoch,
- viewport_size,
- display_list.wr.finalize(),
- );
+ self.webrender_api
+ .send_display_list(epoch, viewport_size, display_list.wr.finalize());
if self.trace_layout {
layout_debug::end_trace(self.generation.get());
diff --git a/components/layout_traits/lib.rs b/components/layout_traits/lib.rs
index 2ee0021df96..c33aa3e47aa 100644
--- a/components/layout_traits/lib.rs
+++ b/components/layout_traits/lib.rs
@@ -44,7 +44,6 @@ pub trait LayoutThreadFactory {
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan,
webrender_api_sender: WebrenderIpcSender,
- webrender_document: webrender_api::DocumentId,
paint_time_metrics: PaintTimeMetrics,
busy: Arc<AtomicBool>,
load_webfonts_synchronously: bool,
diff --git a/components/net/connector.rs b/components/net/connector.rs
index 058a27c47d6..dc44002a85a 100644
--- a/components/net/connector.rs
+++ b/components/net/connector.rs
@@ -8,8 +8,13 @@ use hyper::client::HttpConnector as HyperHttpConnector;
use hyper::rt::Future;
use hyper::{Body, Client};
use hyper_openssl::HttpsConnector;
-use openssl::ssl::{SslConnector, SslConnectorBuilder, SslMethod, SslOptions};
-use openssl::x509;
+use openssl::ex_data::Index;
+use openssl::ssl::{
+ Ssl, SslConnector, SslConnectorBuilder, SslContext, SslMethod, SslOptions, SslVerifyMode,
+};
+use openssl::x509::{self, X509StoreContext};
+use std::collections::hash_map::{Entry, HashMap};
+use std::sync::{Arc, Mutex};
use tokio::prelude::future::Executor;
pub const BUF_SIZE: usize = 32768;
@@ -30,6 +35,38 @@ const SIGNATURE_ALGORITHMS: &'static str = concat!(
"RSA+SHA512:RSA+SHA384:RSA+SHA256"
);
+#[derive(Clone)]
+pub struct ConnectionCerts {
+ certs: Arc<Mutex<HashMap<String, (Vec<u8>, u32)>>>,
+}
+
+impl ConnectionCerts {
+ pub fn new() -> Self {
+ Self {
+ certs: Arc::new(Mutex::new(HashMap::new())),
+ }
+ }
+
+ fn store(&self, host: String, cert_bytes: Vec<u8>) {
+ let mut certs = self.certs.lock().unwrap();
+ let entry = certs.entry(host).or_insert((cert_bytes, 0));
+ entry.1 += 1;
+ }
+
+ pub(crate) fn remove(&self, host: String) -> Option<Vec<u8>> {
+ match self.certs.lock().unwrap().entry(host) {
+ Entry::Vacant(_) => return None,
+ Entry::Occupied(mut e) => {
+ e.get_mut().1 -= 1;
+ if e.get().1 == 0 {
+ return Some((e.remove_entry().1).0);
+ }
+ Some(e.get().0.clone())
+ },
+ }
+ }
+}
+
pub struct HttpConnector {
inner: HyperHttpConnector,
}
@@ -60,7 +97,34 @@ impl Connect for HttpConnector {
pub type Connector = HttpsConnector<HttpConnector>;
pub type TlsConfig = SslConnectorBuilder;
-pub fn create_tls_config(certs: &str, alpn: &[u8]) -> TlsConfig {
+#[derive(Clone)]
+pub struct ExtraCerts(Arc<Mutex<Vec<Vec<u8>>>>);
+
+impl ExtraCerts {
+ pub fn new() -> Self {
+ Self(Arc::new(Mutex::new(vec![])))
+ }
+
+ pub fn add(&self, bytes: Vec<u8>) {
+ self.0.lock().unwrap().push(bytes);
+ }
+}
+
+struct Host(String);
+
+lazy_static! {
+ static ref EXTRA_INDEX: Index<SslContext, ExtraCerts> = SslContext::new_ex_index().unwrap();
+ static ref CONNECTION_INDEX: Index<SslContext, ConnectionCerts> =
+ SslContext::new_ex_index().unwrap();
+ static ref HOST_INDEX: Index<Ssl, Host> = Ssl::new_ex_index().unwrap();
+}
+
+pub fn create_tls_config(
+ certs: &str,
+ alpn: &[u8],
+ extra_certs: ExtraCerts,
+ connection_certs: ConnectionCerts,
+) -> TlsConfig {
// certs include multiple certificates. We could add all of them at once,
// but if any of them were already added, openssl would fail to insert all
// of them.
@@ -104,6 +168,44 @@ pub fn create_tls_config(certs: &str, alpn: &[u8]) -> TlsConfig {
SslOptions::NO_COMPRESSION,
);
+ cfg.set_ex_data(*EXTRA_INDEX, extra_certs);
+ cfg.set_ex_data(*CONNECTION_INDEX, connection_certs);
+ cfg.set_verify_callback(SslVerifyMode::PEER, |verified, x509_store_context| {
+ if verified {
+ return true;
+ }
+
+ let ssl_idx = X509StoreContext::ssl_idx().unwrap();
+ let ssl = x509_store_context.ex_data(ssl_idx).unwrap();
+
+ // Obtain the cert bytes for this connection.
+ let cert = match x509_store_context.current_cert() {
+ Some(cert) => cert,
+ None => return false,
+ };
+ let pem = match cert.to_pem() {
+ Ok(pem) => pem,
+ Err(_) => return false,
+ };
+
+ let ssl_context = ssl.ssl_context();
+
+ // Ensure there's an entry stored in the set of known connection certs for this connection.
+ if let Some(host) = ssl.ex_data(*HOST_INDEX) {
+ let connection_certs = ssl_context.ex_data(*CONNECTION_INDEX).unwrap();
+ connection_certs.store((*host).0.clone(), pem.clone());
+ }
+
+ // Fall back to the dynamic set of allowed certs.
+ let extra_certs = ssl_context.ex_data(*EXTRA_INDEX).unwrap();
+ for cert in &*extra_certs.0.lock().unwrap() {
+ if pem == *cert {
+ return true;
+ }
+ }
+ false
+ });
+
cfg
}
@@ -111,7 +213,11 @@ pub fn create_http_client<E>(tls_config: TlsConfig, executor: E) -> Client<Conne
where
E: Executor<Box<dyn Future<Error = (), Item = ()> + Send + 'static>> + Sync + Send + 'static,
{
- let connector = HttpsConnector::with_connector(HttpConnector::new(), tls_config).unwrap();
+ let mut connector = HttpsConnector::with_connector(HttpConnector::new(), tls_config).unwrap();
+ connector.set_callback(|configuration, destination| {
+ configuration.set_ex_data(*HOST_INDEX, Host(destination.host().to_owned()));
+ Ok(())
+ });
Client::builder()
.http1_title_case_headers(true)
diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs
index 457b462bc0b..c25ab10cbe6 100644
--- a/components/net/fetch/methods.rs
+++ b/components/net/fetch/methods.rs
@@ -15,17 +15,19 @@ use headers::{AccessControlExposeHeaders, ContentType, HeaderMapExt, Range};
use http::header::{self, HeaderMap, HeaderName};
use hyper::Method;
use hyper::StatusCode;
-use ipc_channel::ipc::IpcReceiver;
+use ipc_channel::ipc::{self, IpcReceiver};
use mime::{self, Mime};
use net_traits::blob_url_store::{parse_blob_url, BlobURLStoreError};
use net_traits::filemanager_thread::{FileTokenCheck, RelativePos};
use net_traits::request::{
is_cors_safelisted_method, is_cors_safelisted_request_header, Origin, ResponseTainting, Window,
};
-use net_traits::request::{CredentialsMode, Destination, Referrer, Request, RequestMode};
+use net_traits::request::{
+ BodyChunkRequest, CredentialsMode, Destination, Referrer, Request, RequestMode,
+};
use net_traits::response::{Response, ResponseBody, ResponseType};
use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy, ResourceFetchTiming};
-use net_traits::{ResourceAttribute, ResourceTimeValue};
+use net_traits::{ResourceAttribute, ResourceTimeValue, ResourceTimingType};
use servo_arc::Arc as ServoArc;
use servo_url::ServoUrl;
use std::borrow::Cow;
@@ -282,7 +284,10 @@ pub fn main_fetch(
false
};
- if (same_origin && !cors_flag) || current_url.scheme() == "data" {
+ if (same_origin && !cors_flag) ||
+ current_url.scheme() == "data" ||
+ current_url.scheme() == "chrome"
+ {
// Substep 1.
request.response_tainting = ResponseTainting::Basic;
@@ -606,6 +611,17 @@ fn range_not_satisfiable_error(response: &mut Response) {
response.raw_status = Some((StatusCode::RANGE_NOT_SATISFIABLE.as_u16(), reason.into()));
}
+fn create_blank_reply(url: ServoUrl, timing_type: ResourceTimingType) -> Response {
+ let mut response = Response::new(url, ResourceFetchTiming::new(timing_type));
+ response
+ .headers
+ .typed_insert(ContentType::from(mime::TEXT_HTML_UTF_8));
+ *response.body.lock().unwrap() = ResponseBody::Done(vec![]);
+ response.status = Some((StatusCode::OK, "OK".to_string()));
+ response.raw_status = Some((StatusCode::OK.as_u16(), b"OK".to_vec()));
+ response
+}
+
/// [Scheme fetch](https://fetch.spec.whatwg.org#scheme-fetch)
fn scheme_fetch(
request: &mut Request,
@@ -617,15 +633,31 @@ fn scheme_fetch(
let url = request.current_url();
match url.scheme() {
- "about" if url.path() == "blank" => {
- let mut response = Response::new(url, ResourceFetchTiming::new(request.timing_type()));
- response
- .headers
- .typed_insert(ContentType::from(mime::TEXT_HTML_UTF_8));
- *response.body.lock().unwrap() = ResponseBody::Done(vec![]);
- response.status = Some((StatusCode::OK, "OK".to_string()));
- response.raw_status = Some((StatusCode::OK.as_u16(), b"OK".to_vec()));
- response
+ "about" if url.path() == "blank" => create_blank_reply(url, request.timing_type()),
+
+ "chrome" if url.path() == "allowcert" => {
+ let data = request.body.as_mut().and_then(|body| {
+ let stream = body.take_stream();
+ let (body_chan, body_port) = ipc::channel().unwrap();
+ let _ = stream.send(BodyChunkRequest::Connect(body_chan));
+ let _ = stream.send(BodyChunkRequest::Chunk);
+ body_port.recv().ok()
+ });
+ let data = data.as_ref().and_then(|b| {
+ let idx = b.iter().position(|b| *b == b'&')?;
+ Some(b.split_at(idx))
+ });
+
+ if let Some((secret, bytes)) = data {
+ let secret = str::from_utf8(secret).ok().and_then(|s| s.parse().ok());
+ if secret == Some(*net_traits::PRIVILEGED_SECRET) {
+ if let Ok(bytes) = base64::decode(&bytes[1..]) {
+ context.state.extra_certs.add(bytes);
+ }
+ }
+ }
+
+ create_blank_reply(url, request.timing_type())
},
"http" | "https" => http_fetch(
diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs
index 44b36c1bb4d..d69f418006c 100644
--- a/components/net/http_loader.rs
+++ b/components/net/http_loader.rs
@@ -2,7 +2,7 @@
* 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 crate::connector::{create_http_client, Connector, TlsConfig};
+use crate::connector::{create_http_client, ConnectionCerts, Connector, ExtraCerts, TlsConfig};
use crate::cookie;
use crate::cookie_storage::CookieStorage;
use crate::decoder::Decoder;
@@ -89,6 +89,8 @@ pub struct HttpState {
pub auth_cache: RwLock<AuthCache>,
pub history_states: RwLock<HashMap<HistoryStateId, Vec<u8>>>,
pub client: Client<Connector, Body>,
+ pub extra_certs: ExtraCerts,
+ pub connection_certs: ConnectionCerts,
}
impl HttpState {
@@ -104,6 +106,8 @@ impl HttpState {
tls_config,
HANDLE.lock().unwrap().as_ref().unwrap().executor(),
),
+ extra_certs: ExtraCerts::new(),
+ connection_certs: ConnectionCerts::new(),
}
}
}
@@ -527,11 +531,19 @@ fn obtain_response(
let method = method.clone();
let send_start = precise_time_ms();
+ let host = request.uri().host().unwrap_or("").to_owned();
+ let host_clone = request.uri().host().unwrap_or("").to_owned();
+ let connection_certs = context.state.connection_certs.clone();
+ let connection_certs_clone = context.state.connection_certs.clone();
+
let headers = headers.clone();
Box::new(
client
.request(request)
.and_then(move |res| {
+ // We no longer need to track the cert for this connection.
+ connection_certs.remove(host);
+
let send_end = precise_time_ms();
// TODO(#21271) response_start: immediately after receiving first byte of response
@@ -564,7 +576,9 @@ fn obtain_response(
};
Ok((Decoder::detect(res), msg))
})
- .map_err(move |e| NetworkError::from_hyper_error(&e)),
+ .map_err(move |e| {
+ NetworkError::from_hyper_error(&e, connection_certs_clone.remove(host_clone))
+ }),
)
}
@@ -1557,7 +1571,7 @@ fn http_network_fetch(
&url,
&request.method,
&request.headers,
- request.body.as_mut().and_then(|body| body.take_stream()),
+ request.body.as_mut().map(|body| body.take_stream()),
&request.pipeline_id,
request_id.as_ref().map(Deref::deref),
is_xhr,
diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs
index 28a397e78e6..94184c3a046 100644
--- a/components/net/resource_thread.rs
+++ b/components/net/resource_thread.rs
@@ -4,7 +4,9 @@
//! A thread that takes a URL and streams back the binary data.
-use crate::connector::{create_http_client, create_tls_config, ALPN_H2_H1};
+use crate::connector::{
+ create_http_client, create_tls_config, ConnectionCerts, ExtraCerts, ALPN_H2_H1,
+};
use crate::cookie;
use crate::cookie_storage::CookieStorage;
use crate::fetch::cors_cache::CorsCache;
@@ -143,6 +145,9 @@ fn create_http_states(
None => resources::read_string(Resource::SSLCertificates),
};
+ let extra_certs = ExtraCerts::new();
+ let connection_certs = ConnectionCerts::new();
+
let http_state = HttpState {
hsts_list: RwLock::new(hsts_list),
cookie_jar: RwLock::new(cookie_jar),
@@ -151,11 +156,21 @@ fn create_http_states(
http_cache: RwLock::new(http_cache),
http_cache_state: Mutex::new(HashMap::new()),
client: create_http_client(
- create_tls_config(&certs, ALPN_H2_H1),
+ create_tls_config(
+ &certs,
+ ALPN_H2_H1,
+ extra_certs.clone(),
+ connection_certs.clone(),
+ ),
HANDLE.lock().unwrap().as_ref().unwrap().executor(),
),
+ extra_certs,
+ connection_certs,
};
+ let extra_certs = ExtraCerts::new();
+ let connection_certs = ConnectionCerts::new();
+
let private_http_state = HttpState {
hsts_list: RwLock::new(HstsList::from_servo_preload()),
cookie_jar: RwLock::new(CookieStorage::new(150)),
@@ -164,9 +179,16 @@ fn create_http_states(
http_cache: RwLock::new(HttpCache::new()),
http_cache_state: Mutex::new(HashMap::new()),
client: create_http_client(
- create_tls_config(&certs, ALPN_H2_H1),
+ create_tls_config(
+ &certs,
+ ALPN_H2_H1,
+ extra_certs.clone(),
+ connection_certs.clone(),
+ ),
HANDLE.lock().unwrap().as_ref().unwrap().executor(),
),
+ extra_certs,
+ connection_certs,
};
(Arc::new(http_state), Arc::new(private_http_state))
@@ -705,6 +727,8 @@ impl CoreResourceManager {
action_receiver,
http_state.clone(),
self.certificate_path.clone(),
+ http_state.extra_certs.clone(),
+ http_state.connection_certs.clone(),
);
}
}
diff --git a/components/net/tests/fetch.rs b/components/net/tests/fetch.rs
index 38797cf027b..dc4c0f032c0 100644
--- a/components/net/tests/fetch.rs
+++ b/components/net/tests/fetch.rs
@@ -22,7 +22,7 @@ use hyper::body::Body;
use hyper::{Request as HyperRequest, Response as HyperResponse};
use mime::{self, Mime};
use msg::constellation_msg::TEST_PIPELINE_ID;
-use net::connector::{create_tls_config, ALPN_H2_H1};
+use net::connector::{create_tls_config, ConnectionCerts, ExtraCerts, ALPN_H2_H1};
use net::fetch::cors_cache::CorsCache;
use net::fetch::methods::{self, CancellationListener, FetchContext};
use net::filemanager_thread::FileManager;
@@ -682,7 +682,12 @@ fn test_fetch_with_hsts() {
let (server, url) = make_ssl_server(handler, cert_path.clone(), key_path.clone());
let certs = fs::read_to_string(cert_path).expect("Couldn't find certificate file");
- let tls_config = create_tls_config(&certs, ALPN_H2_H1);
+ let tls_config = create_tls_config(
+ &certs,
+ ALPN_H2_H1,
+ ExtraCerts::new(),
+ ConnectionCerts::new(),
+ );
let mut context = FetchContext {
state: Arc::new(HttpState::new(tls_config)),
@@ -735,7 +740,12 @@ fn test_load_adds_host_to_hsts_list_when_url_is_https() {
url.as_mut_url().set_scheme("https").unwrap();
let certs = fs::read_to_string(cert_path).expect("Couldn't find certificate file");
- let tls_config = create_tls_config(&certs, ALPN_H2_H1);
+ let tls_config = create_tls_config(
+ &certs,
+ ALPN_H2_H1,
+ ExtraCerts::new(),
+ ConnectionCerts::new(),
+ );
let mut context = FetchContext {
state: Arc::new(HttpState::new(tls_config)),
@@ -777,6 +787,85 @@ fn test_load_adds_host_to_hsts_list_when_url_is_https() {
}
#[test]
+fn test_fetch_self_signed() {
+ let handler = move |_: HyperRequest<Body>, response: &mut HyperResponse<Body>| {
+ *response.body_mut() = b"Yay!".to_vec().into();
+ };
+ let client_cert_path = Path::new("../../resources/certs").canonicalize().unwrap();
+ let cert_path = Path::new("../../resources/self_signed_certificate_for_testing.crt")
+ .canonicalize()
+ .unwrap();
+ let key_path = Path::new("../../resources/privatekey_for_testing.key")
+ .canonicalize()
+ .unwrap();
+ let (_server, mut url) = make_ssl_server(handler, cert_path.clone(), key_path.clone());
+ url.as_mut_url().set_scheme("https").unwrap();
+
+ let cert_data = fs::read_to_string(cert_path.clone()).expect("Couldn't find certificate file");
+ let client_cert_data =
+ fs::read_to_string(client_cert_path.clone()).expect("Couldn't find certificate file");
+ let extra_certs = ExtraCerts::new();
+ let tls_config = create_tls_config(
+ &client_cert_data,
+ ALPN_H2_H1,
+ extra_certs.clone(),
+ ConnectionCerts::new(),
+ );
+
+ let mut context = FetchContext {
+ state: Arc::new(HttpState::new(tls_config)),
+ user_agent: DEFAULT_USER_AGENT.into(),
+ devtools_chan: None,
+ filemanager: FileManager::new(create_embedder_proxy(), Weak::new()),
+ file_token: FileTokenCheck::NotRequired,
+ cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(None))),
+ timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new(
+ ResourceTimingType::Navigation,
+ ))),
+ };
+
+ let mut request = RequestBuilder::new(url.clone())
+ .method(Method::GET)
+ .body(None)
+ .destination(Destination::Document)
+ .origin(url.clone().origin())
+ .pipeline_id(Some(TEST_PIPELINE_ID))
+ .build();
+
+ let response = fetch_with_context(&mut request, &mut context);
+
+ assert!(matches!(
+ response.get_network_error(),
+ Some(NetworkError::SslValidation(..))
+ ));
+
+ extra_certs.add(cert_data.as_bytes().into());
+
+ // FIXME: something weird happens inside the SSL server after the first
+ // connection encounters a verification error, and it no longer
+ // accepts new connections that should work fine. We are forced
+ // to start a new server and connect to that to verfiy that
+ // the self-signed cert is now accepted.
+
+ let (server, mut url) = make_ssl_server(handler, cert_path.clone(), key_path.clone());
+ url.as_mut_url().set_scheme("https").unwrap();
+
+ let mut request = RequestBuilder::new(url.clone())
+ .method(Method::GET)
+ .body(None)
+ .destination(Destination::Document)
+ .origin(url.clone().origin())
+ .pipeline_id(Some(TEST_PIPELINE_ID))
+ .build();
+
+ let response = fetch_with_context(&mut request, &mut context);
+
+ assert!(response.status.unwrap().0.is_success());
+
+ let _ = server.close();
+}
+
+#[test]
fn test_fetch_with_sri_network_error() {
static MESSAGE: &'static [u8] = b"alert('Hello, Network Error');";
let handler = move |_: HyperRequest<Body>, response: &mut HyperResponse<Body>| {
diff --git a/components/net/tests/main.rs b/components/net/tests/main.rs
index c48ac873729..7583fdf0fc5 100644
--- a/components/net/tests/main.rs
+++ b/components/net/tests/main.rs
@@ -29,7 +29,7 @@ use hyper::server::conn::Http;
use hyper::server::Server as HyperServer;
use hyper::service::service_fn_ok;
use hyper::{Body, Request as HyperRequest, Response as HyperResponse};
-use net::connector::{create_tls_config, ALPN_H2_H1};
+use net::connector::{create_tls_config, ConnectionCerts, ExtraCerts, ALPN_H2_H1};
use net::fetch::cors_cache::CorsCache;
use net::fetch::methods::{self, CancellationListener, FetchContext};
use net::filemanager_thread::FileManager;
@@ -91,7 +91,12 @@ fn new_fetch_context(
pool_handle: Option<Weak<CoreResourceThreadPool>>,
) -> FetchContext {
let certs = resources::read_string(Resource::SSLCertificates);
- let tls_config = create_tls_config(&certs, ALPN_H2_H1);
+ let tls_config = create_tls_config(
+ &certs,
+ ALPN_H2_H1,
+ ExtraCerts::new(),
+ ConnectionCerts::new(),
+ );
let sender = fc.unwrap_or_else(|| create_embedder_proxy());
FetchContext {
diff --git a/components/net/websocket_loader.rs b/components/net/websocket_loader.rs
index 69d3c430fcb..bece51173bb 100644
--- a/components/net/websocket_loader.rs
+++ b/components/net/websocket_loader.rs
@@ -2,7 +2,7 @@
* 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 crate::connector::{create_tls_config, ALPN_H1};
+use crate::connector::{create_tls_config, ConnectionCerts, ExtraCerts, ALPN_H1};
use crate::cookie::Cookie;
use crate::fetch::methods::should_be_blocked_due_to_bad_port;
use crate::hosts::replace_host;
@@ -38,6 +38,8 @@ struct Client<'a> {
event_sender: &'a IpcSender<WebSocketNetworkEvent>,
protocol_in_use: Option<String>,
certificate_path: Option<String>,
+ extra_certs: ExtraCerts,
+ connection_certs: ConnectionCerts,
}
impl<'a> Factory for Client<'a> {
@@ -167,7 +169,12 @@ impl<'a> Handler for Client<'a> {
WebSocketErrorKind::Protocol,
format!("Unable to parse domain from {}. Needed for SSL.", url),
))?;
- let tls_config = create_tls_config(&certs, ALPN_H1);
+ let tls_config = create_tls_config(
+ &certs,
+ ALPN_H1,
+ self.extra_certs.clone(),
+ self.connection_certs.clone(),
+ );
tls_config
.build()
.connect(domain, stream)
@@ -181,6 +188,8 @@ pub fn init(
dom_action_receiver: IpcReceiver<WebSocketDomAction>,
http_state: Arc<HttpState>,
certificate_path: Option<String>,
+ extra_certs: ExtraCerts,
+ connection_certs: ConnectionCerts,
) {
thread::Builder::new()
.name(format!("WebSocket connection to {}", req_builder.url))
@@ -229,6 +238,8 @@ pub fn init(
event_sender: &resource_event_sender,
protocol_in_use: None,
certificate_path,
+ extra_certs,
+ connection_certs,
};
let mut ws = WebSocket::new(client).unwrap();
diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml
index 543d2b538c9..0e663b91bfd 100644
--- a/components/net_traits/Cargo.toml
+++ b/components/net_traits/Cargo.toml
@@ -33,6 +33,7 @@ piston_image = { package = "image", version = "0.23" }
pixels = { path = "../pixels" }
serde = "1.0"
servo_arc = { path = "../servo_arc" }
+servo_rand = { path = "../rand" }
servo_url = { path = "../url" }
time = "0.1"
url = "2.0"
diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs
index 3222daceff0..6dea965d7f8 100644
--- a/components/net_traits/lib.rs
+++ b/components/net_traits/lib.rs
@@ -30,6 +30,7 @@ use ipc_channel::router::ROUTER;
use ipc_channel::Error as IpcError;
use mime::Mime;
use msg::constellation_msg::HistoryStateId;
+use servo_rand::RngCore;
use servo_url::{ImmutableOrigin, ServoUrl};
use time::precise_time_ns;
use webrender_api::{ImageData, ImageDescriptor, ImageKey};
@@ -712,12 +713,17 @@ pub enum NetworkError {
Internal(String),
LoadCancelled,
/// SSL validation error that has to be handled in the HTML parser
- SslValidation(ServoUrl, String),
+ SslValidation(String, Vec<u8>),
}
impl NetworkError {
- pub fn from_hyper_error(error: &HyperError) -> Self {
- NetworkError::Internal(error.to_string())
+ pub fn from_hyper_error(error: &HyperError, cert_bytes: Option<Vec<u8>>) -> Self {
+ let s = error.to_string();
+ if s.contains("the handshake failed") {
+ NetworkError::SslValidation(s, cert_bytes.unwrap_or_default())
+ } else {
+ NetworkError::Internal(s)
+ }
}
pub fn from_http_error(error: &HttpError) -> Self {
@@ -806,3 +812,7 @@ impl WebrenderIpcSender {
}
}
}
+
+lazy_static! {
+ pub static ref PRIVILEGED_SECRET: u32 = servo_rand::ServoRng::new().next_u32();
+}
diff --git a/components/net_traits/request.rs b/components/net_traits/request.rs
index 8906f4f038f..7af3855720d 100644
--- a/components/net_traits/request.rs
+++ b/components/net_traits/request.rs
@@ -164,7 +164,7 @@ impl RequestBody {
}
}
- pub fn take_stream(&mut self) -> Option<IpcSender<BodyChunkRequest>> {
+ pub fn take_stream(&mut self) -> IpcSender<BodyChunkRequest> {
if self.read_from {
match self.source {
BodySource::Null => panic!(
@@ -174,12 +174,12 @@ impl RequestBody {
let (chan, port) = ipc::channel().unwrap();
let _ = self.chan.send(BodyChunkRequest::Extract(port));
self.chan = chan.clone();
- return Some(chan);
+ return chan;
},
}
}
self.read_from = true;
- Some(self.chan.clone())
+ self.chan.clone()
}
pub fn source_is_null(&self) -> bool {
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs
index 0bcf2f45d0f..3a5e9880375 100644
--- a/components/script/dom/htmlmediaelement.rs
+++ b/components/script/dom/htmlmediaelement.rs
@@ -213,7 +213,10 @@ impl VideoFrameRenderer for MediaFrameRenderer {
Some((ref mut image_key, ref mut width, ref mut height)) => {
self.old_frame = Some(*image_key);
- let new_image_key = self.api.generate_image_key();
+ let new_image_key = match self.api.generate_image_key() {
+ Ok(key) => key,
+ Err(()) => return,
+ };
/* update current_frame */
*image_key = new_image_key;
@@ -243,7 +246,10 @@ impl VideoFrameRenderer for MediaFrameRenderer {
updates.push(ImageUpdate::AddImage(new_image_key, descriptor, image_data));
},
None => {
- let image_key = self.api.generate_image_key();
+ let image_key = match self.api.generate_image_key() {
+ Ok(key) => key,
+ Err(()) => return,
+ };
self.current_frame = Some((image_key, frame.get_width(), frame.get_height()));
let image_data = if frame.is_gl_texture() && self.player_id.is_some() {
diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs
index d1a4a18df18..3949f70c53e 100644
--- a/components/script/dom/servoparser/mod.rs
+++ b/components/script/dom/servoparser/mod.rs
@@ -731,9 +731,9 @@ impl FetchResponseListener for ParserContext {
FetchMetadata::Unfiltered(m) => m,
FetchMetadata::Filtered { unsafe_, .. } => unsafe_,
}),
- Err(NetworkError::SslValidation(url, reason)) => {
- ssl_error = Some(reason);
- let mut meta = Metadata::default(url);
+ Err(NetworkError::SslValidation(reason, cert_bytes)) => {
+ ssl_error = Some((reason, cert_bytes));
+ let mut meta = Metadata::default(self.url.clone());
let mime: Option<Mime> = "text/html".parse().ok();
meta.set_content_type(mime.as_ref());
Some(meta)
@@ -815,10 +815,14 @@ impl FetchResponseListener for ParserContext {
},
Some(ref mime) if mime.type_() == mime::TEXT && mime.subtype() == mime::HTML => {
// Handle text/html
- if let Some(reason) = ssl_error {
+ if let Some((reason, bytes)) = ssl_error {
self.is_synthesized_document = true;
let page = resources::read_string(Resource::BadCertHTML);
let page = page.replace("${reason}", &reason);
+ let page =
+ page.replace("${bytes}", std::str::from_utf8(&bytes).unwrap_or_default());
+ let page =
+ page.replace("${secret}", &net_traits::PRIVILEGED_SECRET.to_string());
parser.push_string_input_chunk(page);
parser.parse_sync();
}
diff --git a/components/script/dom/webidls/XMLHttpRequest.webidl b/components/script/dom/webidls/XMLHttpRequest.webidl
index 097b4f7177c..2c043b9407a 100644
--- a/components/script/dom/webidls/XMLHttpRequest.webidl
+++ b/components/script/dom/webidls/XMLHttpRequest.webidl
@@ -12,8 +12,11 @@
* http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0.
*/
+// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit
+typedef (Blob or BufferSource or FormData or DOMString or URLSearchParams) XMLHttpRequestBodyInit;
+
// https://fetch.spec.whatwg.org/#bodyinit
-typedef (Blob or BufferSource or FormData or DOMString or URLSearchParams or ReadableStream) BodyInit;
+typedef (ReadableStream or XMLHttpRequestBodyInit) BodyInit;
enum XMLHttpRequestResponseType {
"",
@@ -54,7 +57,7 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget {
attribute boolean withCredentials;
readonly attribute XMLHttpRequestUpload upload;
[Throws]
- void send(optional (Document or BodyInit)? data = null);
+ void send(optional (Document or XMLHttpRequestBodyInit)? data = null);
void abort();
// response
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index 553cfcb40b0..03a5f5c7bff 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -8,7 +8,7 @@ use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use crate::dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestMethods;
use crate::dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseType;
-use crate::dom::bindings::codegen::UnionTypes::DocumentOrBodyInit;
+use crate::dom::bindings::codegen::UnionTypes::DocumentOrXMLHttpRequestBodyInit;
use crate::dom::bindings::conversions::ToJSValConvertible;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable;
@@ -547,7 +547,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
}
// https://xhr.spec.whatwg.org/#the-send()-method
- fn Send(&self, data: Option<DocumentOrBodyInit>) -> ErrorResult {
+ fn Send(&self, data: Option<DocumentOrXMLHttpRequestBodyInit>) -> ErrorResult {
// Step 1, 2
if self.ready_state.get() != XMLHttpRequestState::Opened || self.send_flag.get() {
return Err(Error::InvalidState);
@@ -560,7 +560,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
};
// Step 4 (first half)
let mut extracted_or_serialized = match data {
- Some(DocumentOrBodyInit::Document(ref doc)) => {
+ Some(DocumentOrXMLHttpRequestBodyInit::Document(ref doc)) => {
let bytes = Vec::from(serialize_document(&doc)?.as_ref());
let content_type = if doc.is_html_document() {
"text/html;charset=UTF-8"
@@ -577,7 +577,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
source: BodySource::Object,
})
},
- Some(DocumentOrBodyInit::Blob(ref b)) => {
+ Some(DocumentOrXMLHttpRequestBodyInit::Blob(ref b)) => {
let extracted_body = b.extract(&self.global()).expect("Couldn't extract body.");
if !extracted_body.in_memory() && self.sync.get() {
warn!("Sync XHR with not in-memory Blob as body not supported");
@@ -586,20 +586,20 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
Some(extracted_body)
}
},
- Some(DocumentOrBodyInit::FormData(ref formdata)) => Some(
+ Some(DocumentOrXMLHttpRequestBodyInit::FormData(ref formdata)) => Some(
formdata
.extract(&self.global())
.expect("Couldn't extract body."),
),
- Some(DocumentOrBodyInit::String(ref str)) => {
+ Some(DocumentOrXMLHttpRequestBodyInit::String(ref str)) => {
Some(str.extract(&self.global()).expect("Couldn't extract body."))
},
- Some(DocumentOrBodyInit::URLSearchParams(ref urlsp)) => Some(
+ Some(DocumentOrXMLHttpRequestBodyInit::URLSearchParams(ref urlsp)) => Some(
urlsp
.extract(&self.global())
.expect("Couldn't extract body."),
),
- Some(DocumentOrBodyInit::ArrayBuffer(ref typedarray)) => {
+ Some(DocumentOrXMLHttpRequestBodyInit::ArrayBuffer(ref typedarray)) => {
let bytes = typedarray.to_vec();
let total_bytes = bytes.len();
let global = self.global();
@@ -611,7 +611,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
source: BodySource::Object,
})
},
- Some(DocumentOrBodyInit::ArrayBufferView(ref typedarray)) => {
+ Some(DocumentOrXMLHttpRequestBodyInit::ArrayBufferView(ref typedarray)) => {
let bytes = typedarray.to_vec();
let total_bytes = bytes.len();
let global = self.global();
@@ -623,25 +623,6 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
source: BodySource::Object,
})
},
- Some(DocumentOrBodyInit::ReadableStream(ref stream)) => {
- if self.sync.get() {
- warn!("Sync XHR with ReadableStream as body not supported");
- None
- } else {
- if stream.is_locked() || stream.is_disturbed() {
- return Err(Error::Type(
- "The body's stream is disturbed or locked".to_string(),
- ));
- }
-
- Some(ExtractedBody {
- stream: stream.clone(),
- total_bytes: None,
- content_type: None,
- source: BodySource::Null,
- })
- }
- },
None => None,
};
@@ -725,7 +706,8 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
match content_type {
Some(content_type) => {
let encoding = match data {
- Some(DocumentOrBodyInit::String(_)) | Some(DocumentOrBodyInit::Document(_)) =>
+ Some(DocumentOrXMLHttpRequestBodyInit::String(_)) |
+ Some(DocumentOrXMLHttpRequestBodyInit::Document(_)) =>
// XHR spec differs from http, and says UTF-8 should be in capitals,
// instead of "utf-8", which is what Hyper defaults to. So not
// using content types provided by Hyper.
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index fc532ff2866..b3e92cbce21 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -1100,12 +1100,11 @@ impl From<i32> for MediaSessionActionType {
#[derive(Deserialize, Serialize)]
pub enum WebrenderMsg {
/// Inform WebRender of the existence of this pipeline.
- SendInitialTransaction(DocumentId, webrender_api::PipelineId),
+ SendInitialTransaction(webrender_api::PipelineId),
/// Perform a scroll operation.
- SendScrollNode(DocumentId, LayoutPoint, ExternalScrollId, ScrollClamping),
+ SendScrollNode(LayoutPoint, ExternalScrollId, ScrollClamping),
/// Inform WebRender of a new display list for the given pipeline.
SendDisplayList(
- DocumentId,
webrender_api::Epoch,
LayoutSize,
webrender_api::PipelineId,
@@ -1116,7 +1115,6 @@ pub enum WebrenderMsg {
/// Perform a hit test operation. The result will be returned via
/// the provided channel sender.
HitTest(
- DocumentId,
Option<webrender_api::PipelineId>,
WorldPoint,
HitTestFlags,
@@ -1140,15 +1138,8 @@ impl WebrenderIpcSender {
}
/// Inform WebRender of the existence of this pipeline.
- pub fn send_initial_transaction(
- &self,
- document: DocumentId,
- pipeline: webrender_api::PipelineId,
- ) {
- if let Err(e) = self
- .0
- .send(WebrenderMsg::SendInitialTransaction(document, pipeline))
- {
+ pub fn send_initial_transaction(&self, pipeline: webrender_api::PipelineId) {
+ if let Err(e) = self.0.send(WebrenderMsg::SendInitialTransaction(pipeline)) {
warn!("Error sending initial transaction: {}", e);
}
}
@@ -1156,14 +1147,14 @@ impl WebrenderIpcSender {
/// Perform a scroll operation.
pub fn send_scroll_node(
&self,
- document: DocumentId,
point: LayoutPoint,
scroll_id: ExternalScrollId,
clamping: ScrollClamping,
) {
- if let Err(e) = self.0.send(WebrenderMsg::SendScrollNode(
- document, point, scroll_id, clamping,
- )) {
+ if let Err(e) = self
+ .0
+ .send(WebrenderMsg::SendScrollNode(point, scroll_id, clamping))
+ {
warn!("Error sending scroll node: {}", e);
}
}
@@ -1171,14 +1162,12 @@ impl WebrenderIpcSender {
/// Inform WebRender of a new display list for the given pipeline.
pub fn send_display_list(
&self,
- document: DocumentId,
epoch: Epoch,
size: LayoutSize,
(pipeline, size2, list): (webrender_api::PipelineId, LayoutSize, BuiltDisplayList),
) {
let (data, descriptor) = list.into_data();
if let Err(e) = self.0.send(WebrenderMsg::SendDisplayList(
- document,
webrender_api::Epoch(epoch.0),
size,
pipeline,
@@ -1194,27 +1183,24 @@ impl WebrenderIpcSender {
/// and a result is available.
pub fn hit_test(
&self,
- document: DocumentId,
pipeline: Option<webrender_api::PipelineId>,
point: WorldPoint,
flags: HitTestFlags,
) -> HitTestResult {
let (sender, receiver) = ipc::channel().unwrap();
self.0
- .send(WebrenderMsg::HitTest(
- document, pipeline, point, flags, sender,
- ))
+ .send(WebrenderMsg::HitTest(pipeline, point, flags, sender))
.expect("error sending hit test");
receiver.recv().expect("error receiving hit test result")
}
/// Create a new image key. Blocks until the key is available.
- pub fn generate_image_key(&self) -> ImageKey {
+ pub fn generate_image_key(&self) -> Result<ImageKey, ()> {
let (sender, receiver) = ipc::channel().unwrap();
self.0
.send(WebrenderMsg::GenerateImageKey(sender))
- .expect("error sending image key generation");
- receiver.recv().expect("error receiving image key result")
+ .map_err(|_| ())?;
+ receiver.recv().map_err(|_| ())
}
/// Perform a resource update operation.
diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml
index 1cb332e3da9..96b2ad36f68 100644
--- a/components/servo/Cargo.toml
+++ b/components/servo/Cargo.toml
@@ -38,6 +38,7 @@ webrender_debugger = ["webrender/debugger"]
xr-profile = ["canvas/xr-profile", "canvas_traits/xr-profile", "script/xr-profile", "webxr/profile"]
[dependencies]
+app_units = "0.7"
background_hang_monitor = { path = "../background_hang_monitor" }
bluetooth = { path = "../bluetooth" }
bluetooth_traits = { path = "../bluetooth_traits" }
@@ -53,6 +54,7 @@ embedder_traits = { path = "../embedder_traits" }
env_logger = "0.7"
euclid = "0.20"
gfx = { path = "../gfx" }
+gfx_traits = { path = "../gfx_traits" }
gleam = "0.11"
gstreamer = { version = "0.15", optional = true }
ipc-channel = "0.14"
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index 9278fb5c0de..25fdd2261b4 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -64,10 +64,12 @@ fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) {}
use bluetooth::BluetoothThreadFactory;
use bluetooth_traits::BluetoothRequest;
+use canvas::canvas_paint_thread::{self, CanvasPaintThread};
use canvas::{SurfaceProviders, WebGLComm, WebGlExecutor};
use canvas_traits::webgl::WebGLThreads;
use compositing::compositor_thread::{
- CompositorProxy, CompositorReceiver, InitialCompositorState, Msg,
+ CompositorProxy, CompositorReceiver, InitialCompositorState, Msg, WebrenderCanvasMsg,
+ WebrenderFontMsg, WebrenderMsg,
};
use compositing::windowing::{EmbedderMethods, WindowEvent, WindowMethods};
use compositing::{CompositingReason, ConstellationMsg, IOCompositor, ShutdownState};
@@ -115,7 +117,6 @@ use std::borrow::Cow;
use std::cmp::max;
use std::path::PathBuf;
use std::rc::Rc;
-use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Mutex};
use surfman::GLApi;
use webrender::ShaderPrecacheFlags;
@@ -454,7 +455,7 @@ where
webrender_surfman.clone(),
webrender_gl.clone(),
&mut webrender,
- webrender_api_sender.clone(),
+ webrender_api.create_sender(),
webrender_document,
&mut webxr_main_thread,
&mut external_image_handlers,
@@ -500,8 +501,6 @@ where
device_pixel_ratio: Scale::new(device_pixel_ratio),
};
- let pending_wr_frame = Arc::new(AtomicBool::new(false));
-
// Create the constellation, which maintains the engine
// pipelines, including the script and layout threads, as well
// as the navigation context.
@@ -515,14 +514,12 @@ where
debugger_chan,
devtools_chan,
webrender_document,
- webrender_api_sender,
webxr_main_thread.registry(),
player_context,
webgl_threads,
glplayer_threads,
event_loop_waker,
window_size,
- pending_wr_frame.clone(),
);
if cfg!(feature = "webdriver") {
@@ -547,7 +544,6 @@ where
webrender_surfman,
webrender_gl,
webxr_main_thread,
- pending_wr_frame,
},
opts.output_file.clone(),
opts.is_running_problem_test,
@@ -855,14 +851,12 @@ fn create_constellation(
debugger_chan: Option<debugger::Sender>,
devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
webrender_document: webrender_api::DocumentId,
- webrender_api_sender: webrender_api::RenderApiSender,
webxr_registry: webxr_api::Registry,
player_context: WindowGLContext,
webgl_threads: Option<WebGLThreads>,
glplayer_threads: Option<GLPlayerThreads>,
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
initial_window_size: WindowSizeData,
- pending_wr_frame: Arc<AtomicBool>,
) -> Sender<ConstellationMsg> {
// Global configuration options, parsed from the command line.
let opts = opts::get();
@@ -879,14 +873,14 @@ fn create_constellation(
config_dir,
opts.certificate_path.clone(),
);
+
let font_cache_thread = FontCacheThread::new(
public_resource_threads.sender(),
- webrender_api_sender.create_api(),
- webrender_document,
+ Box::new(FontCacheWR(compositor_proxy.clone())),
);
let initial_state = InitialConstellationState {
- compositor_proxy,
+ compositor_proxy: compositor_proxy.clone(),
embedder_proxy,
debugger_chan,
devtools_chan,
@@ -897,17 +891,16 @@ fn create_constellation(
time_profiler_chan,
mem_profiler_chan,
webrender_document,
- webrender_api_sender,
webxr_registry,
webgl_threads,
glplayer_threads,
player_context,
event_loop_waker,
- pending_wr_frame,
user_agent,
};
- let (canvas_chan, ipc_canvas_chan) = canvas::canvas_paint_thread::CanvasPaintThread::start();
+ let (canvas_chan, ipc_canvas_chan) =
+ CanvasPaintThread::start(Box::new(CanvasWebrenderApi(compositor_proxy)));
let constellation_chan = Constellation::<
script_layout_interface::message::Msg,
@@ -929,6 +922,50 @@ fn create_constellation(
constellation_chan
}
+struct FontCacheWR(CompositorProxy);
+
+impl gfx_traits::WebrenderApi for FontCacheWR {
+ fn add_font_instance(
+ &self,
+ font_key: webrender_api::FontKey,
+ size: app_units::Au,
+ ) -> webrender_api::FontInstanceKey {
+ let (sender, receiver) = unbounded();
+ let _ = self.0.send(Msg::Webrender(WebrenderMsg::Font(
+ WebrenderFontMsg::AddFontInstance(font_key, size, sender),
+ )));
+ receiver.recv().unwrap()
+ }
+ fn add_font(&self, data: gfx_traits::FontData) -> webrender_api::FontKey {
+ let (sender, receiver) = unbounded();
+ let _ = self.0.send(Msg::Webrender(WebrenderMsg::Font(
+ WebrenderFontMsg::AddFont(data, sender),
+ )));
+ receiver.recv().unwrap()
+ }
+}
+
+#[derive(Clone)]
+struct CanvasWebrenderApi(CompositorProxy);
+
+impl canvas_paint_thread::WebrenderApi for CanvasWebrenderApi {
+ fn generate_key(&self) -> webrender_api::ImageKey {
+ let (sender, receiver) = unbounded();
+ let _ = self.0.send(Msg::Webrender(WebrenderMsg::Canvas(
+ WebrenderCanvasMsg::GenerateKey(sender),
+ )));
+ receiver.recv().unwrap()
+ }
+ fn update_images(&self, updates: Vec<canvas_paint_thread::ImageUpdate>) {
+ let _ = self.0.send(Msg::Webrender(WebrenderMsg::Canvas(
+ WebrenderCanvasMsg::UpdateImages(updates),
+ )));
+ }
+ fn clone(&self) -> Box<dyn canvas_paint_thread::WebrenderApi> {
+ Box::new(<Self as Clone>::clone(self))
+ }
+}
+
// A logger that logs to two downstream loggers.
// This should probably be in the log crate.
struct BothLogger<Log1, Log2>(Log1, Log2);
diff --git a/resources/badcert.html b/resources/badcert.html
index 5a96eee377e..392bddc0572 100644
--- a/resources/badcert.html
+++ b/resources/badcert.html
@@ -3,6 +3,26 @@
<title>Certificate error</title>
</head>
<body>
- <p>${reason}</p>
+ <p>${reason}</p>
+ <pre id="bytes">${bytes}</pre>
+ <button id="leave" onclick="history.back()">Go back (recommended)</button>
+ <button id="allow">Allow certificate temporarily</button>
+ <script>
+ let bytes = document.getElementById('bytes').textContent;
+ let button = document.getElementById('allow');
+ let exitButton = document.getElementById('leave');
+ if (bytes.length) {
+ button.onclick = function() {
+ let xhr = new XMLHttpRequest();
+ xhr.open('POST', 'chrome:allowcert');
+ xhr.onloadend = function() {
+ location.reload(true);
+ };
+ xhr.send("${secret}&" + btoa(bytes));
+ };
+ } else {
+ button.style.display = "none";
+ }
+ </script>
</body>
</html>
diff --git a/resources/servo.css b/resources/servo.css
index bc8d4f1223a..ed6bc3e93dd 100644
--- a/resources/servo.css
+++ b/resources/servo.css
@@ -1,3 +1,7 @@
+button {
+ cursor: default;
+}
+
button,
input {
background: white;
diff --git a/servo-tidy.toml b/servo-tidy.toml
index 480b9fd9ddc..7fb6c99845f 100644
--- a/servo-tidy.toml
+++ b/servo-tidy.toml
@@ -37,7 +37,6 @@ packages = [
"wayland-sys",
"parking_lot",
"parking_lot_core",
- "ron",
# https://github.com/servo/servo/pull/23288#issuecomment-494687746
"gl_generator",
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index e57b659685e..616563a4e31 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -528572,7 +528572,7 @@
]
],
"send-data-es-object.any.js": [
- "c6fe5de260c212013052f66636b92fb07aa82373",
+ "92286bca6dd00b82b78de39fcf7988ba1c424d07",
[
"xhr/send-data-es-object.any.html",
{
@@ -528621,42 +528621,6 @@
}
]
],
- "send-data-readablestream.any.js": [
- "c53b1071828f95669d41a967c51bd352b389bebb",
- [
- "xhr/send-data-readablestream.any.html",
- {
- "script_metadata": [
- [
- "global",
- "window,dedicatedworker,sharedworker"
- ]
- ]
- }
- ],
- [
- "xhr/send-data-readablestream.any.sharedworker.html",
- {
- "script_metadata": [
- [
- "global",
- "window,dedicatedworker,sharedworker"
- ]
- ]
- }
- ],
- [
- "xhr/send-data-readablestream.any.worker.html",
- {
- "script_metadata": [
- [
- "global",
- "window,dedicatedworker,sharedworker"
- ]
- ]
- }
- ]
- ],
"send-data-sharedarraybuffer.any.js": [
"912f622697d538edbbc038f7ec76c2e63ee6ffa0",
[
@@ -529008,7 +528972,7 @@
]
],
"setrequestheader-content-type.htm": [
- "8608c5967d6b29ba4f9d09ae7bf395a6b26876c2",
+ "07238391eb5cc8639edbe996208a18b6d9d26b04",
[
null,
{
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-animation.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-animation.html.ini
new file mode 100644
index 00000000000..5496474410b
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-animation.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-animation.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-interposed.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-interposed.html.ini
new file mode 100644
index 00000000000..f4ba42ba597
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-interposed.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-blended-element-interposed.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-hidden-and-border-radius.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-hidden-and-border-radius.html.ini
new file mode 100644
index 00000000000..b88377b7471
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-hidden-and-border-radius.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-blended-element-overflow-hidden-and-border-radius.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-scroll.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-scroll.html.ini
new file mode 100644
index 00000000000..0cc8e7d5b89
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-scroll.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-blended-element-overflow-scroll.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-with-transparent-pixels.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-with-transparent-pixels.html.ini
new file mode 100644
index 00000000000..e969ccfd9ae
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-with-transparent-pixels.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-blended-element-with-transparent-pixels.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blending-with-sibling.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blending-with-sibling.html.ini
new file mode 100644
index 00000000000..51bd95228fb
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-blending-with-sibling.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-blending-with-sibling.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-both-parent-and-blended-with-3D-transform.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-both-parent-and-blended-with-3D-transform.html.ini
index c66c3bf2773..db1a30234d6 100644
--- a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-both-parent-and-blended-with-3D-transform.html.ini
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-both-parent-and-blended-with-3D-transform.html.ini
@@ -1,3 +1,2 @@
[mix-blend-mode-both-parent-and-blended-with-3D-transform.html]
- expected:
- if os == "linux": FAIL
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-canvas-parent.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-canvas-parent.html.ini
new file mode 100644
index 00000000000..3bca294ac5f
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-canvas-parent.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-canvas-parent.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-canvas-sibling.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-canvas-sibling.html.ini
new file mode 100644
index 00000000000..2bc23c0b9b2
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-canvas-sibling.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-canvas-sibling.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-iframe-parent.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-iframe-parent.html.ini
new file mode 100644
index 00000000000..85229ea8e3f
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-iframe-parent.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-iframe-parent.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-iframe-sibling.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-iframe-sibling.html.ini
new file mode 100644
index 00000000000..17f22fdb1af
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-iframe-sibling.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-iframe-sibling.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-image.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-image.html.ini
new file mode 100644
index 00000000000..7aa3a5aefe5
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-image.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-image.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-intermediate-element-overflow-hidden-and-border-radius.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-intermediate-element-overflow-hidden-and-border-radius.html.ini
index d8f5591b8fd..cfb2c1eebe7 100644
--- a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-intermediate-element-overflow-hidden-and-border-radius.html.ini
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-intermediate-element-overflow-hidden-and-border-radius.html.ini
@@ -1,2 +1,3 @@
[mix-blend-mode-intermediate-element-overflow-hidden-and-border-radius.html]
fuzzy: /css/compositing/mix-blend-mode/reference/mix-blend-mode-intermediate-element-overflow-hidden-and-border-radius-ref.html:9;8
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-mask.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-mask.html.ini
new file mode 100644
index 00000000000..1f039c2f7aa
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-mask.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-mask.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-overflowing-child-of-blended-element.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-overflowing-child-of-blended-element.html.ini
new file mode 100644
index 00000000000..e628a53f56c
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-overflowing-child-of-blended-element.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-overflowing-child-of-blended-element.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-overflowing-child.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-overflowing-child.html.ini
new file mode 100644
index 00000000000..f50a0515ca4
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-overflowing-child.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-overflowing-child.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-element-overflow-scroll-blended-position-fixed.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-element-overflow-scroll-blended-position-fixed.html.ini
new file mode 100644
index 00000000000..f0050373a67
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-element-overflow-scroll-blended-position-fixed.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-parent-element-overflow-scroll-blended-position-fixed.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-element-overflow-scroll.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-element-overflow-scroll.html.ini
new file mode 100644
index 00000000000..87eb5cbd4c6
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-element-overflow-scroll.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-parent-element-overflow-scroll.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-3D-transform.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-3D-transform.html.ini
new file mode 100644
index 00000000000..3260cfddf6f
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-3D-transform.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-parent-with-3D-transform.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-border-radius.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-border-radius.html.ini
new file mode 100644
index 00000000000..52a1cbb7a26
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-border-radius.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-parent-with-border-radius.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-text.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-text.html.ini
index 89ffd68a401..8e6331ff659 100644
--- a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-text.html.ini
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-text.html.ini
@@ -1,3 +1,2 @@
[mix-blend-mode-parent-with-text.html]
- expected:
- if os == "linux": FAIL
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-script.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-script.html.ini
new file mode 100644
index 00000000000..d9d62c6cff4
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-script.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-script.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-sibling-with-3D-transform.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-sibling-with-3D-transform.html.ini
new file mode 100644
index 00000000000..89b4eb5a86a
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-sibling-with-3D-transform.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-sibling-with-3D-transform.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-simple.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-simple.html.ini
new file mode 100644
index 00000000000..b75b4a3d3e2
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-simple.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-simple.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-stacking-context-creates-isolation.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-stacking-context-creates-isolation.html.ini
new file mode 100644
index 00000000000..8e3c2a518e1
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-stacking-context-creates-isolation.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-stacking-context-creates-isolation.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-with-transform-and-preserve-3D.html.ini b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-with-transform-and-preserve-3D.html.ini
new file mode 100644
index 00000000000..5277e6aca56
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/mix-blend-mode/mix-blend-mode-with-transform-and-preserve-3D.html.ini
@@ -0,0 +1,2 @@
+[mix-blend-mode-with-transform-and-preserve-3D.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/compositing/root-element-blend-mode.html.ini b/tests/wpt/metadata/css/compositing/root-element-blend-mode.html.ini
new file mode 100644
index 00000000000..448b96b4886
--- /dev/null
+++ b/tests/wpt/metadata/css/compositing/root-element-blend-mode.html.ini
@@ -0,0 +1,2 @@
+[root-element-blend-mode.html]
+ expected: FAIL
diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json
index 5ce021feee6..47ba62031be 100644
--- a/tests/wpt/mozilla/meta/MANIFEST.json
+++ b/tests/wpt/mozilla/meta/MANIFEST.json
@@ -6080,6 +6080,19 @@
{}
]
],
+ "stacking-context-empty.html": [
+ "952c73f1680805dc3a976446bb509cb924a6a702",
+ [
+ null,
+ [
+ [
+ "/_mozilla/css/stacking-context-empty-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"stacking_context_overflow_a.html": [
"dc379afb77977b0e99a0a8ce3321c9afff236a37",
[
@@ -10311,6 +10324,10 @@
"0525bab6b11800d29f90efc7efef0f43165fba01",
[]
],
+ "stacking-context-empty-ref.html": [
+ "8006e2413694b0776f000d3b8138bed29812b7cd",
+ []
+ ],
"stacking_context_overflow_ref.html": [
"49991c449ab4f42afae6f512a7f184e70d77bc34",
[]
diff --git a/tests/wpt/mozilla/meta/css/inline_block_baseline_a.html.ini b/tests/wpt/mozilla/meta/css/inline_block_baseline_a.html.ini
index 88c40a7a0ae..91cee3c0295 100644
--- a/tests/wpt/mozilla/meta/css/inline_block_baseline_a.html.ini
+++ b/tests/wpt/mozilla/meta/css/inline_block_baseline_a.html.ini
@@ -1,3 +1,4 @@
[inline_block_baseline_a.html]
expected:
- if os == "mac": FAIL
+ if os == "linux": FAIL
+ fuzzy: /_mozilla/css/inline_block_baseline_ref.html:49;2097
diff --git a/tests/wpt/mozilla/tests/css/stacking-context-empty-ref.html b/tests/wpt/mozilla/tests/css/stacking-context-empty-ref.html
new file mode 100644
index 00000000000..8006e241369
--- /dev/null
+++ b/tests/wpt/mozilla/tests/css/stacking-context-empty-ref.html
@@ -0,0 +1 @@
+<p><img src="100x100_green.png">
diff --git a/tests/wpt/mozilla/tests/css/stacking-context-empty.html b/tests/wpt/mozilla/tests/css/stacking-context-empty.html
new file mode 100644
index 00000000000..952c73f1680
--- /dev/null
+++ b/tests/wpt/mozilla/tests/css/stacking-context-empty.html
@@ -0,0 +1,14 @@
+<link rel="match" href="stacking-context-empty-ref.html">
+<style>
+ div {
+ border-radius: 2px;
+ background: #777;
+ border-bottom: 1px solid #f1f1f1;
+ }
+.test {
+ transform: scaleX(0);
+}
+</style>
+<p><img src="100x100_green.png">
+<div class="test">aaa</div>
+<p><img class="test" src="100x100_green.png">
diff --git a/tests/wpt/web-platform-tests/xhr/send-data-es-object.any.js b/tests/wpt/web-platform-tests/xhr/send-data-es-object.any.js
index c6fe5de260c..92286bca6dd 100644
--- a/tests/wpt/web-platform-tests/xhr/send-data-es-object.any.js
+++ b/tests/wpt/web-platform-tests/xhr/send-data-es-object.any.js
@@ -27,6 +27,7 @@ function do_test(obj, expected, name) {
do_test({}, '[object Object]', 'sending a plain empty object')
do_test(Math, '[object Math]', 'sending the ES Math object')
do_test(new XMLHttpRequest, '[object XMLHttpRequest]', 'sending a new XHR instance')
+do_test(new ReadableStream, '[object ReadableStream]', 'sending a new ReadableStream instance')
do_test({toString:function(){}}, 'undefined', 'sending object that stringifies to undefined')
do_test({toString:function(){return null}}, 'null', 'sending object that stringifies to null')
var ancestor = {toString: function(){
diff --git a/tests/wpt/web-platform-tests/xhr/send-data-readablestream.any.js b/tests/wpt/web-platform-tests/xhr/send-data-readablestream.any.js
deleted file mode 100644
index c53b1071828..00000000000
--- a/tests/wpt/web-platform-tests/xhr/send-data-readablestream.any.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// META: global=window,dedicatedworker,sharedworker
-
-function assert_xhr(stream) {
- const client = new XMLHttpRequest();
- client.open("POST", "...");
- assert_throws_js(TypeError, () => client.send(stream));
-}
-
-test(() => {
- const stream = new ReadableStream();
- stream.getReader();
- assert_xhr(stream);
-}, "XMLHttpRequest: send() with a stream on which getReader() is called");
-
-test(() => {
- const stream = new ReadableStream();
- stream.getReader().read();
- assert_xhr(stream);
-}, "XMLHttpRequest: send() with a stream on which read() is called");
-
-promise_test(async () => {
- const stream = new ReadableStream({ pull: c => c.enqueue(new Uint8Array()) }),
- reader = stream.getReader();
- await reader.read();
- reader.releaseLock();
- assert_xhr(stream);
-}, "XMLHttpRequest: send() with a stream on which read() and releaseLock() are called");
diff --git a/tests/wpt/web-platform-tests/xhr/setrequestheader-content-type.htm b/tests/wpt/web-platform-tests/xhr/setrequestheader-content-type.htm
index 8608c5967d6..07238391eb5 100644
--- a/tests/wpt/web-platform-tests/xhr/setrequestheader-content-type.htm
+++ b/tests/wpt/web-platform-tests/xhr/setrequestheader-content-type.htm
@@ -215,24 +215,6 @@
// https://fetch.spec.whatwg.org/#bodyinit, so the user's must be changed to match it
// as per https://xhr.spec.whatwg.org/#the-send%28%29-method step 4.
)
- request(
- function _ReadableStream() { return new ReadableStream() },
- {"Content-Type": ""},
- "",
- 'ReadableStream request respects setRequestHeader("")'
- )
- request(
- function _ReadableStream() { return new ReadableStream() },
- {},
- undefined,
- "ReadableStream request with under type sends no Content-Type without setRequestHeader() call"
- )
- request(
- function _ReadableStream() { return new ReadableStream() },
- {"Content-Type": "application/xml;charset=ASCII"},
- "application/xml;charset=ASCII",
- "ReadableStream request keeps setRequestHeader() Content-Type and charset"
- )
</script>
</body>
</html>