aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/script_thread.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/script_thread.rs')
-rw-r--r--components/script/script_thread.rs440
1 files changed, 225 insertions, 215 deletions
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 96555524c5d..4a19547138c 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -18,20 +18,20 @@
//! loop.
use devtools;
-use devtools_traits::CSSError;
use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo};
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
+use devtools_traits::CSSError;
use document_loader::DocumentLoader;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
-use dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior};
+use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, StringificationBehavior};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, MutNullableHeap, Root, RootCollection};
use dom::bindings::js::{RootCollectionPtr, RootedReference};
-use dom::bindings::refcounted::{LiveDOMReferences, Trusted};
+use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
use dom::bindings::trace::JSTraceable;
@@ -51,27 +51,25 @@ use dom::worker::TrustedWorkerAddress;
use euclid::Rect;
use euclid::point::Point2D;
use gfx_traits::LayerId;
-use hyper::header::{ContentType, HttpDate};
-use hyper::header::{Headers, LastModified};
+use hyper::header::{ContentType, Headers, HttpDate, LastModified};
+use hyper::header::ReferrerPolicy as ReferrerPolicyHeader;
use hyper::method::Method;
use hyper::mime::{Mime, SubLevel, TopLevel};
+use hyper_serde::Serde;
use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER;
use js::glue::GetWindowProxyClass;
-use js::jsapi::{DOMProxyShadowsResult, HandleId, HandleObject, RootedValue};
use js::jsapi::{JSAutoCompartment, JSContext, JS_SetWrapObjectCallbacks};
use js::jsapi::{JSTracer, SetWindowProxyClass};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use mem::heap_size_of_self_and_children;
-use msg::constellation_msg::{FrameType, LoadData, PanicMsg, PipelineId, PipelineNamespace};
-use msg::constellation_msg::{SubpageId, WindowSizeData, WindowSizeType};
-use msg::webdriver_msg::WebDriverScriptCommand;
-use net_traits::LoadData as NetLoadData;
+use msg::constellation_msg::{FrameType, LoadData, PipelineId, PipelineNamespace};
+use msg::constellation_msg::{ReferrerPolicy, WindowSizeType};
+use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadContext, Metadata, ResourceThreads};
+use net_traits::{IpcSend, LoadData as NetLoadData};
use net_traits::bluetooth_thread::BluetoothMethodMsg;
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
-use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadContext, Metadata, ResourceThreads};
-use net_traits::{RequestSource, CustomResponse, CustomResponseSender, IpcSend};
use network_listener::NetworkListener;
use parse::ParserRoot;
use parse::html::{ParseContext, parse_html};
@@ -80,14 +78,15 @@ use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan};
use profile_traits::time::{self, ProfilerCategory, profile};
use script_layout_interface::message::{self, NewLayoutThreadInfo, ReflowQueryType};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
-use script_runtime::{ScriptPort, StackRootTLS, new_rt_and_cx, get_reports};
-use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
-use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent};
+use script_runtime::{ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
use script_traits::{CompositorEvent, ConstellationControlMsg, EventResult};
use script_traits::{InitialScriptState, MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg};
use script_traits::{ScriptThreadFactory, TimerEvent, TimerEventRequest, TimerSource};
-use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress};
+use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData};
+use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
+use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent};
+use script_traits::webdriver_msg::WebDriverScriptCommand;
use std::borrow::ToOwned;
use std::cell::Cell;
use std::collections::{HashMap, HashSet};
@@ -95,21 +94,21 @@ use std::option::Option;
use std::ptr;
use std::rc::Rc;
use std::result::Result;
-use std::sync::atomic::{Ordering, AtomicBool};
-use std::sync::mpsc::{Receiver, Select, Sender, channel};
use std::sync::{Arc, Mutex};
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::mpsc::{Receiver, Select, Sender, channel};
use style::context::ReflowGoal;
+use style::thread_state;
use task_source::TaskSource;
-use task_source::dom_manipulation::{DOMManipulationTaskSource, DOMManipulationTask};
+use task_source::dom_manipulation::{DOMManipulationTask, DOMManipulationTaskSource};
use task_source::file_reading::FileReadingTaskSource;
use task_source::history_traversal::HistoryTraversalTaskSource;
use task_source::networking::NetworkingTaskSource;
-use task_source::user_interaction::{UserInteractionTaskSource, UserInteractionTask};
+use task_source::user_interaction::{UserInteractionTask, UserInteractionTaskSource};
use time::Tm;
-use url::{Url, Position};
+use url::{Position, Url};
use util::opts;
use util::thread;
-use util::thread_state;
use webdriver_handlers;
thread_local!(pub static STACK_ROOTS: Cell<Option<RootCollectionPtr>> = Cell::new(None));
@@ -132,8 +131,8 @@ pub unsafe fn trace_thread(tr: *mut JSTracer) {
struct InProgressLoad {
/// The pipeline which requested this load.
pipeline_id: PipelineId,
- /// The parent pipeline and child subpage associated with this load, if any.
- parent_info: Option<(PipelineId, SubpageId, FrameType)>,
+ /// The parent pipeline and frame type associated with this load, if any.
+ parent_info: Option<(PipelineId, FrameType)>,
/// The current window size associated with this pipeline.
window_size: Option<WindowSizeData>,
/// Channel to the layout thread associated with this pipeline.
@@ -151,7 +150,7 @@ struct InProgressLoad {
impl InProgressLoad {
/// Create a new InProgressLoad object.
fn new(id: PipelineId,
- parent_info: Option<(PipelineId, SubpageId, FrameType)>,
+ parent_info: Option<(PipelineId, FrameType)>,
layout_chan: Sender<message::Msg>,
window_size: Option<WindowSizeData>,
url: Url) -> InProgressLoad {
@@ -174,10 +173,10 @@ pub struct RunnableWrapper {
}
impl RunnableWrapper {
- pub fn wrap_runnable<T: Runnable + Send + 'static>(&self, runnable: T) -> Box<Runnable + Send> {
+ pub fn wrap_runnable<T: Runnable + Send + 'static>(&self, runnable: Box<T>) -> Box<Runnable + Send> {
box CancellableRunnable {
cancelled: self.cancelled.clone(),
- inner: box runnable,
+ inner: runnable,
}
}
}
@@ -189,8 +188,14 @@ pub struct CancellableRunnable<T: Runnable + Send> {
}
impl<T: Runnable + Send> Runnable for CancellableRunnable<T> {
+ fn name(&self) -> &'static str { self.inner.name() }
+
fn is_cancelled(&self) -> bool {
- self.cancelled.load(Ordering::Relaxed)
+ self.cancelled.load(Ordering::SeqCst)
+ }
+
+ fn main_thread_handler(self: Box<CancellableRunnable<T>>, script_thread: &ScriptThread) {
+ self.inner.main_thread_handler(script_thread);
}
fn handler(self: Box<CancellableRunnable<T>>) {
@@ -200,11 +205,9 @@ impl<T: Runnable + Send> Runnable for CancellableRunnable<T> {
pub trait Runnable {
fn is_cancelled(&self) -> bool { false }
- fn handler(self: Box<Self>);
-}
-
-pub trait MainThreadRunnable {
- fn handler(self: Box<Self>, script_thread: &ScriptThread);
+ fn name(&self) -> &'static str { "generic runnable" }
+ fn handler(self: Box<Self>) {}
+ fn main_thread_handler(self: Box<Self>, _script_thread: &ScriptThread) { self.handler(); }
}
enum MixedMessage {
@@ -212,8 +215,7 @@ enum MixedMessage {
FromScript(MainThreadScriptMsg),
FromDevtools(DevtoolScriptControlMsg),
FromImageCache(ImageCacheResult),
- FromScheduler(TimerEvent),
- FromNetwork(IpcSender<Option<CustomResponse>>),
+ FromScheduler(TimerEvent)
}
/// Messages used to control the script event loop
@@ -338,12 +340,6 @@ pub struct ScriptThread {
/// events in the event queue.
chan: MainThreadScriptChan,
- /// A handle to network event messages
- custom_message_chan: IpcSender<CustomResponseSender>,
-
- /// The port which receives a sender from the network
- custom_message_port: Receiver<CustomResponseSender>,
-
dom_manipulation_task_source: DOMManipulationTaskSource,
user_interaction_task_source: UserInteractionTaskSource,
@@ -397,8 +393,6 @@ pub struct ScriptThread {
timer_event_port: Receiver<TimerEvent>,
content_process_shutdown_chan: IpcSender<()>,
-
- panic_chan: IpcSender<PanicMsg>,
}
/// In the event of thread panic, all data on the stack runs its destructor. However, there
@@ -445,15 +439,15 @@ impl ScriptThreadFactory for ScriptThread {
fn create(state: InitialScriptState,
load_data: LoadData)
-> (Sender<message::Msg>, Receiver<message::Msg>) {
- let panic_chan = state.panic_chan.clone();
let (script_chan, script_port) = channel();
let (sender, receiver) = channel();
let layout_chan = sender.clone();
let pipeline_id = state.id;
- thread::spawn_named_with_send_on_panic(format!("ScriptThread {:?}", state.id),
- thread_state::SCRIPT,
- move || {
+ thread::spawn_named(format!("ScriptThread {:?}", state.id),
+ move || {
+ thread_state::initialize(thread_state::SCRIPT);
+ PipelineId::install(pipeline_id);
PipelineNamespace::install(state.pipeline_namespace_id);
let roots = RootCollection::new();
let _stack_roots_tls = StackRootTLS::new(&roots);
@@ -483,32 +477,26 @@ impl ScriptThreadFactory for ScriptThread {
// This must always be the very last operation performed before the thread completes
failsafe.neuter();
- }, Some(pipeline_id), panic_chan);
+ });
(sender, receiver)
}
}
-pub unsafe extern "C" fn shadow_check_callback(_cx: *mut JSContext,
- _object: HandleObject, _id: HandleId) -> DOMProxyShadowsResult {
- // XXX implement me
- DOMProxyShadowsResult::ShadowCheckFailed
-}
-
impl ScriptThread {
- pub fn page_headers_available(id: &PipelineId, subpage: Option<&SubpageId>, metadata: Option<Metadata>)
+ pub fn page_headers_available(id: &PipelineId, metadata: Option<Metadata>)
-> Option<ParserRoot> {
SCRIPT_THREAD_ROOT.with(|root| {
let script_thread = unsafe { &*root.get().unwrap() };
- script_thread.handle_page_headers_available(id, subpage, metadata)
+ script_thread.handle_page_headers_available(id, metadata)
})
}
// stores a service worker registration
- pub fn set_registration(scope_url: Url, registration:&ServiceWorkerRegistration) {
+ pub fn set_registration(scope_url: Url, registration:&ServiceWorkerRegistration, pipeline_id: PipelineId) {
SCRIPT_THREAD_ROOT.with(|root| {
let script_thread = unsafe { &*root.get().unwrap() };
- script_thread.handle_serviceworker_registration(scope_url, registration);
+ script_thread.handle_serviceworker_registration(scope_url, registration, pipeline_id);
});
}
@@ -558,9 +546,6 @@ impl ScriptThread {
let (ipc_devtools_sender, ipc_devtools_receiver) = ipc::channel().unwrap();
let devtools_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_devtools_receiver);
- let (ipc_custom_resp_chan, ipc_custom_resp_port) = ipc::channel().unwrap();
- let custom_msg_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_custom_resp_port);
-
// Ask the router to proxy IPC messages from the image cache thread to us.
let (ipc_image_cache_channel, ipc_image_cache_port) = ipc::channel().unwrap();
let image_cache_port =
@@ -571,6 +556,8 @@ impl ScriptThread {
// Ask the router to proxy IPC messages from the control port to us.
let control_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(state.control_port);
+ let boxed_script_sender = MainThreadScriptChan(chan.clone()).clone();
+
ScriptThread {
browsing_context: MutNullableHeap::new(None),
incomplete_loads: DOMRefCell::new(vec!()),
@@ -584,22 +571,19 @@ impl ScriptThread {
bluetooth_thread: state.bluetooth_thread,
port: port,
- custom_message_chan: ipc_custom_resp_chan,
- custom_message_port: custom_msg_port,
chan: MainThreadScriptChan(chan.clone()),
dom_manipulation_task_source: DOMManipulationTaskSource(chan.clone()),
user_interaction_task_source: UserInteractionTaskSource(chan.clone()),
networking_task_source: NetworkingTaskSource(chan.clone()),
- history_traversal_task_source: HistoryTraversalTaskSource(chan.clone()),
- file_reading_task_source: FileReadingTaskSource(chan),
+ history_traversal_task_source: HistoryTraversalTaskSource(chan),
+ file_reading_task_source: FileReadingTaskSource(boxed_script_sender),
control_chan: state.control_chan,
control_port: control_port,
constellation_chan: state.constellation_chan,
time_profiler_chan: state.time_profiler_chan,
mem_profiler_chan: state.mem_profiler_chan,
- panic_chan: state.panic_chan,
devtools_chan: state.devtools_chan,
devtools_port: devtools_port,
@@ -647,7 +631,7 @@ impl ScriptThread {
/// Handle incoming control messages.
fn handle_msgs(&self) -> bool {
use self::MixedMessage::{FromConstellation, FromDevtools, FromImageCache};
- use self::MixedMessage::{FromScheduler, FromScript, FromNetwork};
+ use self::MixedMessage::{FromScheduler, FromScript};
// Handle pending resize events.
// Gather them first to avoid a double mut borrow on self.
@@ -660,7 +644,7 @@ impl ScriptThread {
let window = context.active_window();
let resize_event = window.steal_resize_event();
match resize_event {
- Some(size) => resizes.push((window.pipeline(), size)),
+ Some(size) => resizes.push((window.pipeline_id(), size)),
None => ()
}
}
@@ -681,7 +665,6 @@ impl ScriptThread {
let mut timer_event_port = sel.handle(&self.timer_event_port);
let mut devtools_port = sel.handle(&self.devtools_port);
let mut image_cache_port = sel.handle(&self.image_cache_port);
- let mut custom_message_port = sel.handle(&self.custom_message_port);
unsafe {
script_port.add();
control_port.add();
@@ -690,7 +673,6 @@ impl ScriptThread {
devtools_port.add();
}
image_cache_port.add();
- custom_message_port.add();
}
let ret = sel.wait();
if ret == script_port.id() {
@@ -703,8 +685,6 @@ impl ScriptThread {
FromDevtools(self.devtools_port.recv().unwrap())
} else if ret == image_cache_port.id() {
FromImageCache(self.image_cache_port.recv().unwrap())
- } else if ret == custom_message_port.id() {
- FromNetwork(self.custom_message_port.recv().unwrap())
} else {
panic!("unexpected select result")
}
@@ -772,10 +752,7 @@ impl ScriptThread {
Err(_) => match self.timer_event_port.try_recv() {
Err(_) => match self.devtools_port.try_recv() {
Err(_) => match self.image_cache_port.try_recv() {
- Err(_) => match self.custom_message_port.try_recv() {
- Err(_) => break,
- Ok(ev) => event = FromNetwork(ev)
- },
+ Err(_) => break,
Ok(ev) => event = FromImageCache(ev),
},
Ok(ev) => event = FromDevtools(ev),
@@ -801,7 +778,6 @@ impl ScriptThread {
},
FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg),
FromScript(inner_msg) => self.handle_msg_from_script(inner_msg),
- FromNetwork(inner_msg) => self.handle_msg_from_network(inner_msg),
FromScheduler(inner_msg) => self.handle_timer_event(inner_msg),
FromDevtools(inner_msg) => self.handle_msg_from_devtools(inner_msg),
FromImageCache(inner_msg) => self.handle_msg_from_image_cache(inner_msg),
@@ -860,8 +836,7 @@ impl ScriptThread {
_ => ScriptThreadEventCategory::ScriptEvent
}
},
- MixedMessage::FromScheduler(_) => ScriptThreadEventCategory::TimerEvent,
- MixedMessage::FromNetwork(_) => ScriptThreadEventCategory::NetworkEvent
+ MixedMessage::FromScheduler(_) => ScriptThreadEventCategory::TimerEvent
}
}
@@ -902,22 +877,12 @@ impl ScriptThread {
fn handle_msg_from_constellation(&self, msg: ConstellationControlMsg) {
match msg {
- ConstellationControlMsg::AttachLayout(_) =>
- panic!("should have handled AttachLayout already"),
- ConstellationControlMsg::Navigate(pipeline_id, subpage_id, load_data) =>
- self.handle_navigate(pipeline_id, Some(subpage_id), load_data),
+ ConstellationControlMsg::Navigate(parent_pipeline_id, pipeline_id, load_data) =>
+ self.handle_navigate(parent_pipeline_id, Some(pipeline_id), load_data),
ConstellationControlMsg::SendEvent(id, event) =>
self.handle_event(id, event),
ConstellationControlMsg::ResizeInactive(id, new_size) =>
self.handle_resize_inactive_msg(id, new_size),
- ConstellationControlMsg::Viewport(..) =>
- panic!("should have handled Viewport already"),
- ConstellationControlMsg::SetScrollState(..) =>
- panic!("should have handled SetScrollState already"),
- ConstellationControlMsg::Resize(..) =>
- panic!("should have handled Resize already"),
- ConstellationControlMsg::ExitPipeline(..) =>
- panic!("should have handled ExitPipeline already"),
ConstellationControlMsg::GetTitle(pipeline_id) =>
self.handle_get_title_msg(pipeline_id),
ConstellationControlMsg::Freeze(pipeline_id) =>
@@ -926,24 +891,22 @@ impl ScriptThread {
self.handle_thaw_msg(pipeline_id),
ConstellationControlMsg::ChangeFrameVisibilityStatus(pipeline_id, visible) =>
self.handle_visibility_change_msg(pipeline_id, visible),
- ConstellationControlMsg::NotifyVisibilityChange(containing_id, pipeline_id, visible) =>
- self.handle_visibility_change_complete_msg(containing_id, pipeline_id, visible),
+ ConstellationControlMsg::NotifyVisibilityChange(parent_pipeline_id, pipeline_id, visible) =>
+ self.handle_visibility_change_complete_msg(parent_pipeline_id, pipeline_id, visible),
ConstellationControlMsg::MozBrowserEvent(parent_pipeline_id,
- subpage_id,
+ pipeline_id,
event) =>
self.handle_mozbrowser_event_msg(parent_pipeline_id,
- subpage_id,
+ pipeline_id,
event),
- ConstellationControlMsg::UpdateSubpageId(containing_pipeline_id,
- old_subpage_id,
- new_subpage_id,
- new_pipeline_id) =>
- self.handle_update_subpage_id(containing_pipeline_id,
- old_subpage_id,
- new_subpage_id,
- new_pipeline_id),
- ConstellationControlMsg::FocusIFrame(containing_pipeline_id, subpage_id) =>
- self.handle_focus_iframe_msg(containing_pipeline_id, subpage_id),
+ ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
+ old_pipeline_id,
+ new_pipeline_id) =>
+ self.handle_update_pipeline_id(parent_pipeline_id,
+ old_pipeline_id,
+ new_pipeline_id),
+ ConstellationControlMsg::FocusIFrame(parent_pipeline_id, pipeline_id) =>
+ self.handle_focus_iframe_msg(parent_pipeline_id, pipeline_id),
ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, msg) =>
self.handle_webdriver_msg(pipeline_id, msg),
ConstellationControlMsg::TickAllAnimations(pipeline_id) =>
@@ -951,21 +914,27 @@ impl ScriptThread {
ConstellationControlMsg::WebFontLoaded(pipeline_id) =>
self.handle_web_font_loaded(pipeline_id),
ConstellationControlMsg::DispatchFrameLoadEvent {
- target: pipeline_id, parent: containing_id } =>
- self.handle_frame_load_event(containing_id, pipeline_id),
- ConstellationControlMsg::FramedContentChanged(containing_pipeline_id, subpage_id) =>
- self.handle_framed_content_changed(containing_pipeline_id, subpage_id),
+ target: pipeline_id, parent: parent_pipeline_id } =>
+ self.handle_frame_load_event(parent_pipeline_id, pipeline_id),
+ ConstellationControlMsg::FramedContentChanged(parent_pipeline_id, pipeline_id) =>
+ self.handle_framed_content_changed(parent_pipeline_id, pipeline_id),
ConstellationControlMsg::ReportCSSError(pipeline_id, filename, line, column, msg) =>
self.handle_css_error_reporting(pipeline_id, filename, line, column, msg),
ConstellationControlMsg::Reload(pipeline_id) =>
self.handle_reload(pipeline_id),
+ msg @ ConstellationControlMsg::AttachLayout(..) |
+ msg @ ConstellationControlMsg::Viewport(..) |
+ msg @ ConstellationControlMsg::SetScrollState(..) |
+ msg @ ConstellationControlMsg::Resize(..) |
+ msg @ ConstellationControlMsg::ExitPipeline(..) =>
+ panic!("should have handled {:?} already", msg),
}
}
fn handle_msg_from_script(&self, msg: MainThreadScriptMsg) {
match msg {
- MainThreadScriptMsg::Navigate(id, load_data) =>
- self.handle_navigate(id, None, load_data),
+ MainThreadScriptMsg::Navigate(parent_pipeline_id, load_data) =>
+ self.handle_navigate(parent_pipeline_id, None, load_data),
MainThreadScriptMsg::ExitWindow(id) =>
self.handle_exit_window_msg(id),
MainThreadScriptMsg::DocumentLoadsComplete(id) =>
@@ -977,14 +946,12 @@ impl ScriptThread {
runnable.handler()
}
}
- MainThreadScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) =>
- LiveDOMReferences::cleanup(addr),
MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) =>
self.collect_reports(reports_chan),
MainThreadScriptMsg::DOMManipulation(task) =>
task.handle_task(self),
MainThreadScriptMsg::UserInteraction(task) =>
- task.handle_task(),
+ task.handle_task(self),
}
}
@@ -1050,12 +1017,6 @@ impl ScriptThread {
msg.responder.unwrap().respond(msg.image_response);
}
- fn handle_msg_from_network(&self, msg: IpcSender<Option<CustomResponse>>) {
- // We may detect controlling service workers here
- // We send None as default
- let _ = msg.send(None);
- }
-
fn handle_webdriver_msg(&self, pipeline_id: PipelineId, msg: WebDriverScriptCommand) {
let context = self.root_browsing_context();
match msg {
@@ -1102,7 +1063,10 @@ impl ScriptThread {
fn handle_resize(&self, id: PipelineId, size: WindowSizeData, size_type: WindowSizeType) {
if let Some(ref context) = self.find_child_context(id) {
- let window = context.active_window();
+ let window = match context.find(id) {
+ Some(browsing_context) => browsing_context.active_window(),
+ None => return warn!("Message sent to closed pipeline {}.", id),
+ };
window.set_resize_event(size, size_type);
return;
}
@@ -1162,16 +1126,15 @@ impl ScriptThread {
fn handle_new_layout(&self, new_layout_info: NewLayoutInfo) {
let NewLayoutInfo {
- containing_pipeline_id,
+ parent_pipeline_id,
new_pipeline_id,
- subpage_id,
frame_type,
load_data,
paint_chan,
- panic_chan,
pipeline_port,
layout_to_constellation_chan,
content_process_shutdown_chan,
+ layout_threads,
} = new_layout_info;
let layout_pair = channel();
@@ -1184,15 +1147,15 @@ impl ScriptThread {
layout_pair: layout_pair,
pipeline_port: pipeline_port,
constellation_chan: layout_to_constellation_chan,
- panic_chan: panic_chan,
paint_chan: paint_chan,
script_chan: self.control_chan.clone(),
image_cache_thread: self.image_cache_thread.clone(),
content_process_shutdown_chan: content_process_shutdown_chan,
+ layout_threads: layout_threads,
};
let context = self.root_browsing_context();
- let parent_context = context.find(containing_pipeline_id).expect("ScriptThread: received a layout
+ let parent_context = context.find(parent_pipeline_id).expect("ScriptThread: received a layout
whose parent has a PipelineId which does not correspond to a pipeline in the script
thread's browsing context tree. This is a bug.");
let parent_window = parent_context.active_window();
@@ -1203,7 +1166,7 @@ impl ScriptThread {
.unwrap();
// Kick off the fetch for the new resource.
- let new_load = InProgressLoad::new(new_pipeline_id, Some((containing_pipeline_id, subpage_id, frame_type)),
+ let new_load = InProgressLoad::new(new_pipeline_id, Some((parent_pipeline_id, frame_type)),
layout_chan, parent_window.window_size(),
load_data.url.clone());
self.start_page_load(new_load, load_data);
@@ -1223,9 +1186,23 @@ impl ScriptThread {
// https://html.spec.whatwg.org/multipage/#the-end step 7
let handler = box DocumentProgressHandler::new(Trusted::new(doc));
- self.dom_manipulation_task_source.queue(DOMManipulationTask::DocumentProgress(handler)).unwrap();
+ self.dom_manipulation_task_source.queue(handler, GlobalRef::Window(doc.window())).unwrap();
- self.constellation_chan.send(ConstellationMsg::LoadComplete(pipeline)).unwrap();
+ if let Some(fragment) = doc.url().fragment() {
+ self.check_and_scroll_fragment(fragment, pipeline, doc);
+ }
+ }
+
+ fn check_and_scroll_fragment(&self, fragment: &str, pipeline_id: PipelineId, doc: &Document) {
+ match doc.find_fragment_node(fragment) {
+ Some(ref node) => {
+ doc.set_target_element(Some(node.r()));
+ self.scroll_fragment_point(pipeline_id, node.r());
+ }
+ None => {
+ doc.set_target_element(None);
+ }
+ }
}
fn collect_reports(&self, reports_chan: ReportsChan) {
@@ -1274,10 +1251,10 @@ impl ScriptThread {
}
/// Updates iframe element after a change in visibility
- fn handle_visibility_change_complete_msg(&self, containing_id: PipelineId, id: PipelineId, visible: bool) {
+ fn handle_visibility_change_complete_msg(&self, parent_pipeline_id: PipelineId, id: PipelineId, visible: bool) {
if let Some(root_context) = self.browsing_context.get() {
- if let Some(ref inner_context) = root_context.find(containing_id) {
- if let Some(iframe) = inner_context.active_document().find_iframe_by_pipeline(id) {
+ if let Some(ref inner_context) = root_context.find(parent_pipeline_id) {
+ if let Some(iframe) = inner_context.active_document().find_iframe(id) {
iframe.change_visibility_status(visible);
}
}
@@ -1343,12 +1320,12 @@ impl ScriptThread {
fn handle_focus_iframe_msg(&self,
parent_pipeline_id: PipelineId,
- subpage_id: SubpageId) {
+ pipeline_id: PipelineId) {
let borrowed_context = self.root_browsing_context();
let context = borrowed_context.find(parent_pipeline_id).unwrap();
let doc = context.active_document();
- let frame_element = doc.find_iframe(subpage_id);
+ let frame_element = doc.find_iframe(pipeline_id);
if let Some(ref frame_element) = frame_element {
doc.begin_focus_transaction();
@@ -1359,11 +1336,11 @@ impl ScriptThread {
fn handle_framed_content_changed(&self,
parent_pipeline_id: PipelineId,
- subpage_id: SubpageId) {
+ pipeline_id: PipelineId) {
let root_context = self.root_browsing_context();
let context = root_context.find(parent_pipeline_id).unwrap();
let doc = context.active_document();
- let frame_element = doc.find_iframe(subpage_id);
+ let frame_element = doc.find_iframe(pipeline_id);
if let Some(ref frame_element) = frame_element {
frame_element.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
let window = context.active_window();
@@ -1377,33 +1354,32 @@ impl ScriptThread {
/// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart
fn handle_mozbrowser_event_msg(&self,
parent_pipeline_id: PipelineId,
- subpage_id: SubpageId,
+ pipeline_id: Option<PipelineId>,
event: MozBrowserEvent) {
- let borrowed_context = self.root_browsing_context();
-
- let frame_element = borrowed_context.find(parent_pipeline_id).and_then(|context| {
- let doc = context.active_document();
- doc.find_iframe(subpage_id)
- });
-
- if let Some(ref frame_element) = frame_element {
- frame_element.dispatch_mozbrowser_event(event);
+ match self.root_browsing_context().find(parent_pipeline_id) {
+ None => warn!("Mozbrowser event after pipeline {:?} closed.", parent_pipeline_id),
+ Some(context) => match pipeline_id {
+ None => context.active_window().dispatch_mozbrowser_event(event),
+ Some(pipeline_id) => match context.active_document().find_iframe(pipeline_id) {
+ None => warn!("Mozbrowser event after iframe {:?}/{:?} closed.", parent_pipeline_id, pipeline_id),
+ Some(frame_element) => frame_element.dispatch_mozbrowser_event(event),
+ },
+ },
}
}
- fn handle_update_subpage_id(&self,
- containing_pipeline_id: PipelineId,
- old_subpage_id: SubpageId,
- new_subpage_id: SubpageId,
- new_pipeline_id: PipelineId) {
+ fn handle_update_pipeline_id(&self,
+ parent_pipeline_id: PipelineId,
+ old_pipeline_id: PipelineId,
+ new_pipeline_id: PipelineId) {
let borrowed_context = self.root_browsing_context();
- let frame_element = borrowed_context.find(containing_pipeline_id).and_then(|context| {
+ let frame_element = borrowed_context.find(parent_pipeline_id).and_then(|context| {
let doc = context.active_document();
- doc.find_iframe(old_subpage_id)
+ doc.find_iframe(old_pipeline_id)
});
- frame_element.unwrap().update_subpage_id(new_subpage_id, new_pipeline_id);
+ frame_element.unwrap().update_pipeline_id(new_pipeline_id);
}
/// Window was resized, but this script was not active, so don't reflow yet
@@ -1432,11 +1408,9 @@ impl ScriptThread {
/// We have received notification that the response associated with a load has completed.
/// Kick off the document and frame tree creation process using the result.
- fn handle_page_headers_available(&self, id: &PipelineId, subpage: Option<&SubpageId>,
+ fn handle_page_headers_available(&self, id: &PipelineId,
metadata: Option<Metadata>) -> Option<ParserRoot> {
- let idx = self.incomplete_loads.borrow().iter().position(|load| {
- load.pipeline_id == *id && load.parent_info.as_ref().map(|info| &info.1) == subpage
- });
+ let idx = self.incomplete_loads.borrow().iter().position(|load| { load.pipeline_id == *id });
// The matching in progress load structure may not exist if
// the pipeline exited before the page load completed.
match idx {
@@ -1451,8 +1425,33 @@ impl ScriptThread {
}
}
- fn handle_serviceworker_registration(&self, scope: Url, registration: &ServiceWorkerRegistration) {
- self.registration_map.borrow_mut().insert(scope, JS::from_ref(registration));
+ fn handle_serviceworker_registration(&self,
+ scope: Url,
+ registration: &ServiceWorkerRegistration,
+ pipeline_id: PipelineId) {
+ {
+ let ref mut reg_ref = *self.registration_map.borrow_mut();
+ // according to spec we should replace if an older registration exists for
+ // same scope otherwise just insert the new one
+ let _ = reg_ref.remove(&scope);
+ reg_ref.insert(scope.clone(), JS::from_ref(registration));
+ }
+
+ // send ScopeThings to sw-manager
+ let ref maybe_registration_ref = *self.registration_map.borrow();
+ let maybe_registration = match maybe_registration_ref.get(&scope) {
+ Some(r) => r,
+ None => return
+ };
+ if let Some(context) = self.root_browsing_context().find(pipeline_id) {
+ let window = context.active_window();
+ let global_ref = GlobalRef::Window(window.r());
+ let script_url = maybe_registration.get_installed().get_script_url();
+ let scope_things = ServiceWorkerRegistration::create_scope_things(global_ref, script_url);
+ let _ = self.constellation_chan.send(ConstellationMsg::RegisterServiceWorker(scope_things, scope));
+ } else {
+ warn!("Registration failed for {}", scope);
+ }
}
/// Handles a request for the window title.
@@ -1497,7 +1496,7 @@ impl ScriptThread {
// If root is being exited, shut down all contexts
let context = self.root_browsing_context();
let window = context.active_window();
- if window.pipeline() == id {
+ if window.pipeline_id() == id {
debug!("shutting down layout for root context {:?}", id);
shut_down_layout(&context);
let _ = self.constellation_chan.send(ConstellationMsg::PipelineExited(id));
@@ -1529,12 +1528,12 @@ impl ScriptThread {
}
/// Notify the containing document of a child frame that has completed loading.
- fn handle_frame_load_event(&self, containing_pipeline: PipelineId, id: PipelineId) {
- let document = match self.root_browsing_context().find(containing_pipeline) {
+ fn handle_frame_load_event(&self, parent_pipeline_id: PipelineId, id: PipelineId) {
+ let document = match self.root_browsing_context().find(parent_pipeline_id) {
Some(browsing_context) => browsing_context.active_document(),
- None => return warn!("Message sent to closed pipeline {}.", containing_pipeline),
+ None => return warn!("Message sent to closed pipeline {}.", parent_pipeline_id),
};
- if let Some(iframe) = document.find_iframe_by_pipeline(id) {
+ if let Some(iframe) = document.find_iframe(id) {
iframe.iframe_load_event_steps(id);
}
}
@@ -1556,7 +1555,7 @@ impl ScriptThread {
}
debug!("ScriptThread: loading {} on pipeline {:?}", incomplete.url, incomplete.pipeline_id);
- let frame_element = incomplete.parent_info.and_then(|(parent_id, subpage_id, _)| {
+ let frame_element = incomplete.parent_info.and_then(|(parent_id, _)| {
// The root context may not exist yet, if the parent of this frame
// exists in a different script thread.
let root_context = self.browsing_context.get();
@@ -1571,7 +1570,7 @@ impl ScriptThread {
root_context.and_then(|root_context| {
root_context.find(parent_id).and_then(|context| {
let doc = context.active_document();
- doc.find_iframe(subpage_id)
+ doc.find_iframe(incomplete.pipeline_id)
})
})
});
@@ -1581,7 +1580,6 @@ impl ScriptThread {
let UserInteractionTaskSource(ref user_sender) = self.user_interaction_task_source;
let NetworkingTaskSource(ref network_sender) = self.networking_task_source;
let HistoryTraversalTaskSource(ref history_sender) = self.history_traversal_task_source;
- let FileReadingTaskSource(ref file_sender) = self.file_reading_task_source;
let (ipc_timer_event_chan, ipc_timer_event_port) = ipc::channel().unwrap();
ROUTER.route_ipc_receiver_to_mpsc_sender(ipc_timer_event_port,
@@ -1594,9 +1592,8 @@ impl ScriptThread {
UserInteractionTaskSource(user_sender.clone()),
NetworkingTaskSource(network_sender.clone()),
HistoryTraversalTaskSource(history_sender.clone()),
- FileReadingTaskSource(file_sender.clone()),
+ self.file_reading_task_source.clone(),
self.image_cache_channel.clone(),
- self.custom_message_chan.clone(),
self.image_cache_thread.clone(),
self.resource_threads.clone(),
self.bluetooth_thread.clone(),
@@ -1606,7 +1603,6 @@ impl ScriptThread {
self.constellation_chan.clone(),
self.control_chan.clone(),
self.scheduler_chan.clone(),
- self.panic_chan.clone(),
ipc_timer_event_chan,
incomplete.layout_chan,
incomplete.pipeline_id,
@@ -1662,7 +1658,7 @@ impl ScriptThread {
// We have a new root frame tree.
self.browsing_context.set(Some(&new_context));
(new_context, ContextToRemove::Root)
- } else if let Some((parent, _, _)) = incomplete.parent_info {
+ } else if let Some((parent, _)) = incomplete.parent_info {
// Create a new context tree entry. This will be a child context.
let new_context = BrowsingContext::new(&window, frame_element, incomplete.pipeline_id);
@@ -1685,7 +1681,7 @@ impl ScriptThread {
headers.get().map(|&LastModified(HttpDate(ref tm))| dom_last_modified(tm))
});
- let content_type = metadata.content_type.as_ref().and_then(|&ContentType(ref mimetype)| {
+ let content_type = metadata.content_type.as_ref().and_then(|&Serde(ContentType(ref mimetype))| {
match *mimetype {
Mime(TopLevel::Application, SubLevel::Xml, _) |
Mime(TopLevel::Application, SubLevel::Ext(_), _) |
@@ -1696,16 +1692,40 @@ impl ScriptThread {
});
let loader = DocumentLoader::new_with_threads(self.resource_threads.clone(),
- Some(browsing_context.pipeline()),
+ Some(browsing_context.pipeline_id()),
Some(incomplete.url.clone()));
let is_html_document = match metadata.content_type {
- Some(ContentType(Mime(TopLevel::Application, SubLevel::Xml, _))) |
- Some(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _))) =>
+ Some(Serde(ContentType(Mime(TopLevel::Application, SubLevel::Xml, _)))) |
+ Some(Serde(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _)))) =>
IsHTMLDocument::NonHTMLDocument,
_ => IsHTMLDocument::HTMLDocument,
};
+ let referrer = match metadata.referrer {
+ Some(ref referrer) => Some(referrer.clone().into_string()),
+ None => None,
+ };
+
+ let referrer_policy = if let Some(headers) = metadata.headers {
+ headers.get::<ReferrerPolicyHeader>().map(|h| match *h {
+ ReferrerPolicyHeader::NoReferrer =>
+ ReferrerPolicy::NoReferrer,
+ ReferrerPolicyHeader::NoReferrerWhenDowngrade =>
+ ReferrerPolicy::NoReferrerWhenDowngrade,
+ ReferrerPolicyHeader::SameOrigin =>
+ ReferrerPolicy::SameOrigin,
+ ReferrerPolicyHeader::Origin =>
+ ReferrerPolicy::Origin,
+ ReferrerPolicyHeader::OriginWhenCrossOrigin =>
+ ReferrerPolicy::OriginWhenCrossOrigin,
+ ReferrerPolicyHeader::UnsafeUrl =>
+ ReferrerPolicy::UnsafeUrl,
+ })
+ } else {
+ None
+ };
+
let document = Document::new(window.r(),
Some(&browsing_context),
Some(final_url.clone()),
@@ -1713,7 +1733,9 @@ impl ScriptThread {
content_type,
last_modified,
DocumentSource::FromParser,
- loader);
+ loader,
+ referrer,
+ referrer_policy);
if using_new_context {
browsing_context.init(&document);
} else {
@@ -1726,7 +1748,7 @@ impl ScriptThread {
.unwrap();
// Notify devtools that a new script global exists.
- self.notify_devtools(document.Title(), final_url.clone(), (browsing_context.pipeline(), None));
+ self.notify_devtools(document.Title(), final_url.clone(), (browsing_context.pipeline_id(), None));
let is_javascript = incomplete.url.scheme() == "javascript";
let parse_input = if is_javascript {
@@ -1747,12 +1769,15 @@ impl ScriptThread {
// Script source is ready to be evaluated (11.)
unsafe {
let _ac = JSAutoCompartment::new(self.get_cx(), window.reflector().get_jsobject().get());
- let mut jsval = RootedValue::new(self.get_cx(), UndefinedValue());
+ rooted!(in(self.get_cx()) let mut jsval = UndefinedValue());
window.evaluate_js_on_global_with_result(&script_source, jsval.handle_mut());
let strval = DOMString::from_jsval(self.get_cx(),
jsval.handle(),
StringificationBehavior::Empty);
- strval.unwrap_or(DOMString::new())
+ match strval {
+ Ok(ConversionResult::Success(s)) => s,
+ _ => DOMString::new(),
+ }
}
} else {
DOMString::new()
@@ -1761,11 +1786,11 @@ impl ScriptThread {
document.set_https_state(metadata.https_state);
let is_xml = match metadata.content_type {
- Some(ContentType(Mime(TopLevel::Application, SubLevel::Ext(ref sub_level), _)))
+ Some(Serde(ContentType(Mime(TopLevel::Application, SubLevel::Ext(ref sub_level), _))))
if sub_level.ends_with("+xml") => true,
- Some(ContentType(Mime(TopLevel::Application, SubLevel::Xml, _))) |
- Some(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _))) => true,
+ Some(Serde(ContentType(Mime(TopLevel::Application, SubLevel::Xml, _)))) |
+ Some(Serde(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _)))) => true,
_ => false,
};
@@ -1787,7 +1812,7 @@ impl ScriptThread {
}
if !incomplete.is_visible {
- self.alter_resource_utilization(browsing_context.pipeline(), false);
+ self.alter_resource_utilization(browsing_context.pipeline_id(), false);
}
context_remover.neuter();
@@ -1937,12 +1962,12 @@ impl ScriptThread {
document.r().handle_touchpad_pressure_event(self.js_runtime.rt(), point, pressure, phase);
}
- KeyEvent(key, state, modifiers) => {
+ KeyEvent(ch, key, state, modifiers) => {
let document = match self.root_browsing_context().find(pipeline_id) {
Some(browsing_context) => browsing_context.active_document(),
None => return warn!("Message sent to closed pipeline {}.", pipeline_id),
};
- document.dispatch_key_event(key, state, modifiers, &self.constellation_chan);
+ document.dispatch_key_event(ch, key, state, modifiers, &self.constellation_chan);
}
}
}
@@ -1975,35 +2000,30 @@ impl ScriptThread {
/// https://html.spec.whatwg.org/multipage/#navigating-across-documents
/// The entry point for content to notify that a new load has been requested
/// for the given pipeline (specifically the "navigate" algorithm).
- fn handle_navigate(&self, pipeline_id: PipelineId, subpage_id: Option<SubpageId>, load_data: LoadData) {
- // Step 8.
+ fn handle_navigate(&self, parent_pipeline_id: PipelineId, pipeline_id: Option<PipelineId>, load_data: LoadData) {
+ // Step 7.
{
let nurl = &load_data.url;
if let Some(fragment) = nurl.fragment() {
- let document = match self.root_browsing_context().find(pipeline_id) {
+ let document = match self.root_browsing_context().find(parent_pipeline_id) {
Some(browsing_context) => browsing_context.active_document(),
- None => return warn!("Message sent to closed pipeline {}.", pipeline_id),
+ None => return warn!("Message sent to closed pipeline {}.", parent_pipeline_id),
};
let url = document.url();
if &url[..Position::AfterQuery] == &nurl[..Position::AfterQuery] &&
load_data.method == Method::Get {
- match document.find_fragment_node(fragment) {
- Some(ref node) => {
- self.scroll_fragment_point(pipeline_id, node.r());
- }
- None => {}
- }
+ self.check_and_scroll_fragment(fragment, parent_pipeline_id, document.r());
return;
}
}
}
- match subpage_id {
- Some(subpage_id) => {
+ match pipeline_id {
+ Some(pipeline_id) => {
let root_context = self.root_browsing_context();
- let iframe = root_context.find(pipeline_id).and_then(|context| {
+ let iframe = root_context.find(parent_pipeline_id).and_then(|context| {
let doc = context.active_document();
- doc.find_iframe(subpage_id)
+ doc.find_iframe(pipeline_id)
});
if let Some(iframe) = iframe.r() {
iframe.navigate_or_reload_child_browsing_context(Some(load_data));
@@ -2011,7 +2031,7 @@ impl ScriptThread {
}
None => {
self.constellation_chan
- .send(ConstellationMsg::LoadUrl(pipeline_id, load_data))
+ .send(ConstellationMsg::LoadUrl(parent_pipeline_id, load_data))
.unwrap();
}
}
@@ -2050,13 +2070,13 @@ impl ScriptThread {
/// argument until a notification is received that the fetch is complete.
fn start_page_load(&self, incomplete: InProgressLoad, mut load_data: LoadData) {
let id = incomplete.pipeline_id.clone();
- let subpage = incomplete.parent_info.clone().map(|p| p.1);
- let context = Arc::new(Mutex::new(ParserContext::new(id, subpage, load_data.url.clone())));
+ let context = Arc::new(Mutex::new(ParserContext::new(id, load_data.url.clone())));
let (action_sender, action_receiver) = ipc::channel().unwrap();
let listener = NetworkListener {
context: context,
script_chan: self.chan.clone(),
+ wrapper: None,
};
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
listener.notify_action(message.to().unwrap());
@@ -2080,8 +2100,7 @@ impl ScriptThread {
pipeline_id: Some(id),
credentials_flag: true,
referrer_policy: load_data.referrer_policy,
- referrer_url: load_data.referrer_url,
- source: RequestSource::Window(self.custom_message_chan.clone())
+ referrer_url: load_data.referrer_url
}, LoadConsumer::Listener(response_target), None)).unwrap();
self.incomplete_loads.borrow_mut().push(incomplete);
@@ -2173,7 +2192,7 @@ fn shut_down_layout(context_tree: &BrowsingContext) {
let chan = window.layout_chan().clone();
if chan.send(message::Msg::PrepareToExit(response_chan)).is_ok() {
channels.push(chan);
- response_port.recv().unwrap();
+ let _ = response_port.recv();
}
}
@@ -2192,15 +2211,6 @@ fn shut_down_layout(context_tree: &BrowsingContext) {
}
}
-// TODO: remove this function, as it's a source of panic.
-pub fn get_browsing_context(context: &BrowsingContext,
- pipeline_id: PipelineId)
- -> Root<BrowsingContext> {
- context.find(pipeline_id).expect("ScriptThread: received an event \
- message for a layout channel that is not associated with this script thread.\
- This is a bug.")
-}
-
fn dom_last_modified(tm: &Tm) -> String {
tm.to_local().strftime("%m/%d/%Y %H:%M:%S").unwrap().to_string()
}