mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
Make it possible for iframes to create their own pipeline ID.
This doesn't change any functionality, but it's the first step towards removing SubpageId. Adding this change now will allow us to gradually change over code referencing subpage id rather than in one massive PR. Introduces a namespace for pipeline ID generation - there is a namespace for the constellation thread, and one per script thread.
This commit is contained in:
parent
35888e5a1d
commit
5645dba1fa
9 changed files with 193 additions and 68 deletions
|
@ -15,7 +15,9 @@ use ipc_channel::ipc::IpcSender;
|
|||
use layers::geometry::DevicePixel;
|
||||
use offscreen_gl_context::GLContextAttributes;
|
||||
use png::Image;
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use style_traits::viewport::ViewportConstraints;
|
||||
use url::Url;
|
||||
|
@ -211,6 +213,23 @@ pub enum FocusType {
|
|||
Parent, // Focusing a parent element (an iframe)
|
||||
}
|
||||
|
||||
/// Specifies the information required to load a URL in an iframe.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct IframeLoadInfo {
|
||||
/// Url to load
|
||||
pub url: Url,
|
||||
/// Pipeline ID of the parent of this iframe
|
||||
pub containing_pipeline_id: PipelineId,
|
||||
/// The new subpage ID for this load
|
||||
pub new_subpage_id: SubpageId,
|
||||
/// The old subpage ID for this iframe, if a page was previously loaded.
|
||||
pub old_subpage_id: Option<SubpageId>,
|
||||
/// The new pipeline ID that the iframe has generated.
|
||||
pub new_pipeline_id: PipelineId,
|
||||
/// Sandbox type of this iframe
|
||||
pub sandbox: IFrameSandboxState,
|
||||
}
|
||||
|
||||
/// Messages from the compositor and script to the constellation.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum Msg {
|
||||
|
@ -222,7 +241,7 @@ pub enum Msg {
|
|||
DOMLoad(PipelineId),
|
||||
FrameSize(PipelineId, SubpageId, Size2D<f32>),
|
||||
LoadUrl(PipelineId, LoadData),
|
||||
ScriptLoadedURLInIFrame(Url, PipelineId, SubpageId, Option<SubpageId>, IFrameSandboxState),
|
||||
ScriptLoadedURLInIFrame(IframeLoadInfo),
|
||||
Navigate(Option<(PipelineId, SubpageId)>, NavigationDirection),
|
||||
PainterReady(PipelineId),
|
||||
ResizedWindow(WindowSizeData),
|
||||
|
@ -393,8 +412,95 @@ pub struct FrameId(pub u32);
|
|||
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
||||
pub struct WorkerId(pub u32);
|
||||
|
||||
/// Each pipeline ID needs to be unique. However, it also needs to be possible to
|
||||
/// generate the pipeline ID from an iframe element (this simplifies a lot of other
|
||||
/// code that makes use of pipeline IDs).
|
||||
///
|
||||
/// To achieve this, each pipeline index belongs to a particular namespace. There is
|
||||
/// a namespace for the constellation thread, and also one for every script thread.
|
||||
/// This allows pipeline IDs to be generated by any of those threads without conflicting
|
||||
/// with pipeline IDs created by other script threads or the constellation. The
|
||||
/// constellation is the only code that is responsible for creating new *namespaces*.
|
||||
/// This ensures that namespaces are always unique, even when using multi-process mode.
|
||||
///
|
||||
/// It may help conceptually to think of the namespace ID as an identifier for the
|
||||
/// thread that created this pipeline ID - however this is really an implementation
|
||||
/// detail so shouldn't be relied upon in code logic. It's best to think of the
|
||||
/// pipeline ID as a simple unique identifier that doesn't convey any more information.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct PipelineNamespace {
|
||||
id: PipelineNamespaceId,
|
||||
next_index: PipelineIndex,
|
||||
}
|
||||
|
||||
impl PipelineNamespace {
|
||||
pub fn install(namespace_id: PipelineNamespaceId) {
|
||||
PIPELINE_NAMESPACE.with(|tls| {
|
||||
assert!(tls.get().is_none());
|
||||
tls.set(Some(PipelineNamespace {
|
||||
id: namespace_id,
|
||||
next_index: PipelineIndex(0),
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
fn next(&mut self) -> PipelineId {
|
||||
let pipeline_id = PipelineId {
|
||||
namespace_id: self.id,
|
||||
index: self.next_index,
|
||||
};
|
||||
|
||||
let PipelineIndex(current_index) = self.next_index;
|
||||
self.next_index = PipelineIndex(current_index + 1);
|
||||
|
||||
pipeline_id
|
||||
}
|
||||
}
|
||||
|
||||
thread_local!(pub static PIPELINE_NAMESPACE: Cell<Option<PipelineNamespace>> = Cell::new(None));
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
||||
pub struct PipelineId(pub u32);
|
||||
pub struct PipelineNamespaceId(pub u32);
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
||||
pub struct PipelineIndex(u32);
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
||||
pub struct PipelineId {
|
||||
namespace_id: PipelineNamespaceId,
|
||||
index: PipelineIndex
|
||||
}
|
||||
|
||||
impl PipelineId {
|
||||
pub fn new() -> PipelineId {
|
||||
PIPELINE_NAMESPACE.with(|tls| {
|
||||
let mut namespace = tls.get().expect("No namespace set for this thread!");
|
||||
let new_pipeline_id = namespace.next();
|
||||
tls.set(Some(namespace));
|
||||
new_pipeline_id
|
||||
})
|
||||
}
|
||||
|
||||
// TODO(gw): This should be removed. It's only required because of the code
|
||||
// that uses it in the devtools lib.rs file (which itself is a TODO). Once
|
||||
// that is fixed, this should be removed. It also relies on the first
|
||||
// call to PipelineId::new() returning (0,0), which is checked with an
|
||||
// assert in handle_init_load().
|
||||
pub fn fake_root_pipeline_id() -> PipelineId {
|
||||
PipelineId {
|
||||
namespace_id: PipelineNamespaceId(0),
|
||||
index: PipelineIndex(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PipelineId {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
let PipelineNamespaceId(namespace_id) = self.namespace_id;
|
||||
let PipelineIndex(index) = self.index;
|
||||
write!(fmt, "({},{})", namespace_id, index)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
||||
pub struct SubpageId(pub u32);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue