Skip to content
Permalink
Browse files

clean-up navigation

security: check target and source origin before executing JS url

implement replacement-enabled flag as a HistoryEntryReplacement enum

add source origin string on loaddata

add LoadOrigin

iframe: remove optional load-data

auxiliaries: add load-data into info

constellation: remove url from Pipeline::new

check load origin: link to whatwg issue

switch loadorigin toplevel to constellation
  • Loading branch information...
gterzian committed May 12, 2019
1 parent 973a344 commit 571beec179fe9fd5fff2c12b3c5dfa0a5d93df01
@@ -145,11 +145,11 @@ use script_traits::{
use script_traits::{
ConstellationControlMsg, ConstellationMsg as FromCompositorMsg, DiscardBrowsingContext,
};
use script_traits::{DocumentActivity, DocumentState, LayoutControlMsg, LoadData};
use script_traits::{DocumentActivity, DocumentState, LayoutControlMsg, LoadData, LoadOrigin};
use script_traits::{HistoryEntryReplacement, IFrameSizeMsg, WindowSizeData, WindowSizeType};
use script_traits::{
IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState, TimerSchedulerMsg,
};
use script_traits::{IFrameSizeMsg, WindowSizeData, WindowSizeType};
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
use script_traits::{SWManagerMsg, ScopeThings, UpdatePipelineIdReason, WebDriverCommandMsg};
use serde::{Deserialize, Serialize};
@@ -171,7 +171,7 @@ use style_traits::viewport::ViewportConstraints;
use style_traits::CSSPixel;
use webvr_traits::{WebVREvent, WebVRMsg};

type PendingApprovalNavigations = HashMap<PipelineId, (LoadData, bool)>;
type PendingApprovalNavigations = HashMap<PipelineId, (LoadData, HistoryEntryReplacement)>;

/// Servo supports tabs (referred to as browsers), so `Constellation` needs to
/// store browser specific data for bookkeeping.
@@ -1320,7 +1320,7 @@ where
// If there is already a pending page (self.pending_changes), it will not be overridden;
// However, if the id is not encompassed by another change, it will be.
FromCompositorMsg::LoadUrl(top_level_browsing_context_id, url) => {
let load_data = LoadData::new(url, None, None, None);
let load_data = LoadData::new(LoadOrigin::Constellation, url, None, None, None);
let ctx_id = BrowsingContextId::from(top_level_browsing_context_id);
let pipeline_id = match self.browsing_contexts.get(&ctx_id) {
Some(ctx) => ctx.pipeline_id,
@@ -1333,7 +1333,12 @@ where
};
// Since this is a top-level load, initiated by the embedder, go straight to load_url,
// bypassing schedule_navigation.
self.load_url(top_level_browsing_context_id, pipeline_id, load_data, false);
self.load_url(
top_level_browsing_context_id,
pipeline_id,
load_data,
HistoryEntryReplacement::Disabled,
);
},
FromCompositorMsg::IsReadyToSaveImage(pipeline_states) => {
let is_ready = self.handle_is_ready_to_save_image(pipeline_states);
@@ -1916,7 +1921,7 @@ where
warn!("creating replacement pipeline for about:failure");

let new_pipeline_id = PipelineId::new();
let load_data = LoadData::new(failure_url, None, None, None);
let load_data = LoadData::new(LoadOrigin::Constellation, failure_url, None, None, None);
let sandbox = IFrameSandboxState::IFrameSandboxed;
let is_private = false;
self.new_pipeline(
@@ -2035,7 +2040,7 @@ where
);
self.embedder_proxy.send(msg);
let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id);
let load_data = LoadData::new(url, None, None, None);
let load_data = LoadData::new(LoadOrigin::Constellation, url, None, None, None);
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
let is_private = false;
let is_visible = true;
@@ -2196,7 +2201,9 @@ where
// see https://html.spec.whatwg.org/multipage/#the-iframe-element:completely-loaded
debug!("checking old pipeline? {:?}", load_info.old_pipeline_id);
if let Some(old_pipeline) = old_pipeline {
replace |= !old_pipeline.completely_loaded;
if !old_pipeline.completely_loaded {
replace = HistoryEntryReplacement::Enabled;
}
debug!(
"old pipeline is {}completely loaded",
if old_pipeline.completely_loaded {
@@ -2207,16 +2214,6 @@ where
);
}

let load_data = load_info.load_data.unwrap_or_else(|| {
let url = match old_pipeline {
Some(old_pipeline) => old_pipeline.url.clone(),
None => ServoUrl::parse("about:blank").expect("infallible"),
};

// TODO - loaddata here should have referrer info (not None, None)
LoadData::new(url, Some(parent_pipeline_id), None, None)
});

let is_parent_private = {
let parent_browsing_context_id = match self.pipelines.get(&parent_pipeline_id) {
Some(pipeline) => pipeline.browsing_context_id,
@@ -2250,10 +2247,11 @@ where
},
};

let replace = if replace {
Some(NeedsToReload::No(browsing_context.pipeline_id))
} else {
None
let replace = match replace {
HistoryEntryReplacement::Enabled => {
Some(NeedsToReload::No(browsing_context.pipeline_id))
},
HistoryEntryReplacement::Disabled => None,
};

// https://github.com/rust-lang/rust/issues/59159
@@ -2268,7 +2266,7 @@ where
Some(parent_pipeline_id),
None,
browsing_context_size,
load_data,
load_info.load_data,
load_info.sandbox,
is_private,
browsing_context_is_visible,
@@ -2285,7 +2283,7 @@ where

fn handle_script_new_iframe(
&mut self,
load_info: IFrameLoadInfo,
load_info: IFrameLoadInfoWithData,
layout_sender: IpcSender<LayoutControlMsg>,
) {
let IFrameLoadInfo {
@@ -2295,12 +2293,7 @@ where
top_level_browsing_context_id,
is_private,
..
} = load_info;

let url = ServoUrl::parse("about:blank").expect("infallible");

// TODO: Referrer?
let load_data = LoadData::new(url.clone(), Some(parent_pipeline_id), None, None);
} = load_info.info;

let (script_sender, parent_browsing_context_id) =
match self.pipelines.get(&parent_pipeline_id) {
@@ -2326,9 +2319,8 @@ where
script_sender,
layout_sender,
self.compositor_proxy.clone(),
url,
is_parent_visible,
load_data,
load_info.load_data,
);

assert!(!self.pipelines.contains_key(&new_pipeline_id));
@@ -2353,17 +2345,13 @@ where
layout_sender: IpcSender<LayoutControlMsg>,
) {
let AuxiliaryBrowsingContextLoadInfo {
load_data,
opener_pipeline_id,
new_top_level_browsing_context_id,
new_browsing_context_id,
new_pipeline_id,
} = load_info;

let url = ServoUrl::parse("about:blank").expect("infallible");

// TODO: Referrer?
let load_data = LoadData::new(url.clone(), None, None, None);

let (script_sender, opener_browsing_context_id) =
match self.pipelines.get(&opener_pipeline_id) {
Some(pipeline) => (pipeline.event_loop.clone(), pipeline.browsing_context_id),
@@ -2392,7 +2380,6 @@ where
script_sender,
layout_sender,
self.compositor_proxy.clone(),
url,
is_opener_visible,
load_data,
);
@@ -2496,7 +2483,7 @@ where
top_level_browsing_context_id: TopLevelBrowsingContextId,
source_id: PipelineId,
load_data: LoadData,
replace: bool,
replace: HistoryEntryReplacement,
) {
match self.pending_approval_navigations.entry(source_id) {
Entry::Occupied(_) => {
@@ -2522,13 +2509,15 @@ where
top_level_browsing_context_id: TopLevelBrowsingContextId,
source_id: PipelineId,
load_data: LoadData,
replace: bool,
replace: HistoryEntryReplacement,
) -> Option<PipelineId> {
let replace_debug = match replace {
HistoryEntryReplacement::Enabled => "",
HistoryEntryReplacement::Disabled => "not",
};
debug!(
"Loading {} in pipeline {}, {}replacing.",
load_data.url,
source_id,
if replace { "" } else { "not " }
load_data.url, source_id, replace_debug
);
// If this load targets an iframe, its framing element may exist
// in a separate script thread than the framed document that initiated
@@ -2569,7 +2558,7 @@ where
Some(parent_pipeline_id) => {
// Find the script thread for the pipeline containing the iframe
// and issue an iframe load through there.
let msg = ConstellationControlMsg::Navigate(
let msg = ConstellationControlMsg::NavigateIframe(
parent_pipeline_id,
browsing_context_id,
load_data,
@@ -2612,10 +2601,9 @@ where

// Create the new pipeline

let replace = if replace {
Some(NeedsToReload::No(pipeline_id))
} else {
None
let replace = match replace {
HistoryEntryReplacement::Enabled => Some(NeedsToReload::No(pipeline_id)),
HistoryEntryReplacement::Disabled => None,
};

let new_pipeline_id = PipelineId::new();
@@ -2730,7 +2718,7 @@ where
&mut self,
pipeline_id: PipelineId,
new_url: ServoUrl,
replacement_enabled: bool,
replacement_enabled: HistoryEntryReplacement,
) {
let (top_level_browsing_context_id, old_url) = match self.pipelines.get_mut(&pipeline_id) {
Some(pipeline) => {
@@ -2745,15 +2733,18 @@ where
},
};

if !replacement_enabled {
let diff = SessionHistoryDiff::HashDiff {
pipeline_reloader: NeedsToReload::No(pipeline_id),
new_url,
old_url,
};
self.get_joint_session_history(top_level_browsing_context_id)
.push_diff(diff);
self.notify_history_changed(top_level_browsing_context_id);
match replacement_enabled {
HistoryEntryReplacement::Disabled => {
let diff = SessionHistoryDiff::HashDiff {
pipeline_reloader: NeedsToReload::No(pipeline_id),
new_url,
old_url,
};
self.get_joint_session_history(top_level_browsing_context_id)
.push_diff(diff);
self.notify_history_changed(top_level_browsing_context_id);
},
HistoryEntryReplacement::Enabled => {},
}
}

@@ -3395,7 +3386,12 @@ where
));
},
WebDriverCommandMsg::LoadUrl(top_level_browsing_context_id, load_data, reply) => {
self.load_url_for_webdriver(top_level_browsing_context_id, load_data, reply, false);
self.load_url_for_webdriver(
top_level_browsing_context_id,
load_data,
reply,
HistoryEntryReplacement::Disabled,
);
},
WebDriverCommandMsg::Refresh(top_level_browsing_context_id, reply) => {
let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id);
@@ -3412,7 +3408,12 @@ where
Some(pipeline) => pipeline.load_data.clone(),
None => return warn!("Pipeline {} refresh after closure.", pipeline_id),
};
self.load_url_for_webdriver(top_level_browsing_context_id, load_data, reply, true);
self.load_url_for_webdriver(
top_level_browsing_context_id,
load_data,
reply,
HistoryEntryReplacement::Enabled,
);
},
WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd) => {
let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
@@ -3595,7 +3596,7 @@ where
top_level_browsing_context_id: TopLevelBrowsingContextId,
load_data: LoadData,
reply: IpcSender<webdriver_msg::LoadStatus>,
replace: bool,
replace: HistoryEntryReplacement,
) {
let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id);
let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
@@ -215,8 +215,6 @@ impl Pipeline {
device_pixel_ratio: state.device_pixel_ratio,
};

let url = state.load_data.url.clone();

let (script_chan, sampler_chan) = match state.event_loop {
Some(script_chan) => {
let new_layout_info = NewLayoutInfo {
@@ -336,7 +334,6 @@ impl Pipeline {
script_chan,
pipeline_chan,
state.compositor_proxy,
url,
state.prev_visibility,
state.load_data,
);
@@ -356,7 +353,6 @@ impl Pipeline {
event_loop: Rc<EventLoop>,
layout_chan: IpcSender<LayoutControlMsg>,
compositor_proxy: CompositorProxy,
url: ServoUrl,
is_visible: bool,
load_data: LoadData,
) -> Pipeline {
@@ -368,7 +364,7 @@ impl Pipeline {
event_loop: event_loop,
layout_chan: layout_chan,
compositor_proxy: compositor_proxy,
url: url,
url: load_data.url.clone(),
children: vec![],
running_animations: false,
load_data: load_data,

0 comments on commit 571beec

Please sign in to comment.
You can’t perform that action at this time.