mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Auto merge of #11727 - creativcoder:swmanager, r=jdm
Integrate service worker manager thread <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes are part of #11091 <!-- Either: --> - [X] There are tests for these changes at my [gh-pages](https://github.com/creativcoder/gsoc16/tree/gh-pages) branch to test the instantiation of service workers by their manager, but will need to discuss how that would integrate into master. Changes: - Introduces a `ServiceWorkerManager`, which maintains an map of registered service workers as well as a map of active workers keyed by their `scope_url`. - Adds the initialization of ServiceWorkerManager, at the `script::init()`, which makes it available as a single entity listening for requests from different script threads. - Adds a timeout thread in `serviceworkerglobalscope`, which terminates the workers, after a timeout of 60 secs, thereby removing it from the active workers list. - Adds the matching of scope urls, in longest prefix way rather than path structural way, according to [spec](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#scope-match-algorithm). - Make ServiceWorkerManager, the holder of network sender, instead of script thread, so it can send `CustomResponse`. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11727) <!-- Reviewable:end -->
This commit is contained in:
commit
513811f6b4
39 changed files with 780 additions and 582 deletions
|
@ -41,13 +41,14 @@ use pipeline::{ChildProcess, InitialPipelineState, Pipeline};
|
||||||
use profile_traits::mem;
|
use profile_traits::mem;
|
||||||
use profile_traits::time;
|
use profile_traits::time;
|
||||||
use rand::{random, Rng, SeedableRng, StdRng};
|
use rand::{random, Rng, SeedableRng, StdRng};
|
||||||
use script_traits::webdriver_msg;
|
|
||||||
use script_traits::{AnimationState, AnimationTickType, CompositorEvent};
|
use script_traits::{AnimationState, AnimationTickType, CompositorEvent};
|
||||||
use script_traits::{ConstellationControlMsg, ConstellationMsg as FromCompositorMsg};
|
use script_traits::{ConstellationControlMsg, ConstellationMsg as FromCompositorMsg};
|
||||||
use script_traits::{DocumentState, LayoutControlMsg};
|
use script_traits::{DocumentState, LayoutControlMsg};
|
||||||
use script_traits::{IFrameLoadInfo, IFrameSandboxState, TimerEventRequest};
|
use script_traits::{IFrameLoadInfo, IFrameSandboxState, TimerEventRequest};
|
||||||
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
|
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
|
||||||
use script_traits::{LogEntry, MozBrowserEvent, MozBrowserErrorType, WebDriverCommandMsg, WindowSizeData};
|
use script_traits::{MozBrowserEvent, MozBrowserErrorType, WebDriverCommandMsg, WindowSizeData};
|
||||||
|
use script_traits::{ScopeThings, SWManagerMsg};
|
||||||
|
use script_traits::{webdriver_msg, LogEntry, ServiceWorkerMsg};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::io::Error as IOError;
|
use std::io::Error as IOError;
|
||||||
|
@ -125,6 +126,15 @@ pub struct Constellation<Message, LTF, STF> {
|
||||||
/// A channel through which messages can be sent to the bluetooth thread.
|
/// A channel through which messages can be sent to the bluetooth thread.
|
||||||
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
||||||
|
|
||||||
|
/// Sender to Service Worker Manager thread
|
||||||
|
swmanager_chan: Option<IpcSender<ServiceWorkerMsg>>,
|
||||||
|
|
||||||
|
/// to send messages to this object
|
||||||
|
swmanager_sender: IpcSender<SWManagerMsg>,
|
||||||
|
|
||||||
|
/// to receive sw manager message
|
||||||
|
swmanager_receiver: Receiver<SWManagerMsg>,
|
||||||
|
|
||||||
/// A list of all the pipelines. (See the `pipeline` module for more details.)
|
/// A list of all the pipelines. (See the `pipeline` module for more details.)
|
||||||
pipelines: HashMap<PipelineId, Pipeline>,
|
pipelines: HashMap<PipelineId, Pipeline>,
|
||||||
|
|
||||||
|
@ -410,9 +420,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
where LTF: LayoutThreadFactory<Message=Message>,
|
where LTF: LayoutThreadFactory<Message=Message>,
|
||||||
STF: ScriptThreadFactory<Message=Message>
|
STF: ScriptThreadFactory<Message=Message>
|
||||||
{
|
{
|
||||||
pub fn start(state: InitialConstellationState) -> Sender<FromCompositorMsg> {
|
pub fn start(state: InitialConstellationState) -> (Sender<FromCompositorMsg>, IpcSender<SWManagerMsg>) {
|
||||||
let (compositor_sender, compositor_receiver) = channel();
|
let (compositor_sender, compositor_receiver) = channel();
|
||||||
|
|
||||||
|
// service worker manager to communicate with constellation
|
||||||
|
let (swmanager_sender, swmanager_receiver) = ipc::channel().expect("ipc channel failure");
|
||||||
|
let sw_mgr_clone = swmanager_sender.clone();
|
||||||
|
|
||||||
spawn_named("Constellation".to_owned(), move || {
|
spawn_named("Constellation".to_owned(), move || {
|
||||||
let (ipc_script_sender, ipc_script_receiver) = ipc::channel().expect("ipc channel failure");
|
let (ipc_script_sender, ipc_script_receiver) = ipc::channel().expect("ipc channel failure");
|
||||||
let script_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_script_receiver);
|
let script_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_script_receiver);
|
||||||
|
@ -423,6 +437,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
let (ipc_panic_sender, ipc_panic_receiver) = ipc::channel().expect("ipc channel failure");
|
let (ipc_panic_sender, ipc_panic_receiver) = ipc::channel().expect("ipc channel failure");
|
||||||
let panic_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_panic_receiver);
|
let panic_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_panic_receiver);
|
||||||
|
|
||||||
|
let swmanager_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(swmanager_receiver);
|
||||||
|
|
||||||
let mut constellation: Constellation<Message, LTF, STF> = Constellation {
|
let mut constellation: Constellation<Message, LTF, STF> = Constellation {
|
||||||
script_sender: ipc_script_sender,
|
script_sender: ipc_script_sender,
|
||||||
layout_sender: ipc_layout_sender,
|
layout_sender: ipc_layout_sender,
|
||||||
|
@ -438,6 +454,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
private_resource_threads: state.private_resource_threads,
|
private_resource_threads: state.private_resource_threads,
|
||||||
image_cache_thread: state.image_cache_thread,
|
image_cache_thread: state.image_cache_thread,
|
||||||
font_cache_thread: state.font_cache_thread,
|
font_cache_thread: state.font_cache_thread,
|
||||||
|
swmanager_chan: None,
|
||||||
|
swmanager_receiver: swmanager_receiver,
|
||||||
|
swmanager_sender: sw_mgr_clone,
|
||||||
pipelines: HashMap::new(),
|
pipelines: HashMap::new(),
|
||||||
frames: HashMap::new(),
|
frames: HashMap::new(),
|
||||||
subpage_map: HashMap::new(),
|
subpage_map: HashMap::new(),
|
||||||
|
@ -482,7 +501,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
PipelineNamespace::install(namespace_id);
|
PipelineNamespace::install(namespace_id);
|
||||||
constellation.run();
|
constellation.run();
|
||||||
});
|
});
|
||||||
compositor_sender
|
(compositor_sender, swmanager_sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&mut self) {
|
fn run(&mut self) {
|
||||||
|
@ -534,6 +553,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
compositor_proxy: self.compositor_proxy.clone_compositor_proxy(),
|
compositor_proxy: self.compositor_proxy.clone_compositor_proxy(),
|
||||||
devtools_chan: self.devtools_chan.clone(),
|
devtools_chan: self.devtools_chan.clone(),
|
||||||
bluetooth_thread: self.bluetooth_thread.clone(),
|
bluetooth_thread: self.bluetooth_thread.clone(),
|
||||||
|
swmanager_thread: self.swmanager_sender.clone(),
|
||||||
image_cache_thread: self.image_cache_thread.clone(),
|
image_cache_thread: self.image_cache_thread.clone(),
|
||||||
font_cache_thread: self.font_cache_thread.clone(),
|
font_cache_thread: self.font_cache_thread.clone(),
|
||||||
resource_threads: resource_threads,
|
resource_threads: resource_threads,
|
||||||
|
@ -607,6 +627,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
Compositor(FromCompositorMsg),
|
Compositor(FromCompositorMsg),
|
||||||
Layout(FromLayoutMsg),
|
Layout(FromLayoutMsg),
|
||||||
Panic(PanicMsg),
|
Panic(PanicMsg),
|
||||||
|
FromSWManager(SWManagerMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get one incoming request.
|
// Get one incoming request.
|
||||||
|
@ -625,6 +646,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
let receiver_from_compositor = &self.compositor_receiver;
|
let receiver_from_compositor = &self.compositor_receiver;
|
||||||
let receiver_from_layout = &self.layout_receiver;
|
let receiver_from_layout = &self.layout_receiver;
|
||||||
let receiver_from_panic = &self.panic_receiver;
|
let receiver_from_panic = &self.panic_receiver;
|
||||||
|
let receiver_from_swmanager = &self.swmanager_receiver;
|
||||||
select! {
|
select! {
|
||||||
msg = receiver_from_script.recv() =>
|
msg = receiver_from_script.recv() =>
|
||||||
Request::Script(msg.expect("Unexpected script channel panic in constellation")),
|
Request::Script(msg.expect("Unexpected script channel panic in constellation")),
|
||||||
|
@ -633,7 +655,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
msg = receiver_from_layout.recv() =>
|
msg = receiver_from_layout.recv() =>
|
||||||
Request::Layout(msg.expect("Unexpected layout channel panic in constellation")),
|
Request::Layout(msg.expect("Unexpected layout channel panic in constellation")),
|
||||||
msg = receiver_from_panic.recv() =>
|
msg = receiver_from_panic.recv() =>
|
||||||
Request::Panic(msg.expect("Unexpected panic channel panic in constellation"))
|
Request::Panic(msg.expect("Unexpected panic channel panic in constellation")),
|
||||||
|
msg = receiver_from_swmanager.recv() =>
|
||||||
|
Request::FromSWManager(msg.expect("Unexpected panic channel panic in constellation"))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -650,6 +674,18 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
Request::Panic(message) => {
|
Request::Panic(message) => {
|
||||||
self.handle_request_from_panic(message);
|
self.handle_request_from_panic(message);
|
||||||
},
|
},
|
||||||
|
Request::FromSWManager(message) => {
|
||||||
|
self.handle_request_from_swmanager(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_request_from_swmanager(&mut self, message: SWManagerMsg) {
|
||||||
|
match message {
|
||||||
|
SWManagerMsg::OwnSender(sw_sender) => {
|
||||||
|
// store service worker manager for communicating with it.
|
||||||
|
self.swmanager_chan = Some(sw_sender);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,6 +959,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
FromScriptMsg::GetScrollOffset(pid, lid, send) => {
|
FromScriptMsg::GetScrollOffset(pid, lid, send) => {
|
||||||
self.compositor_proxy.send(ToCompositorMsg::GetScrollOffset(pid, lid, send));
|
self.compositor_proxy.send(ToCompositorMsg::GetScrollOffset(pid, lid, send));
|
||||||
}
|
}
|
||||||
|
FromScriptMsg::RegisterServiceWorker(scope_things, scope) => {
|
||||||
|
debug!("constellation got store registration scope message");
|
||||||
|
self.handle_register_serviceworker(scope_things, scope);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -950,6 +990,14 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_register_serviceworker(&self, scope_things: ScopeThings, scope: Url) {
|
||||||
|
if let Some(ref mgr) = self.swmanager_chan {
|
||||||
|
let _ = mgr.send(ServiceWorkerMsg::RegisterServiceWorker(scope_things, scope));
|
||||||
|
} else {
|
||||||
|
warn!("sending scope info to service worker manager failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_exit(&mut self) {
|
fn handle_exit(&mut self) {
|
||||||
// TODO: add a timer, which forces shutdown if threads aren't responsive.
|
// TODO: add a timer, which forces shutdown if threads aren't responsive.
|
||||||
if self.shutting_down { return; }
|
if self.shutting_down { return; }
|
||||||
|
@ -999,6 +1047,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
warn!("Exit bluetooth thread failed ({})", e);
|
warn!("Exit bluetooth thread failed ({})", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("Exiting service worker manager thread.");
|
||||||
|
if let Some(mgr) = self.swmanager_chan.as_ref() {
|
||||||
|
if let Err(e) = mgr.send(ServiceWorkerMsg::Exit) {
|
||||||
|
warn!("Exit service worker manager failed ({})", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
debug!("Exiting font cache thread.");
|
debug!("Exiting font cache thread.");
|
||||||
self.font_cache_thread.exit();
|
self.font_cache_thread.exit();
|
||||||
|
|
||||||
|
|
|
@ -19,13 +19,13 @@ use layers::geometry::DevicePixel;
|
||||||
use layout_traits::LayoutThreadFactory;
|
use layout_traits::LayoutThreadFactory;
|
||||||
use msg::constellation_msg::{FrameId, FrameType, LoadData, PanicMsg, PipelineId};
|
use msg::constellation_msg::{FrameId, FrameType, LoadData, PanicMsg, PipelineId};
|
||||||
use msg::constellation_msg::{PipelineNamespaceId, SubpageId};
|
use msg::constellation_msg::{PipelineNamespaceId, SubpageId};
|
||||||
use net_traits::ResourceThreads;
|
|
||||||
use net_traits::bluetooth_thread::BluetoothMethodMsg;
|
use net_traits::bluetooth_thread::BluetoothMethodMsg;
|
||||||
use net_traits::image_cache_thread::ImageCacheThread;
|
use net_traits::image_cache_thread::ImageCacheThread;
|
||||||
|
use net_traits::{ResourceThreads, IpcSend};
|
||||||
use profile_traits::mem as profile_mem;
|
use profile_traits::mem as profile_mem;
|
||||||
use profile_traits::time;
|
use profile_traits::time;
|
||||||
use script_traits::{ConstellationControlMsg, InitialScriptState, MozBrowserEvent};
|
use script_traits::{ConstellationControlMsg, InitialScriptState, MozBrowserEvent};
|
||||||
use script_traits::{LayoutControlMsg, LayoutMsg, NewLayoutInfo, ScriptMsg};
|
use script_traits::{LayoutControlMsg, LayoutMsg, NewLayoutInfo, ScriptMsg, SWManagerMsg, SWManagerSenders};
|
||||||
use script_traits::{ScriptThreadFactory, TimerEventRequest, WindowSizeData};
|
use script_traits::{ScriptThreadFactory, TimerEventRequest, WindowSizeData};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Error as IOError;
|
use std::io::Error as IOError;
|
||||||
|
@ -99,6 +99,8 @@ pub struct InitialPipelineState {
|
||||||
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
/// A channel to the bluetooth thread.
|
/// A channel to the bluetooth thread.
|
||||||
pub bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
pub bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
||||||
|
/// A channel to the service worker manager thread
|
||||||
|
pub swmanager_thread: IpcSender<SWManagerMsg>,
|
||||||
/// A channel to the image cache thread.
|
/// A channel to the image cache thread.
|
||||||
pub image_cache_thread: ImageCacheThread,
|
pub image_cache_thread: ImageCacheThread,
|
||||||
/// A channel to the font cache thread.
|
/// A channel to the font cache thread.
|
||||||
|
@ -222,6 +224,7 @@ impl Pipeline {
|
||||||
scheduler_chan: state.scheduler_chan,
|
scheduler_chan: state.scheduler_chan,
|
||||||
devtools_chan: script_to_devtools_chan,
|
devtools_chan: script_to_devtools_chan,
|
||||||
bluetooth_thread: state.bluetooth_thread,
|
bluetooth_thread: state.bluetooth_thread,
|
||||||
|
swmanager_thread: state.swmanager_thread,
|
||||||
image_cache_thread: state.image_cache_thread,
|
image_cache_thread: state.image_cache_thread,
|
||||||
font_cache_thread: state.font_cache_thread,
|
font_cache_thread: state.font_cache_thread,
|
||||||
resource_threads: state.resource_threads,
|
resource_threads: state.resource_threads,
|
||||||
|
@ -414,6 +417,7 @@ pub struct UnprivilegedPipelineContent {
|
||||||
scheduler_chan: IpcSender<TimerEventRequest>,
|
scheduler_chan: IpcSender<TimerEventRequest>,
|
||||||
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||||
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
||||||
|
swmanager_thread: IpcSender<SWManagerMsg>,
|
||||||
image_cache_thread: ImageCacheThread,
|
image_cache_thread: ImageCacheThread,
|
||||||
font_cache_thread: FontCacheThread,
|
font_cache_thread: FontCacheThread,
|
||||||
resource_threads: ResourceThreads,
|
resource_threads: ResourceThreads,
|
||||||
|
@ -546,4 +550,11 @@ impl UnprivilegedPipelineContent {
|
||||||
pub fn prefs(&self) -> HashMap<String, Pref> {
|
pub fn prefs(&self) -> HashMap<String, Pref> {
|
||||||
self.prefs.clone()
|
self.prefs.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn swmanager_senders(&self) -> SWManagerSenders {
|
||||||
|
SWManagerSenders {
|
||||||
|
swmanager_sender: self.swmanager_thread.clone(),
|
||||||
|
resource_sender: self.resource_threads.sender()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use font_template::{FontTemplate, FontTemplateDescriptor};
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use mime::{TopLevel, SubLevel};
|
use mime::{TopLevel, SubLevel};
|
||||||
use net_traits::{AsyncResponseTarget, LoadContext, PendingAsyncLoad, CoreResourceThread, ResponseAction, RequestSource};
|
use net_traits::{AsyncResponseTarget, LoadContext, PendingAsyncLoad, CoreResourceThread, ResponseAction};
|
||||||
use platform::font_context::FontContextHandle;
|
use platform::font_context::FontContextHandle;
|
||||||
use platform::font_list::SANS_SERIF_FONT_FAMILY;
|
use platform::font_list::SANS_SERIF_FONT_FAMILY;
|
||||||
use platform::font_list::for_each_available_family;
|
use platform::font_list::for_each_available_family;
|
||||||
|
@ -211,8 +211,7 @@ impl FontCache {
|
||||||
url.clone(),
|
url.clone(),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None);
|
||||||
RequestSource::None);
|
|
||||||
let (data_sender, data_receiver) = ipc::channel().unwrap();
|
let (data_sender, data_receiver) = ipc::channel().unwrap();
|
||||||
let data_target = AsyncResponseTarget {
|
let data_target = AsyncResponseTarget {
|
||||||
sender: data_sender,
|
sender: data_sender,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use mime_classifier::MimeClassifier;
|
||||||
use mime_guess::guess_mime_type;
|
use mime_guess::guess_mime_type;
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
||||||
use net_traits::ProgressMsg::{Done, Payload};
|
use net_traits::ProgressMsg::{Done, Payload};
|
||||||
use net_traits::{LoadConsumer, LoadData, Metadata, NetworkError, LoadOrigin, RequestSource};
|
use net_traits::{LoadConsumer, LoadData, Metadata, NetworkError, LoadOrigin};
|
||||||
use resource_thread::{CancellationListener, ProgressSender};
|
use resource_thread::{CancellationListener, ProgressSender};
|
||||||
use resource_thread::{send_error, start_sending_sniffed_opt};
|
use resource_thread::{send_error, start_sending_sniffed_opt};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
|
@ -39,9 +39,6 @@ impl LoadOrigin for FileLoadOrigin {
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn request_source(&self) -> RequestSource {
|
|
||||||
RequestSource::None
|
|
||||||
}
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ use hyper::method::Method;
|
||||||
use hyper::mime::{Mime, SubLevel, TopLevel};
|
use hyper::mime::{Mime, SubLevel, TopLevel};
|
||||||
use hyper::net::Fresh;
|
use hyper::net::Fresh;
|
||||||
use hyper::status::{StatusClass, StatusCode};
|
use hyper::status::{StatusClass, StatusCode};
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use log;
|
use log;
|
||||||
use mime_classifier::MimeClassifier;
|
use mime_classifier::MimeClassifier;
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
||||||
|
@ -32,7 +32,7 @@ use net_traits::ProgressMsg::{Done, Payload};
|
||||||
use net_traits::hosts::replace_hosts;
|
use net_traits::hosts::replace_hosts;
|
||||||
use net_traits::response::HttpsState;
|
use net_traits::response::HttpsState;
|
||||||
use net_traits::{CookieSource, IncludeSubdomains, LoadConsumer, LoadContext, LoadData};
|
use net_traits::{CookieSource, IncludeSubdomains, LoadConsumer, LoadContext, LoadData};
|
||||||
use net_traits::{Metadata, NetworkError, RequestSource, CustomResponse};
|
use net_traits::{Metadata, NetworkError, CustomResponse, CustomResponseMediator};
|
||||||
use openssl;
|
use openssl;
|
||||||
use openssl::ssl::error::{SslError, OpensslError};
|
use openssl::ssl::error::{SslError, OpensslError};
|
||||||
use profile_traits::time::{ProfilerCategory, profile, ProfilerChan, TimerMetadata};
|
use profile_traits::time::{ProfilerCategory, profile, ProfilerChan, TimerMetadata};
|
||||||
|
@ -59,6 +59,7 @@ pub fn factory(user_agent: String,
|
||||||
http_state: HttpState,
|
http_state: HttpState,
|
||||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
profiler_chan: ProfilerChan,
|
profiler_chan: ProfilerChan,
|
||||||
|
swmanager_chan: Option<IpcSender<CustomResponseMediator>>,
|
||||||
connector: Arc<Pool<Connector>>)
|
connector: Arc<Pool<Connector>>)
|
||||||
-> Box<FnBox(LoadData,
|
-> Box<FnBox(LoadData,
|
||||||
LoadConsumer,
|
LoadConsumer,
|
||||||
|
@ -78,6 +79,7 @@ pub fn factory(user_agent: String,
|
||||||
connector,
|
connector,
|
||||||
http_state,
|
http_state,
|
||||||
devtools_chan,
|
devtools_chan,
|
||||||
|
swmanager_chan,
|
||||||
cancel_listener,
|
cancel_listener,
|
||||||
user_agent)
|
user_agent)
|
||||||
})
|
})
|
||||||
|
@ -131,6 +133,7 @@ fn load_for_consumer(load_data: LoadData,
|
||||||
connector: Arc<Pool<Connector>>,
|
connector: Arc<Pool<Connector>>,
|
||||||
http_state: HttpState,
|
http_state: HttpState,
|
||||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
|
swmanager_chan: Option<IpcSender<CustomResponseMediator>>,
|
||||||
cancel_listener: CancellationListener,
|
cancel_listener: CancellationListener,
|
||||||
user_agent: String) {
|
user_agent: String) {
|
||||||
let factory = NetworkHttpRequestFactory {
|
let factory = NetworkHttpRequestFactory {
|
||||||
|
@ -140,7 +143,7 @@ fn load_for_consumer(load_data: LoadData,
|
||||||
let ui_provider = TFDProvider;
|
let ui_provider = TFDProvider;
|
||||||
match load(&load_data, &ui_provider, &http_state,
|
match load(&load_data, &ui_provider, &http_state,
|
||||||
devtools_chan, &factory,
|
devtools_chan, &factory,
|
||||||
user_agent, &cancel_listener) {
|
user_agent, &cancel_listener, swmanager_chan) {
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
match error.error {
|
match error.error {
|
||||||
LoadErrorType::ConnectionAborted { .. } => unreachable!(),
|
LoadErrorType::ConnectionAborted { .. } => unreachable!(),
|
||||||
|
@ -860,7 +863,8 @@ pub fn load<A, B>(load_data: &LoadData,
|
||||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
request_factory: &HttpRequestFactory<R=A>,
|
request_factory: &HttpRequestFactory<R=A>,
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
cancel_listener: &CancellationListener)
|
cancel_listener: &CancellationListener,
|
||||||
|
swmanager_chan: Option<IpcSender<CustomResponseMediator>>)
|
||||||
-> Result<StreamedResponse, LoadError> where A: HttpRequest + 'static, B: UIProvider {
|
-> Result<StreamedResponse, LoadError> where A: HttpRequest + 'static, B: UIProvider {
|
||||||
let max_redirects = PREFS.get("network.http.redirection-limit").as_i64().unwrap() as u32;
|
let max_redirects = PREFS.get("network.http.redirection-limit").as_i64().unwrap() as u32;
|
||||||
let mut iters = 0;
|
let mut iters = 0;
|
||||||
|
@ -878,17 +882,19 @@ pub fn load<A, B>(load_data: &LoadData,
|
||||||
}
|
}
|
||||||
|
|
||||||
let (msg_sender, msg_receiver) = ipc::channel().unwrap();
|
let (msg_sender, msg_receiver) = ipc::channel().unwrap();
|
||||||
match load_data.source {
|
let response_mediator = CustomResponseMediator {
|
||||||
RequestSource::Window(ref sender) | RequestSource::Worker(ref sender) => {
|
response_chan: msg_sender,
|
||||||
sender.send(msg_sender.clone()).unwrap();
|
load_url: doc_url.clone()
|
||||||
let received_msg = msg_receiver.recv().unwrap();
|
};
|
||||||
if let Some(custom_response) = received_msg {
|
if let Some(sender) = swmanager_chan {
|
||||||
|
let _ = sender.send(response_mediator);
|
||||||
|
if let Ok(Some(custom_response)) = msg_receiver.recv() {
|
||||||
let metadata = Metadata::default(doc_url.clone());
|
let metadata = Metadata::default(doc_url.clone());
|
||||||
let readable_response = to_readable_response(custom_response);
|
let readable_response = to_readable_response(custom_response);
|
||||||
return StreamedResponse::from_http_response(box readable_response, metadata);
|
return StreamedResponse::from_http_response(box readable_response, metadata);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
RequestSource::None => {}
|
debug!("Did not receive a custom response");
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the URL is a view-source scheme then the scheme data contains the
|
// If the URL is a view-source scheme then the scheme data contains the
|
||||||
|
|
|
@ -11,7 +11,7 @@ use net_traits::image_cache_thread::ImageResponder;
|
||||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheCommand, ImageCacheThread, ImageState};
|
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheCommand, ImageCacheThread, ImageState};
|
||||||
use net_traits::image_cache_thread::{ImageCacheResult, ImageOrMetadataAvailable, ImageResponse, UsePlaceholder};
|
use net_traits::image_cache_thread::{ImageCacheResult, ImageOrMetadataAvailable, ImageResponse, UsePlaceholder};
|
||||||
use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadData, CoreResourceThread, LoadOrigin};
|
use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadData, CoreResourceThread, LoadOrigin};
|
||||||
use net_traits::{ResponseAction, LoadContext, NetworkError, RequestSource};
|
use net_traits::{ResponseAction, LoadContext, NetworkError};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
|
@ -313,9 +313,6 @@ impl LoadOrigin for ImageCacheOrigin {
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn request_source(&self) -> RequestSource {
|
|
||||||
RequestSource::None
|
|
||||||
}
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ use net_traits::request::{Request, RequestInit};
|
||||||
use net_traits::storage_thread::StorageThreadMsg;
|
use net_traits::storage_thread::StorageThreadMsg;
|
||||||
use net_traits::{AsyncResponseTarget, Metadata, ProgressMsg, ResponseAction, CoreResourceThread};
|
use net_traits::{AsyncResponseTarget, Metadata, ProgressMsg, ResponseAction, CoreResourceThread};
|
||||||
use net_traits::{CoreResourceMsg, CookieSource, FetchResponseMsg, FetchTaskTarget, LoadConsumer};
|
use net_traits::{CoreResourceMsg, CookieSource, FetchResponseMsg, FetchTaskTarget, LoadConsumer};
|
||||||
use net_traits::{LoadData, LoadResponse, NetworkError, ResourceId};
|
use net_traits::{LoadData, LoadResponse, NetworkError, ResourceId, CustomResponseMediator};
|
||||||
use net_traits::{WebSocketCommunicate, WebSocketConnectData, ResourceThreads};
|
use net_traits::{WebSocketCommunicate, WebSocketConnectData, ResourceThreads};
|
||||||
use profile_traits::time::ProfilerChan;
|
use profile_traits::time::ProfilerChan;
|
||||||
use rustc_serialize::json;
|
use rustc_serialize::json;
|
||||||
|
@ -202,7 +202,7 @@ pub fn new_core_resource_thread(user_agent: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ResourceChannelManager {
|
struct ResourceChannelManager {
|
||||||
resource_manager: CoreResourceManager,
|
resource_manager: CoreResourceManager
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_resource_groups() -> (ResourceGroup, ResourceGroup) {
|
fn create_resource_groups() -> (ResourceGroup, ResourceGroup) {
|
||||||
|
@ -279,6 +279,9 @@ impl ResourceChannelManager {
|
||||||
let mut cookie_jar = group.cookie_jar.write().unwrap();
|
let mut cookie_jar = group.cookie_jar.write().unwrap();
|
||||||
consumer.send(cookie_jar.cookies_for_url(&url, source)).unwrap();
|
consumer.send(cookie_jar.cookies_for_url(&url, source)).unwrap();
|
||||||
}
|
}
|
||||||
|
CoreResourceMsg::NetworkMediator(mediator_chan) => {
|
||||||
|
self.resource_manager.swmanager_chan = Some(mediator_chan)
|
||||||
|
}
|
||||||
CoreResourceMsg::GetCookiesDataForUrl(url, consumer, source) => {
|
CoreResourceMsg::GetCookiesDataForUrl(url, consumer, source) => {
|
||||||
let mut cookie_jar = group.cookie_jar.write().unwrap();
|
let mut cookie_jar = group.cookie_jar.write().unwrap();
|
||||||
let cookies = cookie_jar.cookies_data_for_url(&url, source).collect();
|
let cookies = cookie_jar.cookies_data_for_url(&url, source).collect();
|
||||||
|
@ -456,6 +459,7 @@ pub struct CoreResourceManager {
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
mime_classifier: Arc<MimeClassifier>,
|
mime_classifier: Arc<MimeClassifier>,
|
||||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
|
swmanager_chan: Option<IpcSender<CustomResponseMediator>>,
|
||||||
profiler_chan: ProfilerChan,
|
profiler_chan: ProfilerChan,
|
||||||
filemanager_chan: IpcSender<FileManagerThreadMsg>,
|
filemanager_chan: IpcSender<FileManagerThreadMsg>,
|
||||||
cancel_load_map: HashMap<ResourceId, Sender<()>>,
|
cancel_load_map: HashMap<ResourceId, Sender<()>>,
|
||||||
|
@ -471,6 +475,7 @@ impl CoreResourceManager {
|
||||||
user_agent: user_agent,
|
user_agent: user_agent,
|
||||||
mime_classifier: Arc::new(MimeClassifier::new()),
|
mime_classifier: Arc::new(MimeClassifier::new()),
|
||||||
devtools_chan: devtools_channel,
|
devtools_chan: devtools_channel,
|
||||||
|
swmanager_chan: None,
|
||||||
profiler_chan: profiler_chan,
|
profiler_chan: profiler_chan,
|
||||||
filemanager_chan: filemanager_chan,
|
filemanager_chan: filemanager_chan,
|
||||||
cancel_load_map: HashMap::new(),
|
cancel_load_map: HashMap::new(),
|
||||||
|
@ -542,6 +547,7 @@ impl CoreResourceManager {
|
||||||
http_state,
|
http_state,
|
||||||
self.devtools_chan.clone(),
|
self.devtools_chan.clone(),
|
||||||
self.profiler_chan.clone(),
|
self.profiler_chan.clone(),
|
||||||
|
self.swmanager_chan.clone(),
|
||||||
resource_grp.connector.clone())
|
resource_grp.connector.clone())
|
||||||
},
|
},
|
||||||
"data" => from_factory(data_loader::factory),
|
"data" => from_factory(data_loader::factory),
|
||||||
|
|
|
@ -97,13 +97,10 @@ impl CustomResponse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type CustomResponseSender = IpcSender<Option<CustomResponse>>;
|
#[derive(Clone, Deserialize, Serialize)]
|
||||||
|
pub struct CustomResponseMediator {
|
||||||
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
|
pub response_chan: IpcSender<Option<CustomResponse>>,
|
||||||
pub enum RequestSource {
|
pub load_url: Url
|
||||||
Window(#[ignore_heap_size_of = "Defined in ipc-channel"] IpcSender<CustomResponseSender>),
|
|
||||||
Worker(#[ignore_heap_size_of = "Defined in ipc-channel"] IpcSender<CustomResponseSender>),
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
|
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
|
||||||
|
@ -126,9 +123,7 @@ pub struct LoadData {
|
||||||
pub context: LoadContext,
|
pub context: LoadContext,
|
||||||
/// The policy and referring URL for the originator of this request
|
/// The policy and referring URL for the originator of this request
|
||||||
pub referrer_policy: Option<ReferrerPolicy>,
|
pub referrer_policy: Option<ReferrerPolicy>,
|
||||||
pub referrer_url: Option<Url>,
|
pub referrer_url: Option<Url>
|
||||||
pub source: RequestSource,
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LoadData {
|
impl LoadData {
|
||||||
|
@ -147,7 +142,6 @@ impl LoadData {
|
||||||
context: context,
|
context: context,
|
||||||
referrer_policy: load_origin.referrer_policy(),
|
referrer_policy: load_origin.referrer_policy(),
|
||||||
referrer_url: load_origin.referrer_url().clone(),
|
referrer_url: load_origin.referrer_url().clone(),
|
||||||
source: load_origin.request_source()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +149,6 @@ impl LoadData {
|
||||||
pub trait LoadOrigin {
|
pub trait LoadOrigin {
|
||||||
fn referrer_url(&self) -> Option<Url>;
|
fn referrer_url(&self) -> Option<Url>;
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy>;
|
fn referrer_policy(&self) -> Option<ReferrerPolicy>;
|
||||||
fn request_source(&self) -> RequestSource;
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId>;
|
fn pipeline_id(&self) -> Option<PipelineId>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,6 +429,8 @@ pub enum CoreResourceMsg {
|
||||||
Cancel(ResourceId),
|
Cancel(ResourceId),
|
||||||
/// Synchronization message solely for knowing the state of the ResourceChannelManager loop
|
/// Synchronization message solely for knowing the state of the ResourceChannelManager loop
|
||||||
Synchronize(IpcSender<()>),
|
Synchronize(IpcSender<()>),
|
||||||
|
/// Send the network sender in constellation to CoreResourceThread
|
||||||
|
NetworkMediator(IpcSender<CustomResponseMediator>),
|
||||||
/// Break the load handler loop, send a reply when done cleaning up local resources
|
/// Break the load handler loop, send a reply when done cleaning up local resources
|
||||||
// and exit
|
// and exit
|
||||||
Exit(IpcSender<()>),
|
Exit(IpcSender<()>),
|
||||||
|
@ -451,8 +446,7 @@ pub struct PendingAsyncLoad {
|
||||||
guard: PendingLoadGuard,
|
guard: PendingLoadGuard,
|
||||||
context: LoadContext,
|
context: LoadContext,
|
||||||
referrer_policy: Option<ReferrerPolicy>,
|
referrer_policy: Option<ReferrerPolicy>,
|
||||||
referrer_url: Option<Url>,
|
referrer_url: Option<Url>
|
||||||
source: RequestSource
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PendingLoadGuard {
|
struct PendingLoadGuard {
|
||||||
|
@ -480,9 +474,6 @@ impl LoadOrigin for PendingAsyncLoad {
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
self.referrer_policy.clone()
|
self.referrer_policy.clone()
|
||||||
}
|
}
|
||||||
fn request_source(&self) -> RequestSource {
|
|
||||||
self.source.clone()
|
|
||||||
}
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
self.pipeline
|
self.pipeline
|
||||||
}
|
}
|
||||||
|
@ -494,8 +485,7 @@ impl PendingAsyncLoad {
|
||||||
url: Url,
|
url: Url,
|
||||||
pipeline: Option<PipelineId>,
|
pipeline: Option<PipelineId>,
|
||||||
referrer_policy: Option<ReferrerPolicy>,
|
referrer_policy: Option<ReferrerPolicy>,
|
||||||
referrer_url: Option<Url>,
|
referrer_url: Option<Url>)
|
||||||
source: RequestSource)
|
|
||||||
-> PendingAsyncLoad {
|
-> PendingAsyncLoad {
|
||||||
PendingAsyncLoad {
|
PendingAsyncLoad {
|
||||||
core_resource_thread: core_resource_thread,
|
core_resource_thread: core_resource_thread,
|
||||||
|
@ -504,8 +494,7 @@ impl PendingAsyncLoad {
|
||||||
guard: PendingLoadGuard { loaded: false, },
|
guard: PendingLoadGuard { loaded: false, },
|
||||||
context: context,
|
context: context,
|
||||||
referrer_policy: referrer_policy,
|
referrer_policy: referrer_policy,
|
||||||
referrer_url: referrer_url,
|
referrer_url: referrer_url
|
||||||
source: source
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
use dom::bindings::js::JS;
|
use dom::bindings::js::JS;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
use net_traits::{PendingAsyncLoad, LoadContext};
|
use net_traits::{PendingAsyncLoad, AsyncResponseTarget, LoadContext};
|
||||||
use net_traits::{RequestSource, AsyncResponseTarget};
|
|
||||||
use net_traits::{ResourceThreads, IpcSend};
|
use net_traits::{ResourceThreads, IpcSend};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -130,14 +129,12 @@ impl DocumentLoader {
|
||||||
let context = load.to_load_context();
|
let context = load.to_load_context();
|
||||||
let url = load.url().clone();
|
let url = load.url().clone();
|
||||||
self.add_blocking_load(load);
|
self.add_blocking_load(load);
|
||||||
let client_chan = referrer.window().custom_message_chan();
|
|
||||||
PendingAsyncLoad::new(context,
|
PendingAsyncLoad::new(context,
|
||||||
self.resource_threads.sender(),
|
self.resource_threads.sender(),
|
||||||
url,
|
url,
|
||||||
self.pipeline,
|
self.pipeline,
|
||||||
referrer.get_referrer_policy(),
|
referrer.get_referrer_policy(),
|
||||||
Some(referrer.url().clone()),
|
Some(referrer.url().clone()))
|
||||||
RequestSource::Window(client_chan))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create and initiate a new network request.
|
/// Create and initiate a new network request.
|
||||||
|
|
|
@ -8,10 +8,7 @@ use dom::bindings::str::DOMString;
|
||||||
use dom::bindings::structuredclone::StructuredCloneData;
|
use dom::bindings::structuredclone::StructuredCloneData;
|
||||||
use js::jsapi::{JSRuntime, JS_RequestInterruptCallback};
|
use js::jsapi::{JSRuntime, JS_RequestInterruptCallback};
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
|
||||||
use net_traits::{LoadOrigin, RequestSource};
|
|
||||||
use script_runtime::CommonScriptMsg;
|
use script_runtime::CommonScriptMsg;
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
/// Messages used to control the worker event loops
|
/// Messages used to control the worker event loops
|
||||||
pub enum WorkerScriptMsg {
|
pub enum WorkerScriptMsg {
|
||||||
|
@ -21,29 +18,6 @@ pub enum WorkerScriptMsg {
|
||||||
DOMMessage(StructuredCloneData),
|
DOMMessage(StructuredCloneData),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct WorkerScriptLoadOrigin {
|
|
||||||
pub referrer_url: Option<Url>,
|
|
||||||
pub referrer_policy: Option<ReferrerPolicy>,
|
|
||||||
pub request_source: RequestSource,
|
|
||||||
pub pipeline_id: Option<PipelineId>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LoadOrigin for WorkerScriptLoadOrigin {
|
|
||||||
fn referrer_url(&self) -> Option<Url> {
|
|
||||||
self.referrer_url.clone()
|
|
||||||
}
|
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
|
||||||
self.referrer_policy.clone()
|
|
||||||
}
|
|
||||||
fn request_source(&self) -> RequestSource {
|
|
||||||
self.request_source.clone()
|
|
||||||
}
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
|
||||||
self.pipeline_id.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SimpleWorkerErrorHandler<T: Reflectable> {
|
pub struct SimpleWorkerErrorHandler<T: Reflectable> {
|
||||||
pub addr: Trusted<T>,
|
pub addr: Trusted<T>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue};
|
||||||
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
|
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
|
||||||
use msg::constellation_msg::{PipelineId, PanicMsg};
|
use msg::constellation_msg::{PipelineId, PanicMsg};
|
||||||
use net_traits::filemanager_thread::FileManagerThreadMsg;
|
use net_traits::filemanager_thread::FileManagerThreadMsg;
|
||||||
use net_traits::{ResourceThreads, CoreResourceThread, RequestSource, IpcSend};
|
use net_traits::{ResourceThreads, CoreResourceThread, IpcSend};
|
||||||
use profile_traits::{mem, time};
|
use profile_traits::{mem, time};
|
||||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
|
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
|
||||||
use script_thread::{MainThreadScriptChan, ScriptThread, RunnableWrapper};
|
use script_thread::{MainThreadScriptChan, ScriptThread, RunnableWrapper};
|
||||||
|
@ -66,14 +66,6 @@ impl<'a> GlobalRef<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// gets the custom message channel associated with global object
|
|
||||||
pub fn request_source(&self) -> RequestSource {
|
|
||||||
match *self {
|
|
||||||
GlobalRef::Window(ref window) => RequestSource::Window(window.custom_message_chan()),
|
|
||||||
GlobalRef::Worker(ref worker) => RequestSource::Worker(worker.custom_message_chan()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the `PipelineId` for this global scope.
|
/// Get the `PipelineId` for this global scope.
|
||||||
pub fn pipeline(&self) -> PipelineId {
|
pub fn pipeline(&self) -> PipelineId {
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use devtools;
|
use devtools;
|
||||||
use devtools_traits::DevtoolScriptControlMsg;
|
use devtools_traits::DevtoolScriptControlMsg;
|
||||||
use dom::abstractworker::{WorkerScriptLoadOrigin, WorkerScriptMsg, SharedRt , SimpleWorkerErrorHandler};
|
use dom::abstractworker::{WorkerScriptMsg, SharedRt , SimpleWorkerErrorHandler};
|
||||||
use dom::abstractworkerglobalscope::{SendableWorkerScriptChan, WorkerThreadWorkerChan};
|
use dom::abstractworkerglobalscope::{SendableWorkerScriptChan, WorkerThreadWorkerChan};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding;
|
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding;
|
||||||
|
@ -21,7 +21,6 @@ use dom::bindings::structuredclone::StructuredCloneData;
|
||||||
use dom::messageevent::MessageEvent;
|
use dom::messageevent::MessageEvent;
|
||||||
use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler};
|
use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler};
|
||||||
use dom::workerglobalscope::WorkerGlobalScope;
|
use dom::workerglobalscope::WorkerGlobalScope;
|
||||||
use dom::workerglobalscope::WorkerGlobalScopeInit;
|
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use js::jsapi::{HandleValue, JS_SetInterruptCallback};
|
use js::jsapi::{HandleValue, JS_SetInterruptCallback};
|
||||||
|
@ -29,12 +28,13 @@ use js::jsapi::{JSAutoCompartment, JSContext};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
use net_traits::{LoadContext, load_whole_resource, CustomResponse, IpcSend};
|
use net_traits::{LoadContext, load_whole_resource, IpcSend};
|
||||||
use rand::random;
|
use rand::random;
|
||||||
use script_runtime::ScriptThreadEventCategory::WorkerEvent;
|
use script_runtime::ScriptThreadEventCategory::WorkerEvent;
|
||||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
|
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
|
||||||
use script_traits::{TimerEvent, TimerSource};
|
use script_traits::{TimerEvent, TimerSource, WorkerScriptLoadOrigin, WorkerGlobalScopeInit};
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
|
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -70,8 +70,7 @@ impl<'a> Drop for AutoWorkerReset<'a> {
|
||||||
enum MixedMessage {
|
enum MixedMessage {
|
||||||
FromWorker((TrustedWorkerAddress, WorkerScriptMsg)),
|
FromWorker((TrustedWorkerAddress, WorkerScriptMsg)),
|
||||||
FromScheduler((TrustedWorkerAddress, TimerEvent)),
|
FromScheduler((TrustedWorkerAddress, TimerEvent)),
|
||||||
FromDevtools(DevtoolScriptControlMsg),
|
FromDevtools(DevtoolScriptControlMsg)
|
||||||
FromNetwork(IpcSender<Option<CustomResponse>>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope
|
// https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope
|
||||||
|
@ -102,14 +101,16 @@ impl DedicatedWorkerGlobalScope {
|
||||||
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
||||||
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
||||||
timer_event_chan: IpcSender<TimerEvent>,
|
timer_event_chan: IpcSender<TimerEvent>,
|
||||||
timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>)
|
timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>,
|
||||||
|
closing: Arc<AtomicBool>)
|
||||||
-> DedicatedWorkerGlobalScope {
|
-> DedicatedWorkerGlobalScope {
|
||||||
DedicatedWorkerGlobalScope {
|
DedicatedWorkerGlobalScope {
|
||||||
workerglobalscope: WorkerGlobalScope::new_inherited(init,
|
workerglobalscope: WorkerGlobalScope::new_inherited(init,
|
||||||
worker_url,
|
worker_url,
|
||||||
runtime,
|
runtime,
|
||||||
from_devtools_receiver,
|
from_devtools_receiver,
|
||||||
timer_event_chan),
|
timer_event_chan,
|
||||||
|
Some(closing)),
|
||||||
id: id,
|
id: id,
|
||||||
receiver: receiver,
|
receiver: receiver,
|
||||||
own_sender: own_sender,
|
own_sender: own_sender,
|
||||||
|
@ -128,7 +129,8 @@ impl DedicatedWorkerGlobalScope {
|
||||||
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
||||||
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
||||||
timer_event_chan: IpcSender<TimerEvent>,
|
timer_event_chan: IpcSender<TimerEvent>,
|
||||||
timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>)
|
timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>,
|
||||||
|
closing: Arc<AtomicBool>)
|
||||||
-> Root<DedicatedWorkerGlobalScope> {
|
-> Root<DedicatedWorkerGlobalScope> {
|
||||||
let cx = runtime.cx();
|
let cx = runtime.cx();
|
||||||
let scope = box DedicatedWorkerGlobalScope::new_inherited(init,
|
let scope = box DedicatedWorkerGlobalScope::new_inherited(init,
|
||||||
|
@ -140,7 +142,8 @@ impl DedicatedWorkerGlobalScope {
|
||||||
own_sender,
|
own_sender,
|
||||||
receiver,
|
receiver,
|
||||||
timer_event_chan,
|
timer_event_chan,
|
||||||
timer_event_port);
|
timer_event_port,
|
||||||
|
closing);
|
||||||
DedicatedWorkerGlobalScopeBinding::Wrap(cx, scope)
|
DedicatedWorkerGlobalScopeBinding::Wrap(cx, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +157,8 @@ impl DedicatedWorkerGlobalScope {
|
||||||
parent_sender: Box<ScriptChan + Send>,
|
parent_sender: Box<ScriptChan + Send>,
|
||||||
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
||||||
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
|
||||||
worker_load_origin: WorkerScriptLoadOrigin) {
|
worker_load_origin: WorkerScriptLoadOrigin,
|
||||||
|
closing: Arc<AtomicBool>) {
|
||||||
let serialized_worker_url = worker_url.to_string();
|
let serialized_worker_url = worker_url.to_string();
|
||||||
let name = format!("WebWorker for {}", serialized_worker_url);
|
let name = format!("WebWorker for {}", serialized_worker_url);
|
||||||
let panic_chan = init.panic_chan.clone();
|
let panic_chan = init.panic_chan.clone();
|
||||||
|
@ -193,7 +197,7 @@ impl DedicatedWorkerGlobalScope {
|
||||||
let global = DedicatedWorkerGlobalScope::new(
|
let global = DedicatedWorkerGlobalScope::new(
|
||||||
init, url, id, devtools_mpsc_port, runtime,
|
init, url, id, devtools_mpsc_port, runtime,
|
||||||
parent_sender.clone(), own_sender, receiver,
|
parent_sender.clone(), own_sender, receiver,
|
||||||
timer_ipc_chan, timer_rx);
|
timer_ipc_chan, timer_rx, closing);
|
||||||
// FIXME(njn): workers currently don't have a unique ID suitable for using in reporter
|
// FIXME(njn): workers currently don't have a unique ID suitable for using in reporter
|
||||||
// registration (#6631), so we instead use a random number and cross our fingers.
|
// registration (#6631), so we instead use a random number and cross our fingers.
|
||||||
let scope = global.upcast::<WorkerGlobalScope>();
|
let scope = global.upcast::<WorkerGlobalScope>();
|
||||||
|
@ -254,20 +258,17 @@ impl DedicatedWorkerGlobalScope {
|
||||||
let worker_port = &self.receiver;
|
let worker_port = &self.receiver;
|
||||||
let timer_event_port = &self.timer_event_port;
|
let timer_event_port = &self.timer_event_port;
|
||||||
let devtools_port = scope.from_devtools_receiver();
|
let devtools_port = scope.from_devtools_receiver();
|
||||||
let msg_port = scope.custom_message_port();
|
|
||||||
|
|
||||||
let sel = Select::new();
|
let sel = Select::new();
|
||||||
let mut worker_handle = sel.handle(worker_port);
|
let mut worker_handle = sel.handle(worker_port);
|
||||||
let mut timer_event_handle = sel.handle(timer_event_port);
|
let mut timer_event_handle = sel.handle(timer_event_port);
|
||||||
let mut devtools_handle = sel.handle(devtools_port);
|
let mut devtools_handle = sel.handle(devtools_port);
|
||||||
let mut msg_port_handle = sel.handle(msg_port);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
worker_handle.add();
|
worker_handle.add();
|
||||||
timer_event_handle.add();
|
timer_event_handle.add();
|
||||||
if scope.from_devtools_sender().is_some() {
|
if scope.from_devtools_sender().is_some() {
|
||||||
devtools_handle.add();
|
devtools_handle.add();
|
||||||
}
|
}
|
||||||
msg_port_handle.add();
|
|
||||||
}
|
}
|
||||||
let ret = sel.wait();
|
let ret = sel.wait();
|
||||||
if ret == worker_handle.id() {
|
if ret == worker_handle.id() {
|
||||||
|
@ -276,8 +277,6 @@ impl DedicatedWorkerGlobalScope {
|
||||||
Ok(MixedMessage::FromScheduler(try!(timer_event_port.recv())))
|
Ok(MixedMessage::FromScheduler(try!(timer_event_port.recv())))
|
||||||
} else if ret == devtools_handle.id() {
|
} else if ret == devtools_handle.id() {
|
||||||
Ok(MixedMessage::FromDevtools(try!(devtools_port.recv())))
|
Ok(MixedMessage::FromDevtools(try!(devtools_port.recv())))
|
||||||
} else if ret == msg_port_handle.id() {
|
|
||||||
Ok(MixedMessage::FromNetwork(try!(msg_port.recv())))
|
|
||||||
} else {
|
} else {
|
||||||
panic!("unexpected select result!")
|
panic!("unexpected select result!")
|
||||||
}
|
}
|
||||||
|
@ -339,10 +338,6 @@ impl DedicatedWorkerGlobalScope {
|
||||||
MixedMessage::FromWorker((linked_worker, msg)) => {
|
MixedMessage::FromWorker((linked_worker, msg)) => {
|
||||||
let _ar = AutoWorkerReset::new(self, linked_worker);
|
let _ar = AutoWorkerReset::new(self, linked_worker);
|
||||||
self.handle_script_event(msg);
|
self.handle_script_event(msg);
|
||||||
},
|
|
||||||
MixedMessage::FromNetwork(network_sender) => {
|
|
||||||
// We send None as of now
|
|
||||||
let _ = network_sender.send(None);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use dom::abstractworker::WorkerScriptMsg;
|
||||||
use dom::abstractworker::{SimpleWorkerErrorHandler, WorkerErrorHandler};
|
use dom::abstractworker::{SimpleWorkerErrorHandler, WorkerErrorHandler};
|
||||||
use dom::abstractworker::{WorkerScriptMsg, WorkerScriptLoadOrigin, SharedRt};
|
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
||||||
use dom::bindings::codegen::Bindings::ServiceWorkerBinding::{ServiceWorkerMethods, ServiceWorkerState, Wrap};
|
use dom::bindings::codegen::Bindings::ServiceWorkerBinding::{ServiceWorkerMethods, ServiceWorkerState, Wrap};
|
||||||
|
@ -13,19 +13,13 @@ use dom::bindings::js::Root;
|
||||||
use dom::bindings::refcounted::Trusted;
|
use dom::bindings::refcounted::Trusted;
|
||||||
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
|
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
|
||||||
use dom::bindings::str::{DOMString, USVString};
|
use dom::bindings::str::{DOMString, USVString};
|
||||||
use dom::client::Client;
|
|
||||||
use dom::errorevent::ErrorEvent;
|
use dom::errorevent::ErrorEvent;
|
||||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
|
||||||
use dom::workerglobalscope::prepare_workerscope_init;
|
|
||||||
use ipc_channel::ipc;
|
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use script_thread::Runnable;
|
use script_thread::Runnable;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::mpsc::Sender;
|
||||||
use std::sync::mpsc::{Sender, channel};
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>;
|
pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>;
|
||||||
|
@ -35,36 +29,27 @@ pub struct ServiceWorker {
|
||||||
eventtarget: EventTarget,
|
eventtarget: EventTarget,
|
||||||
script_url: DOMRefCell<String>,
|
script_url: DOMRefCell<String>,
|
||||||
state: Cell<ServiceWorkerState>,
|
state: Cell<ServiceWorkerState>,
|
||||||
closing: Arc<AtomicBool>,
|
|
||||||
#[ignore_heap_size_of = "Defined in std"]
|
#[ignore_heap_size_of = "Defined in std"]
|
||||||
sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
sender: Option<Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>>,
|
||||||
#[ignore_heap_size_of = "Defined in rust-mozjs"]
|
|
||||||
runtime: Arc<Mutex<Option<SharedRt>>>,
|
|
||||||
skip_waiting: Cell<bool>
|
skip_waiting: Cell<bool>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceWorker {
|
impl ServiceWorker {
|
||||||
fn new_inherited(sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
fn new_inherited(script_url: &str,
|
||||||
closing: Arc<AtomicBool>,
|
|
||||||
script_url: &str,
|
|
||||||
skip_waiting: bool) -> ServiceWorker {
|
skip_waiting: bool) -> ServiceWorker {
|
||||||
ServiceWorker {
|
ServiceWorker {
|
||||||
eventtarget: EventTarget::new_inherited(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
closing: closing,
|
sender: None,
|
||||||
sender: sender,
|
|
||||||
script_url: DOMRefCell::new(String::from(script_url)),
|
script_url: DOMRefCell::new(String::from(script_url)),
|
||||||
state: Cell::new(ServiceWorkerState::Installing),
|
state: Cell::new(ServiceWorkerState::Installing),
|
||||||
runtime: Arc::new(Mutex::new(None)),
|
|
||||||
skip_waiting: Cell::new(skip_waiting)
|
skip_waiting: Cell::new(skip_waiting)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(global: GlobalRef,
|
pub fn new(global: GlobalRef,
|
||||||
closing: Arc<AtomicBool>,
|
|
||||||
sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
|
||||||
script_url: &str,
|
script_url: &str,
|
||||||
skip_waiting: bool) -> Root<ServiceWorker> {
|
skip_waiting: bool) -> Root<ServiceWorker> {
|
||||||
reflect_dom_object(box ServiceWorker::new_inherited(sender, closing, script_url, skip_waiting), global, Wrap)
|
reflect_dom_object(box ServiceWorker::new_inherited(script_url, skip_waiting), global, Wrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispatch_simple_error(address: TrustedServiceWorkerAddress) {
|
pub fn dispatch_simple_error(address: TrustedServiceWorkerAddress) {
|
||||||
|
@ -72,23 +57,19 @@ impl ServiceWorker {
|
||||||
service_worker.upcast().fire_simple_event("error");
|
service_worker.upcast().fire_simple_event("error");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_closing(&self) -> bool {
|
|
||||||
self.closing.load(Ordering::SeqCst)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_transition_state(&self, state: ServiceWorkerState) {
|
pub fn set_transition_state(&self, state: ServiceWorkerState) {
|
||||||
self.state.set(state);
|
self.state.set(state);
|
||||||
self.upcast::<EventTarget>().fire_simple_event("statechange");
|
self.upcast::<EventTarget>().fire_simple_event("statechange");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_script_url(&self) -> Url {
|
||||||
|
Url::parse(&self.script_url.borrow().clone()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_error_message(address: TrustedServiceWorkerAddress, message: DOMString,
|
pub fn handle_error_message(address: TrustedServiceWorkerAddress, message: DOMString,
|
||||||
filename: DOMString, lineno: u32, colno: u32) {
|
filename: DOMString, lineno: u32, colno: u32) {
|
||||||
let worker = address.root();
|
let worker = address.root();
|
||||||
|
|
||||||
if worker.is_closing() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let global = worker.r().global();
|
let global = worker.r().global();
|
||||||
rooted!(in(global.r().get_cx()) let error = UndefinedValue());
|
rooted!(in(global.r().get_cx()) let error = UndefinedValue());
|
||||||
let errorevent = ErrorEvent::new(global.r(), atom!("error"),
|
let errorevent = ErrorEvent::new(global.r(), atom!("error"),
|
||||||
|
@ -97,42 +78,12 @@ impl ServiceWorker {
|
||||||
errorevent.upcast::<Event>().fire(worker.upcast());
|
errorevent.upcast::<Event>().fire(worker.upcast());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
pub fn install_serviceworker(global: GlobalRef,
|
||||||
pub fn init_service_worker(global: GlobalRef,
|
|
||||||
script_url: Url,
|
script_url: Url,
|
||||||
skip_waiting: bool) -> Root<ServiceWorker> {
|
skip_waiting: bool) -> Root<ServiceWorker> {
|
||||||
let (sender, receiver) = channel();
|
ServiceWorker::new(global,
|
||||||
let closing = Arc::new(AtomicBool::new(false));
|
|
||||||
let worker = ServiceWorker::new(global,
|
|
||||||
closing.clone(),
|
|
||||||
sender.clone(),
|
|
||||||
script_url.as_str(),
|
script_url.as_str(),
|
||||||
skip_waiting);
|
skip_waiting)
|
||||||
let worker_ref = Trusted::new(worker.r());
|
|
||||||
|
|
||||||
let worker_load_origin = WorkerScriptLoadOrigin {
|
|
||||||
referrer_url: None,
|
|
||||||
referrer_policy: None,
|
|
||||||
request_source: global.request_source(),
|
|
||||||
pipeline_id: Some(global.pipeline())
|
|
||||||
};
|
|
||||||
|
|
||||||
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
|
||||||
let init = prepare_workerscope_init(global,
|
|
||||||
"Service Worker".to_owned(),
|
|
||||||
script_url.clone(),
|
|
||||||
devtools_sender.clone(),
|
|
||||||
closing);
|
|
||||||
|
|
||||||
// represents a service worker client
|
|
||||||
let sw_client = Client::new(global.as_window());
|
|
||||||
let trusted_client = Trusted::new(&*sw_client);
|
|
||||||
|
|
||||||
ServiceWorkerGlobalScope::run_serviceworker_scope(
|
|
||||||
init, script_url, global.pipeline(), devtools_receiver, worker.runtime.clone(), worker_ref,
|
|
||||||
global.script_chan(), sender, receiver, trusted_client, worker_load_origin);
|
|
||||||
|
|
||||||
worker
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer {
|
||||||
script_url,
|
script_url,
|
||||||
scope_str.clone(),
|
scope_str.clone(),
|
||||||
self);
|
self);
|
||||||
ScriptThread::set_registration(scope, &*worker_registration);
|
ScriptThread::set_registration(scope, &*worker_registration, self.global().r().pipeline());
|
||||||
Ok(worker_registration)
|
Ok(worker_registration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
|
|
||||||
use devtools;
|
use devtools;
|
||||||
use devtools_traits::DevtoolScriptControlMsg;
|
use devtools_traits::DevtoolScriptControlMsg;
|
||||||
use dom::abstractworker::{WorkerScriptLoadOrigin, WorkerScriptMsg, SharedRt, SimpleWorkerErrorHandler};
|
use dom::abstractworker::WorkerScriptMsg;
|
||||||
use dom::abstractworkerglobalscope::{SendableWorkerScriptChan, WorkerThreadWorkerChan};
|
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
||||||
use dom::bindings::codegen::Bindings::ServiceWorkerGlobalScopeBinding;
|
use dom::bindings::codegen::Bindings::ServiceWorkerGlobalScopeBinding;
|
||||||
|
@ -13,66 +12,34 @@ use dom::bindings::codegen::Bindings::ServiceWorkerGlobalScopeBinding::ServiceWo
|
||||||
use dom::bindings::global::{GlobalRef, global_root_from_context};
|
use dom::bindings::global::{GlobalRef, global_root_from_context};
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::{Root, RootCollection};
|
use dom::bindings::js::{Root, RootCollection};
|
||||||
use dom::bindings::refcounted::{Trusted, LiveDOMReferences};
|
use dom::bindings::refcounted::LiveDOMReferences;
|
||||||
use dom::bindings::reflector::Reflectable;
|
use dom::bindings::reflector::Reflectable;
|
||||||
use dom::bindings::str::DOMString;
|
use dom::bindings::str::DOMString;
|
||||||
use dom::client::Client;
|
|
||||||
use dom::messageevent::MessageEvent;
|
use dom::messageevent::MessageEvent;
|
||||||
use dom::serviceworker::TrustedServiceWorkerAddress;
|
use dom::serviceworker::TrustedServiceWorkerAddress;
|
||||||
use dom::workerglobalscope::WorkerGlobalScope;
|
use dom::workerglobalscope::WorkerGlobalScope;
|
||||||
use dom::workerglobalscope::WorkerGlobalScopeInit;
|
use ipc_channel::ipc::{self, IpcSender, IpcReceiver};
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use js::jsapi::{JS_SetInterruptCallback, JSAutoCompartment, JSContext};
|
use js::jsapi::{JS_SetInterruptCallback, JSAutoCompartment, JSContext};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
use net_traits::{LoadContext, load_whole_resource, CustomResponse, IpcSend};
|
use net_traits::{LoadContext, load_whole_resource, IpcSend};
|
||||||
use rand::random;
|
use script_runtime::{CommonScriptMsg, StackRootTLS, get_reports, new_rt_and_cx};
|
||||||
use script_runtime::ScriptThreadEventCategory::ServiceWorkerEvent;
|
use script_traits::{TimerEvent, WorkerGlobalScopeInit, ScopeThings, ServiceWorkerMsg};
|
||||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
|
|
||||||
use script_traits::{TimerEvent, TimerSource};
|
|
||||||
use std::mem::replace;
|
|
||||||
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
|
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::thread;
|
||||||
use std::time::Instant;
|
use std::time::Duration;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use util::prefs::PREFS;
|
use util::prefs::PREFS;
|
||||||
use util::thread::spawn_named;
|
use util::thread::spawn_named;
|
||||||
use util::thread_state;
|
use util::thread_state;
|
||||||
use util::thread_state::{IN_WORKER, SCRIPT};
|
use util::thread_state::{IN_WORKER, SCRIPT};
|
||||||
|
|
||||||
/// Set the `worker` field of a related ServiceWorkerGlobalScope object to a particular
|
pub enum MixedMessage {
|
||||||
/// value for the duration of this object's lifetime. This ensures that the related Worker
|
|
||||||
/// object only lives as long as necessary (ie. while events are being executed), while
|
|
||||||
/// providing a reference that can be cloned freely.
|
|
||||||
struct AutoWorkerReset<'a> {
|
|
||||||
workerscope: &'a ServiceWorkerGlobalScope,
|
|
||||||
old_worker: Option<TrustedServiceWorkerAddress>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> AutoWorkerReset<'a> {
|
|
||||||
fn new(workerscope: &'a ServiceWorkerGlobalScope,
|
|
||||||
worker: TrustedServiceWorkerAddress)
|
|
||||||
-> AutoWorkerReset<'a> {
|
|
||||||
AutoWorkerReset {
|
|
||||||
workerscope: workerscope,
|
|
||||||
old_worker: replace(&mut *workerscope.worker.borrow_mut(), Some(worker)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Drop for AutoWorkerReset<'a> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
*self.workerscope.worker.borrow_mut() = self.old_worker.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum MixedMessage {
|
|
||||||
FromServiceWorker((TrustedServiceWorkerAddress, WorkerScriptMsg)),
|
FromServiceWorker((TrustedServiceWorkerAddress, WorkerScriptMsg)),
|
||||||
FromScheduler((TrustedServiceWorkerAddress, TimerEvent)),
|
|
||||||
FromDevtools(DevtoolScriptControlMsg),
|
FromDevtools(DevtoolScriptControlMsg),
|
||||||
FromNetwork(IpcSender<Option<CustomResponse>>),
|
FromTimeoutThread(()),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
|
@ -84,14 +51,13 @@ pub struct ServiceWorkerGlobalScope {
|
||||||
#[ignore_heap_size_of = "Defined in std"]
|
#[ignore_heap_size_of = "Defined in std"]
|
||||||
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
||||||
#[ignore_heap_size_of = "Defined in std"]
|
#[ignore_heap_size_of = "Defined in std"]
|
||||||
timer_event_port: Receiver<(TrustedServiceWorkerAddress, TimerEvent)>,
|
timer_event_port: Receiver<()>,
|
||||||
#[ignore_heap_size_of = "Trusted<T> has unclear ownership like JS<T>"]
|
#[ignore_heap_size_of = "Trusted<T> has unclear ownership like JS<T>"]
|
||||||
worker: DOMRefCell<Option<TrustedServiceWorkerAddress>>,
|
worker: DOMRefCell<Option<TrustedServiceWorkerAddress>>,
|
||||||
#[ignore_heap_size_of = "Can't measure trait objects"]
|
|
||||||
/// Sender to the parent thread.
|
|
||||||
parent_sender: Box<ScriptChan + Send>,
|
|
||||||
#[ignore_heap_size_of = "Defined in std"]
|
#[ignore_heap_size_of = "Defined in std"]
|
||||||
service_worker_client: Trusted<Client>
|
swmanager_sender: IpcSender<ServiceWorkerMsg>,
|
||||||
|
#[ignore_heap_size_of = "Defined in std"]
|
||||||
|
scope_url: Url
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceWorkerGlobalScope {
|
impl ServiceWorkerGlobalScope {
|
||||||
|
@ -100,26 +66,27 @@ impl ServiceWorkerGlobalScope {
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
|
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
|
||||||
runtime: Runtime,
|
runtime: Runtime,
|
||||||
parent_sender: Box<ScriptChan + Send>,
|
|
||||||
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
||||||
receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
||||||
timer_event_chan: IpcSender<TimerEvent>,
|
timer_event_chan: IpcSender<TimerEvent>,
|
||||||
timer_event_port: Receiver<(TrustedServiceWorkerAddress, TimerEvent)>,
|
timer_event_port: Receiver<()>,
|
||||||
client: Trusted<Client>)
|
swmanager_sender: IpcSender<ServiceWorkerMsg>,
|
||||||
|
scope_url: Url)
|
||||||
-> ServiceWorkerGlobalScope {
|
-> ServiceWorkerGlobalScope {
|
||||||
ServiceWorkerGlobalScope {
|
ServiceWorkerGlobalScope {
|
||||||
workerglobalscope: WorkerGlobalScope::new_inherited(init,
|
workerglobalscope: WorkerGlobalScope::new_inherited(init,
|
||||||
worker_url,
|
worker_url,
|
||||||
runtime,
|
runtime,
|
||||||
from_devtools_receiver,
|
from_devtools_receiver,
|
||||||
timer_event_chan),
|
timer_event_chan,
|
||||||
|
None),
|
||||||
id: id,
|
id: id,
|
||||||
receiver: receiver,
|
receiver: receiver,
|
||||||
own_sender: own_sender,
|
|
||||||
timer_event_port: timer_event_port,
|
timer_event_port: timer_event_port,
|
||||||
parent_sender: parent_sender,
|
own_sender: own_sender,
|
||||||
worker: DOMRefCell::new(None),
|
worker: DOMRefCell::new(None),
|
||||||
service_worker_client: client
|
swmanager_sender: swmanager_sender,
|
||||||
|
scope_url: scope_url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,12 +95,12 @@ impl ServiceWorkerGlobalScope {
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
|
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
|
||||||
runtime: Runtime,
|
runtime: Runtime,
|
||||||
parent_sender: Box<ScriptChan + Send>,
|
|
||||||
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
||||||
receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
||||||
timer_event_chan: IpcSender<TimerEvent>,
|
timer_event_chan: IpcSender<TimerEvent>,
|
||||||
timer_event_port: Receiver<(TrustedServiceWorkerAddress, TimerEvent)>,
|
timer_event_port: Receiver<()>,
|
||||||
client: Trusted<Client>)
|
swmanager_sender: IpcSender<ServiceWorkerMsg>,
|
||||||
|
scope_url: Url)
|
||||||
-> Root<ServiceWorkerGlobalScope> {
|
-> Root<ServiceWorkerGlobalScope> {
|
||||||
let cx = runtime.cx();
|
let cx = runtime.cx();
|
||||||
let scope = box ServiceWorkerGlobalScope::new_inherited(init,
|
let scope = box ServiceWorkerGlobalScope::new_inherited(init,
|
||||||
|
@ -141,42 +108,39 @@ impl ServiceWorkerGlobalScope {
|
||||||
id,
|
id,
|
||||||
from_devtools_receiver,
|
from_devtools_receiver,
|
||||||
runtime,
|
runtime,
|
||||||
parent_sender,
|
|
||||||
own_sender,
|
own_sender,
|
||||||
receiver,
|
receiver,
|
||||||
timer_event_chan,
|
timer_event_chan,
|
||||||
timer_event_port,
|
timer_event_port,
|
||||||
client);
|
swmanager_sender,
|
||||||
|
scope_url);
|
||||||
ServiceWorkerGlobalScopeBinding::Wrap(cx, scope)
|
ServiceWorkerGlobalScopeBinding::Wrap(cx, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn run_serviceworker_scope(init: WorkerGlobalScopeInit,
|
pub fn run_serviceworker_scope(scope_things: ScopeThings,
|
||||||
worker_url: Url,
|
|
||||||
id: PipelineId,
|
|
||||||
from_devtools_receiver: IpcReceiver<DevtoolScriptControlMsg>,
|
|
||||||
main_thread_rt: Arc<Mutex<Option<SharedRt>>>,
|
|
||||||
worker: TrustedServiceWorkerAddress,
|
|
||||||
parent_sender: Box<ScriptChan + Send>,
|
|
||||||
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
||||||
receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
|
||||||
client: Trusted<Client>,
|
devtools_receiver: IpcReceiver<DevtoolScriptControlMsg>,
|
||||||
worker_load_origin: WorkerScriptLoadOrigin) {
|
swmanager_sender: IpcSender<ServiceWorkerMsg>,
|
||||||
let serialized_worker_url = worker_url.to_string();
|
scope_url: Url) {
|
||||||
|
let ScopeThings { script_url,
|
||||||
|
pipeline_id,
|
||||||
|
init,
|
||||||
|
worker_load_origin,
|
||||||
|
.. } = scope_things;
|
||||||
|
|
||||||
|
let serialized_worker_url = script_url.to_string();
|
||||||
spawn_named(format!("ServiceWorker for {}", serialized_worker_url), move || {
|
spawn_named(format!("ServiceWorker for {}", serialized_worker_url), move || {
|
||||||
thread_state::initialize(SCRIPT | IN_WORKER);
|
thread_state::initialize(SCRIPT | IN_WORKER);
|
||||||
|
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let _stack_roots_tls = StackRootTLS::new(&roots);
|
let _stack_roots_tls = StackRootTLS::new(&roots);
|
||||||
|
|
||||||
let (url, source) = match load_whole_resource(LoadContext::Script,
|
let (url, source) = match load_whole_resource(LoadContext::Script,
|
||||||
&init.resource_threads.sender(),
|
&init.resource_threads.sender(),
|
||||||
worker_url,
|
script_url,
|
||||||
&worker_load_origin) {
|
&worker_load_origin) {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
println!("error loading script {}", serialized_worker_url);
|
println!("error loading script {}", serialized_worker_url);
|
||||||
parent_sender.send(CommonScriptMsg::RunnableMsg(ServiceWorkerEvent,
|
|
||||||
box SimpleWorkerErrorHandler::new(worker))).unwrap();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Ok((metadata, bytes)) => {
|
Ok((metadata, bytes)) => {
|
||||||
|
@ -185,25 +149,18 @@ impl ServiceWorkerGlobalScope {
|
||||||
};
|
};
|
||||||
|
|
||||||
let runtime = unsafe { new_rt_and_cx() };
|
let runtime = unsafe { new_rt_and_cx() };
|
||||||
*main_thread_rt.lock().unwrap() = Some(SharedRt::new(&runtime));
|
|
||||||
|
|
||||||
let (devtools_mpsc_chan, devtools_mpsc_port) = channel();
|
let (devtools_mpsc_chan, devtools_mpsc_port) = channel();
|
||||||
ROUTER.route_ipc_receiver_to_mpsc_sender(from_devtools_receiver, devtools_mpsc_chan);
|
ROUTER.route_ipc_receiver_to_mpsc_sender(devtools_receiver, devtools_mpsc_chan);
|
||||||
|
|
||||||
let (timer_tx, timer_rx) = channel();
|
// TODO XXXcreativcoder use this timer_ipc_port, when we have a service worker instance here
|
||||||
let (timer_ipc_chan, timer_ipc_port) = ipc::channel().unwrap();
|
let (timer_ipc_chan, _timer_ipc_port) = ipc::channel().unwrap();
|
||||||
let worker_for_route = worker.clone();
|
let (timer_chan, timer_port) = channel();
|
||||||
ROUTER.add_route(timer_ipc_port.to_opaque(), box move |message| {
|
|
||||||
let event = message.to().unwrap();
|
|
||||||
timer_tx.send((worker_for_route.clone(), event)).unwrap();
|
|
||||||
});
|
|
||||||
|
|
||||||
let global = ServiceWorkerGlobalScope::new(
|
let global = ServiceWorkerGlobalScope::new(
|
||||||
init, url, id, devtools_mpsc_port, runtime,
|
init, url, pipeline_id, devtools_mpsc_port, runtime,
|
||||||
parent_sender.clone(), own_sender, receiver,
|
own_sender, receiver,
|
||||||
timer_ipc_chan, timer_rx, client);
|
timer_ipc_chan, timer_port, swmanager_sender, scope_url);
|
||||||
// FIXME(njn): workers currently don't have a unique ID suitable for using in reporter
|
|
||||||
// registration (#6631), so we instead use a random number and cross our fingers.
|
|
||||||
let scope = global.upcast::<WorkerGlobalScope>();
|
let scope = global.upcast::<WorkerGlobalScope>();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -211,35 +168,25 @@ impl ServiceWorkerGlobalScope {
|
||||||
JS_SetInterruptCallback(scope.runtime(), Some(interrupt_callback));
|
JS_SetInterruptCallback(scope.runtime(), Some(interrupt_callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
if scope.is_closing() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let _ar = AutoWorkerReset::new(global.r(), worker);
|
|
||||||
scope.execute_script(DOMString::from(source));
|
scope.execute_script(DOMString::from(source));
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let reporter_name = format!("service-worker-reporter-{}", random::<u64>());
|
|
||||||
scope.mem_profiler_chan().run_with_memory_reporting(|| {
|
|
||||||
// Service workers are time limited
|
// Service workers are time limited
|
||||||
let sw_lifetime = Instant::now();
|
spawn_named("SWTimeoutThread".to_owned(), move || {
|
||||||
let sw_lifetime_timeout = PREFS.get("dom.serviceworker.timeout_seconds").as_u64().unwrap();
|
let sw_lifetime_timeout = PREFS.get("dom.serviceworker.timeout_seconds").as_u64().unwrap();
|
||||||
|
thread::sleep(Duration::new(sw_lifetime_timeout, 0));
|
||||||
|
let _ = timer_chan.send(());
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO XXXcreativcoder bring back run_with_memory_reporting when things are more concrete here.
|
||||||
while let Ok(event) = global.receive_event() {
|
while let Ok(event) = global.receive_event() {
|
||||||
if scope.is_closing() {
|
if !global.handle_event(event) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
global.handle_event(event);
|
|
||||||
if sw_lifetime.elapsed().as_secs() == sw_lifetime_timeout {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, reporter_name, parent_sender, CommonScriptMsg::CollectReports);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, event: MixedMessage) {
|
fn handle_event(&self, event: MixedMessage) -> bool {
|
||||||
match event {
|
match event {
|
||||||
MixedMessage::FromDevtools(msg) => {
|
MixedMessage::FromDevtools(msg) => {
|
||||||
let global_ref = GlobalRef::Worker(self.upcast());
|
let global_ref = GlobalRef::Worker(self.upcast());
|
||||||
|
@ -252,26 +199,15 @@ impl ServiceWorkerGlobalScope {
|
||||||
devtools::handle_wants_live_notifications(&global_ref, bool_val),
|
devtools::handle_wants_live_notifications(&global_ref, bool_val),
|
||||||
_ => debug!("got an unusable devtools control message inside the worker!"),
|
_ => debug!("got an unusable devtools control message inside the worker!"),
|
||||||
}
|
}
|
||||||
},
|
true
|
||||||
MixedMessage::FromScheduler((linked_worker, timer_event)) => {
|
|
||||||
match timer_event {
|
|
||||||
TimerEvent(TimerSource::FromWorker, id) => {
|
|
||||||
let _ar = AutoWorkerReset::new(self, linked_worker);
|
|
||||||
let scope = self.upcast::<WorkerGlobalScope>();
|
|
||||||
scope.handle_fire_timer(id);
|
|
||||||
},
|
|
||||||
TimerEvent(_, _) => {
|
|
||||||
panic!("The service worker received a TimerEvent from a window.")
|
|
||||||
}
|
}
|
||||||
}
|
MixedMessage::FromServiceWorker((_, msg)) => {
|
||||||
}
|
|
||||||
MixedMessage::FromServiceWorker((linked_worker, msg)) => {
|
|
||||||
let _ar = AutoWorkerReset::new(self, linked_worker);
|
|
||||||
self.handle_script_event(msg);
|
self.handle_script_event(msg);
|
||||||
},
|
true
|
||||||
MixedMessage::FromNetwork(network_sender) => {
|
}
|
||||||
// We send None as of now
|
MixedMessage::FromTimeoutThread(_) => {
|
||||||
let _ = network_sender.send(None);
|
let _ = self.swmanager_sender.send(ServiceWorkerMsg::Timeout(self.scope_url.clone()));
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,44 +243,33 @@ impl ServiceWorkerGlobalScope {
|
||||||
fn receive_event(&self) -> Result<MixedMessage, RecvError> {
|
fn receive_event(&self) -> Result<MixedMessage, RecvError> {
|
||||||
let scope = self.upcast::<WorkerGlobalScope>();
|
let scope = self.upcast::<WorkerGlobalScope>();
|
||||||
let worker_port = &self.receiver;
|
let worker_port = &self.receiver;
|
||||||
let timer_event_port = &self.timer_event_port;
|
|
||||||
let devtools_port = scope.from_devtools_receiver();
|
let devtools_port = scope.from_devtools_receiver();
|
||||||
let msg_port = scope.custom_message_port();
|
let timer_event_port = &self.timer_event_port;
|
||||||
|
|
||||||
let sel = Select::new();
|
let sel = Select::new();
|
||||||
let mut worker_handle = sel.handle(worker_port);
|
let mut worker_handle = sel.handle(worker_port);
|
||||||
let mut timer_event_handle = sel.handle(timer_event_port);
|
|
||||||
let mut devtools_handle = sel.handle(devtools_port);
|
let mut devtools_handle = sel.handle(devtools_port);
|
||||||
let mut msg_port_handle = sel.handle(msg_port);
|
let mut timer_port_handle = sel.handle(timer_event_port);
|
||||||
unsafe {
|
unsafe {
|
||||||
worker_handle.add();
|
worker_handle.add();
|
||||||
timer_event_handle.add();
|
|
||||||
if scope.from_devtools_sender().is_some() {
|
if scope.from_devtools_sender().is_some() {
|
||||||
devtools_handle.add();
|
devtools_handle.add();
|
||||||
}
|
}
|
||||||
msg_port_handle.add();
|
timer_port_handle.add();
|
||||||
}
|
}
|
||||||
|
|
||||||
let ret = sel.wait();
|
let ret = sel.wait();
|
||||||
if ret == worker_handle.id() {
|
if ret == worker_handle.id() {
|
||||||
Ok(MixedMessage::FromServiceWorker(try!(worker_port.recv())))
|
Ok(MixedMessage::FromServiceWorker(try!(worker_port.recv())))
|
||||||
} else if ret == timer_event_handle.id() {
|
|
||||||
Ok(MixedMessage::FromScheduler(try!(timer_event_port.recv())))
|
|
||||||
}else if ret == devtools_handle.id() {
|
}else if ret == devtools_handle.id() {
|
||||||
Ok(MixedMessage::FromDevtools(try!(devtools_port.recv())))
|
Ok(MixedMessage::FromDevtools(try!(devtools_port.recv())))
|
||||||
} else if ret == msg_port_handle.id() {
|
} else if ret == timer_port_handle.id() {
|
||||||
Ok(MixedMessage::FromNetwork(try!(msg_port.recv())))
|
Ok(MixedMessage::FromTimeoutThread(try!(timer_event_port.recv())))
|
||||||
} else {
|
} else {
|
||||||
panic!("unexpected select result!")
|
panic!("unexpected select result!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn script_chan(&self) -> Box<ScriptChan + Send> {
|
|
||||||
box WorkerThreadWorkerChan {
|
|
||||||
sender: self.own_sender.clone(),
|
|
||||||
worker: self.worker.borrow().as_ref().unwrap().clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pipeline(&self) -> PipelineId {
|
pub fn pipeline(&self) -> PipelineId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
@ -352,15 +277,6 @@ impl ServiceWorkerGlobalScope {
|
||||||
pub fn process_event(&self, msg: CommonScriptMsg) {
|
pub fn process_event(&self, msg: CommonScriptMsg) {
|
||||||
self.handle_script_event(WorkerScriptMsg::Common(msg));
|
self.handle_script_event(WorkerScriptMsg::Common(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_script_pair(&self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>) {
|
|
||||||
let (tx, rx) = channel();
|
|
||||||
let chan = box SendableWorkerScriptChan {
|
|
||||||
sender: tx,
|
|
||||||
worker: self.worker.borrow().as_ref().unwrap().clone(),
|
|
||||||
};
|
|
||||||
(chan, box rx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
|
|
@ -11,6 +11,8 @@ use dom::bindings::str::USVString;
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::serviceworker::ServiceWorker;
|
use dom::serviceworker::ServiceWorker;
|
||||||
use dom::serviceworkercontainer::Controllable;
|
use dom::serviceworkercontainer::Controllable;
|
||||||
|
use dom::workerglobalscope::prepare_workerscope_init;
|
||||||
|
use script_traits::{WorkerScriptLoadOrigin, ScopeThings};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
|
@ -19,7 +21,7 @@ pub struct ServiceWorkerRegistration {
|
||||||
active: Option<JS<ServiceWorker>>,
|
active: Option<JS<ServiceWorker>>,
|
||||||
installing: Option<JS<ServiceWorker>>,
|
installing: Option<JS<ServiceWorker>>,
|
||||||
waiting: Option<JS<ServiceWorker>>,
|
waiting: Option<JS<ServiceWorker>>,
|
||||||
scope: String,
|
scope: String
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceWorkerRegistration {
|
impl ServiceWorkerRegistration {
|
||||||
|
@ -29,7 +31,7 @@ impl ServiceWorkerRegistration {
|
||||||
active: Some(JS::from_ref(active_sw)),
|
active: Some(JS::from_ref(active_sw)),
|
||||||
installing: None,
|
installing: None,
|
||||||
waiting: None,
|
waiting: None,
|
||||||
scope: scope
|
scope: scope,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
|
@ -37,11 +39,47 @@ impl ServiceWorkerRegistration {
|
||||||
script_url: Url,
|
script_url: Url,
|
||||||
scope: String,
|
scope: String,
|
||||||
container: &Controllable) -> Root<ServiceWorkerRegistration> {
|
container: &Controllable) -> Root<ServiceWorkerRegistration> {
|
||||||
let active_worker = ServiceWorker::init_service_worker(global, script_url, true);
|
let active_worker = ServiceWorker::install_serviceworker(global, script_url.clone(), true);
|
||||||
active_worker.set_transition_state(ServiceWorkerState::Installed);
|
active_worker.set_transition_state(ServiceWorkerState::Installed);
|
||||||
container.set_controller(&*active_worker.clone());
|
container.set_controller(&*active_worker.clone());
|
||||||
reflect_dom_object(box ServiceWorkerRegistration::new_inherited(&*active_worker, scope), global, Wrap)
|
reflect_dom_object(box ServiceWorkerRegistration::new_inherited(&*active_worker, scope), global, Wrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_installed(&self) -> &ServiceWorker {
|
||||||
|
self.active.as_ref().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_scope_things(global: GlobalRef, script_url: Url) -> ScopeThings {
|
||||||
|
let worker_load_origin = WorkerScriptLoadOrigin {
|
||||||
|
referrer_url: None,
|
||||||
|
referrer_policy: None,
|
||||||
|
pipeline_id: Some(global.pipeline())
|
||||||
|
};
|
||||||
|
|
||||||
|
let worker_id = global.get_next_worker_id();
|
||||||
|
let init = prepare_workerscope_init(global, None);
|
||||||
|
ScopeThings {
|
||||||
|
script_url: script_url,
|
||||||
|
pipeline_id: global.pipeline(),
|
||||||
|
init: init,
|
||||||
|
worker_load_origin: worker_load_origin,
|
||||||
|
devtools_chan: global.devtools_chan(),
|
||||||
|
worker_id: worker_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn longest_prefix_match(stored_scope: &Url, potential_match: &Url) -> bool {
|
||||||
|
if stored_scope.origin() != potential_match.origin() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let scope_chars = stored_scope.path().chars();
|
||||||
|
let matching_chars = potential_match.path().chars();
|
||||||
|
if scope_chars.count() > matching_chars.count() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
stored_scope.path().chars().zip(potential_match.path().chars()).all(|(scope, matched)| scope == matched)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceWorkerRegistrationMethods for ServiceWorkerRegistration {
|
impl ServiceWorkerRegistrationMethods for ServiceWorkerRegistration {
|
||||||
|
|
|
@ -44,10 +44,10 @@ use js::rust::CompileOptionsWrapper;
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use libc;
|
use libc;
|
||||||
use msg::constellation_msg::{FrameType, LoadData, PanicMsg, PipelineId, SubpageId, WindowSizeType};
|
use msg::constellation_msg::{FrameType, LoadData, PanicMsg, PipelineId, SubpageId, WindowSizeType};
|
||||||
|
use net_traits::ResourceThreads;
|
||||||
use net_traits::bluetooth_thread::BluetoothMethodMsg;
|
use net_traits::bluetooth_thread::BluetoothMethodMsg;
|
||||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
|
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
|
||||||
use net_traits::storage_thread::StorageType;
|
use net_traits::storage_thread::StorageType;
|
||||||
use net_traits::{ResourceThreads, CustomResponseSender};
|
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use open;
|
use open;
|
||||||
use profile_traits::mem;
|
use profile_traits::mem;
|
||||||
|
@ -155,8 +155,6 @@ pub struct Window {
|
||||||
image_cache_thread: ImageCacheThread,
|
image_cache_thread: ImageCacheThread,
|
||||||
#[ignore_heap_size_of = "channels are hard"]
|
#[ignore_heap_size_of = "channels are hard"]
|
||||||
image_cache_chan: ImageCacheChan,
|
image_cache_chan: ImageCacheChan,
|
||||||
#[ignore_heap_size_of = "channels are hard"]
|
|
||||||
custom_message_chan: IpcSender<CustomResponseSender>,
|
|
||||||
browsing_context: MutNullableHeap<JS<BrowsingContext>>,
|
browsing_context: MutNullableHeap<JS<BrowsingContext>>,
|
||||||
performance: MutNullableHeap<JS<Performance>>,
|
performance: MutNullableHeap<JS<Performance>>,
|
||||||
navigation_start: u64,
|
navigation_start: u64,
|
||||||
|
@ -314,10 +312,6 @@ impl Window {
|
||||||
self.image_cache_chan.clone()
|
self.image_cache_chan.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn custom_message_chan(&self) -> IpcSender<CustomResponseSender> {
|
|
||||||
self.custom_message_chan.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_next_worker_id(&self) -> WorkerId {
|
pub fn get_next_worker_id(&self) -> WorkerId {
|
||||||
let worker_id = self.next_worker_id.get();
|
let worker_id = self.next_worker_id.get();
|
||||||
let WorkerId(id_num) = worker_id;
|
let WorkerId(id_num) = worker_id;
|
||||||
|
@ -1605,7 +1599,6 @@ impl Window {
|
||||||
history_task_source: HistoryTraversalTaskSource,
|
history_task_source: HistoryTraversalTaskSource,
|
||||||
file_task_source: FileReadingTaskSource,
|
file_task_source: FileReadingTaskSource,
|
||||||
image_cache_chan: ImageCacheChan,
|
image_cache_chan: ImageCacheChan,
|
||||||
custom_message_chan: IpcSender<CustomResponseSender>,
|
|
||||||
image_cache_thread: ImageCacheThread,
|
image_cache_thread: ImageCacheThread,
|
||||||
resource_threads: ResourceThreads,
|
resource_threads: ResourceThreads,
|
||||||
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
||||||
|
@ -1641,7 +1634,6 @@ impl Window {
|
||||||
history_traversal_task_source: history_task_source,
|
history_traversal_task_source: history_task_source,
|
||||||
file_reading_task_source: file_task_source,
|
file_reading_task_source: file_task_source,
|
||||||
image_cache_chan: image_cache_chan,
|
image_cache_chan: image_cache_chan,
|
||||||
custom_message_chan: custom_message_chan,
|
|
||||||
console: Default::default(),
|
console: Default::default(),
|
||||||
crypto: Default::default(),
|
crypto: Default::default(),
|
||||||
navigator: Default::default(),
|
navigator: Default::default(),
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use devtools_traits::{ScriptToDevtoolsControlMsg, DevtoolsPageInfo};
|
||||||
|
use dom::abstractworker::WorkerScriptMsg;
|
||||||
use dom::abstractworker::{SimpleWorkerErrorHandler, SharedRt, WorkerErrorHandler};
|
use dom::abstractworker::{SimpleWorkerErrorHandler, SharedRt, WorkerErrorHandler};
|
||||||
use dom::abstractworker::{WorkerScriptLoadOrigin, WorkerScriptMsg};
|
|
||||||
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
||||||
use dom::bindings::codegen::Bindings::WorkerBinding;
|
use dom::bindings::codegen::Bindings::WorkerBinding;
|
||||||
use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods;
|
use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods;
|
||||||
|
@ -26,6 +26,7 @@ use ipc_channel::ipc;
|
||||||
use js::jsapi::{HandleValue, JSContext, JSAutoCompartment};
|
use js::jsapi::{HandleValue, JSContext, JSAutoCompartment};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use script_thread::Runnable;
|
use script_thread::Runnable;
|
||||||
|
use script_traits::WorkerScriptLoadOrigin;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::mpsc::{Sender, channel};
|
use std::sync::mpsc::{Sender, channel};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
@ -81,21 +82,28 @@ impl Worker {
|
||||||
let worker_load_origin = WorkerScriptLoadOrigin {
|
let worker_load_origin = WorkerScriptLoadOrigin {
|
||||||
referrer_url: None,
|
referrer_url: None,
|
||||||
referrer_policy: None,
|
referrer_policy: None,
|
||||||
request_source: global.request_source(),
|
|
||||||
pipeline_id: Some(global.pipeline())
|
pipeline_id: Some(global.pipeline())
|
||||||
};
|
};
|
||||||
|
|
||||||
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
||||||
|
let worker_id = global.get_next_worker_id();
|
||||||
let init = prepare_workerscope_init(global,
|
if let Some(ref chan) = global.devtools_chan() {
|
||||||
"Worker".to_owned(),
|
let pipeline_id = global.pipeline();
|
||||||
worker_url.clone(),
|
let title = format!("Worker for {}", worker_url);
|
||||||
|
let page_info = DevtoolsPageInfo {
|
||||||
|
title: title,
|
||||||
|
url: worker_url.clone(),
|
||||||
|
};
|
||||||
|
let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal((pipeline_id, Some(worker_id)),
|
||||||
devtools_sender.clone(),
|
devtools_sender.clone(),
|
||||||
closing);
|
page_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
let init = prepare_workerscope_init(global, Some(devtools_sender));
|
||||||
|
|
||||||
DedicatedWorkerGlobalScope::run_worker_scope(
|
DedicatedWorkerGlobalScope::run_worker_scope(
|
||||||
init, worker_url, global.pipeline(), devtools_receiver, worker.runtime.clone(), worker_ref,
|
init, worker_url, global.pipeline(), devtools_receiver, worker.runtime.clone(), worker_ref,
|
||||||
global.script_chan(), sender, receiver, worker_load_origin);
|
global.script_chan(), sender, receiver, worker_load_origin, closing);
|
||||||
|
|
||||||
Ok(worker)
|
Ok(worker)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId, DevtoolsPageInfo};
|
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||||
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
|
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
|
||||||
use dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception};
|
use dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception};
|
||||||
|
@ -19,18 +19,18 @@ use dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
||||||
use dom::window::{base64_atob, base64_btoa};
|
use dom::window::{base64_atob, base64_btoa};
|
||||||
use dom::workerlocation::WorkerLocation;
|
use dom::workerlocation::WorkerLocation;
|
||||||
use dom::workernavigator::WorkerNavigator;
|
use dom::workernavigator::WorkerNavigator;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::IpcSender;
|
||||||
use ipc_channel::router::ROUTER;
|
|
||||||
use js::jsapi::{HandleValue, JSContext, JSRuntime};
|
use js::jsapi::{HandleValue, JSContext, JSRuntime};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy, PanicMsg};
|
use msg::constellation_msg::{PipelineId, ReferrerPolicy, PanicMsg};
|
||||||
use net_traits::{LoadContext, ResourceThreads, load_whole_resource};
|
use net_traits::{LoadContext, ResourceThreads, load_whole_resource};
|
||||||
use net_traits::{RequestSource, LoadOrigin, CustomResponseSender, IpcSend};
|
use net_traits::{LoadOrigin, IpcSend};
|
||||||
use profile_traits::{mem, time};
|
use profile_traits::{mem, time};
|
||||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, maybe_take_panic_result};
|
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, maybe_take_panic_result};
|
||||||
use script_thread::RunnableWrapper;
|
use script_thread::RunnableWrapper;
|
||||||
use script_traits::ScriptMsg as ConstellationMsg;
|
use script_traits::ScriptMsg as ConstellationMsg;
|
||||||
|
use script_traits::WorkerGlobalScopeInit;
|
||||||
use script_traits::{MsDuration, TimerEvent, TimerEventId, TimerEventRequest, TimerSource};
|
use script_traits::{MsDuration, TimerEvent, TimerEventId, TimerEventRequest, TimerSource};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
@ -48,52 +48,19 @@ pub enum WorkerGlobalScopeTypeId {
|
||||||
DedicatedWorkerGlobalScope,
|
DedicatedWorkerGlobalScope,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WorkerGlobalScopeInit {
|
|
||||||
pub resource_threads: ResourceThreads,
|
|
||||||
pub mem_profiler_chan: mem::ProfilerChan,
|
|
||||||
pub time_profiler_chan: time::ProfilerChan,
|
|
||||||
pub to_devtools_sender: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
|
||||||
pub from_devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
|
|
||||||
pub constellation_chan: IpcSender<ConstellationMsg>,
|
|
||||||
pub scheduler_chan: IpcSender<TimerEventRequest>,
|
|
||||||
pub panic_chan: IpcSender<PanicMsg>,
|
|
||||||
pub worker_id: WorkerId,
|
|
||||||
pub closing: Arc<AtomicBool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn prepare_workerscope_init(global: GlobalRef,
|
pub fn prepare_workerscope_init(global: GlobalRef,
|
||||||
worker_type: String,
|
devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>) -> WorkerGlobalScopeInit {
|
||||||
worker_url: Url,
|
|
||||||
devtools_sender: IpcSender<DevtoolScriptControlMsg>,
|
|
||||||
closing: Arc<AtomicBool>) -> WorkerGlobalScopeInit {
|
|
||||||
let worker_id = global.get_next_worker_id();
|
let worker_id = global.get_next_worker_id();
|
||||||
let optional_sender = match global.devtools_chan() {
|
|
||||||
Some(ref chan) => {
|
|
||||||
let pipeline_id = global.pipeline();
|
|
||||||
let title = format!("{} for {}", worker_type, worker_url);
|
|
||||||
let page_info = DevtoolsPageInfo {
|
|
||||||
title: title,
|
|
||||||
url: worker_url,
|
|
||||||
};
|
|
||||||
chan.send(ScriptToDevtoolsControlMsg::NewGlobal((pipeline_id, Some(worker_id)),
|
|
||||||
devtools_sender.clone(),
|
|
||||||
page_info)).unwrap();
|
|
||||||
Some(devtools_sender)
|
|
||||||
},
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let init = WorkerGlobalScopeInit {
|
let init = WorkerGlobalScopeInit {
|
||||||
resource_threads: global.resource_threads(),
|
resource_threads: global.resource_threads(),
|
||||||
mem_profiler_chan: global.mem_profiler_chan().clone(),
|
mem_profiler_chan: global.mem_profiler_chan().clone(),
|
||||||
to_devtools_sender: global.devtools_chan(),
|
to_devtools_sender: global.devtools_chan(),
|
||||||
time_profiler_chan: global.time_profiler_chan().clone(),
|
time_profiler_chan: global.time_profiler_chan().clone(),
|
||||||
from_devtools_sender: optional_sender,
|
from_devtools_sender: devtools_sender,
|
||||||
constellation_chan: global.constellation_chan().clone(),
|
constellation_chan: global.constellation_chan().clone(),
|
||||||
panic_chan: global.panic_chan().clone(),
|
panic_chan: global.panic_chan().clone(),
|
||||||
scheduler_chan: global.scheduler_chan().clone(),
|
scheduler_chan: global.scheduler_chan().clone(),
|
||||||
worker_id: worker_id,
|
worker_id: worker_id
|
||||||
closing: closing,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
init
|
init
|
||||||
|
@ -105,7 +72,7 @@ pub struct WorkerGlobalScope {
|
||||||
eventtarget: EventTarget,
|
eventtarget: EventTarget,
|
||||||
worker_id: WorkerId,
|
worker_id: WorkerId,
|
||||||
worker_url: Url,
|
worker_url: Url,
|
||||||
closing: Arc<AtomicBool>,
|
closing: Option<Arc<AtomicBool>>,
|
||||||
#[ignore_heap_size_of = "Defined in js"]
|
#[ignore_heap_size_of = "Defined in js"]
|
||||||
runtime: Runtime,
|
runtime: Runtime,
|
||||||
next_worker_id: Cell<WorkerId>,
|
next_worker_id: Cell<WorkerId>,
|
||||||
|
@ -146,12 +113,6 @@ pub struct WorkerGlobalScope {
|
||||||
|
|
||||||
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
||||||
panic_chan: IpcSender<PanicMsg>,
|
panic_chan: IpcSender<PanicMsg>,
|
||||||
|
|
||||||
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
|
||||||
custom_msg_chan: IpcSender<CustomResponseSender>,
|
|
||||||
|
|
||||||
#[ignore_heap_size_of = "Defined in std"]
|
|
||||||
custom_msg_port: Receiver<CustomResponseSender>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorkerGlobalScope {
|
impl WorkerGlobalScope {
|
||||||
|
@ -159,16 +120,15 @@ impl WorkerGlobalScope {
|
||||||
worker_url: Url,
|
worker_url: Url,
|
||||||
runtime: Runtime,
|
runtime: Runtime,
|
||||||
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
|
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
|
||||||
timer_event_chan: IpcSender<TimerEvent>)
|
timer_event_chan: IpcSender<TimerEvent>,
|
||||||
|
closing: Option<Arc<AtomicBool>>)
|
||||||
-> WorkerGlobalScope {
|
-> WorkerGlobalScope {
|
||||||
let (msg_chan, msg_port) = ipc::channel().unwrap();
|
|
||||||
let custom_msg_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(msg_port);
|
|
||||||
WorkerGlobalScope {
|
WorkerGlobalScope {
|
||||||
eventtarget: EventTarget::new_inherited(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
next_worker_id: Cell::new(WorkerId(0)),
|
next_worker_id: Cell::new(WorkerId(0)),
|
||||||
worker_id: init.worker_id,
|
worker_id: init.worker_id,
|
||||||
worker_url: worker_url,
|
worker_url: worker_url,
|
||||||
closing: init.closing,
|
closing: closing,
|
||||||
runtime: runtime,
|
runtime: runtime,
|
||||||
resource_threads: init.resource_threads,
|
resource_threads: init.resource_threads,
|
||||||
location: Default::default(),
|
location: Default::default(),
|
||||||
|
@ -185,8 +145,6 @@ impl WorkerGlobalScope {
|
||||||
constellation_chan: init.constellation_chan,
|
constellation_chan: init.constellation_chan,
|
||||||
scheduler_chan: init.scheduler_chan,
|
scheduler_chan: init.scheduler_chan,
|
||||||
panic_chan: init.panic_chan,
|
panic_chan: init.panic_chan,
|
||||||
custom_msg_chan: msg_chan,
|
|
||||||
custom_msg_port: custom_msg_port
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,16 +194,12 @@ impl WorkerGlobalScope {
|
||||||
self.runtime.cx()
|
self.runtime.cx()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn custom_message_chan(&self) -> IpcSender<CustomResponseSender> {
|
|
||||||
self.custom_msg_chan.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn custom_message_port(&self) -> &Receiver<CustomResponseSender> {
|
|
||||||
&self.custom_msg_port
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_closing(&self) -> bool {
|
pub fn is_closing(&self) -> bool {
|
||||||
self.closing.load(Ordering::SeqCst)
|
if let Some(ref closing) = self.closing {
|
||||||
|
closing.load(Ordering::SeqCst)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resource_threads(&self) -> &ResourceThreads {
|
pub fn resource_threads(&self) -> &ResourceThreads {
|
||||||
|
@ -273,7 +227,7 @@ impl WorkerGlobalScope {
|
||||||
|
|
||||||
pub fn get_runnable_wrapper(&self) -> RunnableWrapper {
|
pub fn get_runnable_wrapper(&self) -> RunnableWrapper {
|
||||||
RunnableWrapper {
|
RunnableWrapper {
|
||||||
cancelled: self.closing.clone(),
|
cancelled: self.closing.clone().unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,9 +239,6 @@ impl LoadOrigin for WorkerGlobalScope {
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn request_source(&self) -> RequestSource {
|
|
||||||
RequestSource::None
|
|
||||||
}
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
Some(self.pipeline())
|
Some(self.pipeline())
|
||||||
}
|
}
|
||||||
|
@ -451,13 +402,10 @@ impl WorkerGlobalScope {
|
||||||
pub fn script_chan(&self) -> Box<ScriptChan + Send> {
|
pub fn script_chan(&self) -> Box<ScriptChan + Send> {
|
||||||
let dedicated =
|
let dedicated =
|
||||||
self.downcast::<DedicatedWorkerGlobalScope>();
|
self.downcast::<DedicatedWorkerGlobalScope>();
|
||||||
let service_worker = self.downcast::<ServiceWorkerGlobalScope>();
|
|
||||||
if let Some(dedicated) = dedicated {
|
if let Some(dedicated) = dedicated {
|
||||||
return dedicated.script_chan();
|
return dedicated.script_chan();
|
||||||
} else if let Some(service_worker) = service_worker {
|
|
||||||
return service_worker.script_chan();
|
|
||||||
} else {
|
} else {
|
||||||
panic!("need to implement a sender for SharedWorker")
|
panic!("need to implement a sender for SharedWorker/ServiceWorker")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,13 +427,10 @@ impl WorkerGlobalScope {
|
||||||
|
|
||||||
pub fn new_script_pair(&self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>) {
|
pub fn new_script_pair(&self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>) {
|
||||||
let dedicated = self.downcast::<DedicatedWorkerGlobalScope>();
|
let dedicated = self.downcast::<DedicatedWorkerGlobalScope>();
|
||||||
let service_worker = self.downcast::<ServiceWorkerGlobalScope>();
|
|
||||||
if let Some(dedicated) = dedicated {
|
if let Some(dedicated) = dedicated {
|
||||||
return dedicated.new_script_pair();
|
return dedicated.new_script_pair();
|
||||||
} else if let Some(service_worker) = service_worker {
|
|
||||||
return service_worker.new_script_pair();
|
|
||||||
} else {
|
} else {
|
||||||
panic!("need to implement a sender for SharedWorker")
|
panic!("need to implement a sender for SharedWorker/ServiceWorker")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ use net_traits::CoreResourceMsg::Fetch;
|
||||||
use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode};
|
use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode};
|
||||||
use net_traits::trim_http_whitespace;
|
use net_traits::trim_http_whitespace;
|
||||||
use net_traits::{CoreResourceThread, LoadOrigin};
|
use net_traits::{CoreResourceThread, LoadOrigin};
|
||||||
use net_traits::{FetchResponseListener, Metadata, NetworkError, RequestSource};
|
use net_traits::{FetchResponseListener, Metadata, NetworkError};
|
||||||
use network_listener::{NetworkListener, PreInvoke};
|
use network_listener::{NetworkListener, PreInvoke};
|
||||||
use parse::html::{ParseContext, parse_html};
|
use parse::html::{ParseContext, parse_html};
|
||||||
use parse::xml::{self, parse_xml};
|
use parse::xml::{self, parse_xml};
|
||||||
|
@ -274,13 +274,6 @@ impl LoadOrigin for XMLHttpRequest {
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
return self.referrer_policy;
|
return self.referrer_policy;
|
||||||
}
|
}
|
||||||
fn request_source(&self) -> RequestSource {
|
|
||||||
if self.sync.get() {
|
|
||||||
RequestSource::None
|
|
||||||
} else {
|
|
||||||
self.global().r().request_source()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
Some(global.r().pipeline())
|
Some(global.r().pipeline())
|
||||||
|
|
|
@ -106,6 +106,7 @@ pub mod parse;
|
||||||
pub mod script_runtime;
|
pub mod script_runtime;
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub mod script_thread;
|
pub mod script_thread;
|
||||||
|
mod serviceworker_manager;
|
||||||
mod task_source;
|
mod task_source;
|
||||||
pub mod textinput;
|
pub mod textinput;
|
||||||
mod timers;
|
mod timers;
|
||||||
|
@ -114,6 +115,8 @@ mod webdriver_handlers;
|
||||||
|
|
||||||
use dom::bindings::codegen::RegisterBindings;
|
use dom::bindings::codegen::RegisterBindings;
|
||||||
use js::jsapi::{Handle, JSContext, JSObject, SetDOMProxyInformation};
|
use js::jsapi::{Handle, JSContext, JSObject, SetDOMProxyInformation};
|
||||||
|
use script_traits::SWManagerSenders;
|
||||||
|
use serviceworker_manager::ServiceWorkerManager;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use util::opts;
|
use util::opts;
|
||||||
|
|
||||||
|
@ -159,11 +162,14 @@ fn perform_platform_specific_initialization() {
|
||||||
fn perform_platform_specific_initialization() {}
|
fn perform_platform_specific_initialization() {}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn init() {
|
pub fn init(sw_senders: SWManagerSenders) {
|
||||||
unsafe {
|
unsafe {
|
||||||
SetDOMProxyInformation(ptr::null(), 0, Some(script_thread::shadow_check_callback));
|
SetDOMProxyInformation(ptr::null(), 0, Some(script_thread::shadow_check_callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Spawn the service worker manager passing the constellation sender
|
||||||
|
ServiceWorkerManager::spawn_manager(sw_senders);
|
||||||
|
|
||||||
// Create the global vtables used by the (generated) DOM
|
// Create the global vtables used by the (generated) DOM
|
||||||
// bindings to implement JS proxies.
|
// bindings to implement JS proxies.
|
||||||
RegisterBindings::RegisterProxyHandlers();
|
RegisterBindings::RegisterProxyHandlers();
|
||||||
|
|
|
@ -65,12 +65,11 @@ use js::jsval::UndefinedValue;
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use mem::heap_size_of_self_and_children;
|
use mem::heap_size_of_self_and_children;
|
||||||
use msg::constellation_msg::{FrameType, LoadData, PanicMsg, PipelineId, PipelineNamespace};
|
use msg::constellation_msg::{FrameType, LoadData, PanicMsg, PipelineId, PipelineNamespace};
|
||||||
use msg::constellation_msg::{ReferrerPolicy, SubpageId, WindowSizeType};
|
use msg::constellation_msg::{SubpageId, WindowSizeType, ReferrerPolicy};
|
||||||
use net_traits::LoadData as NetLoadData;
|
|
||||||
use net_traits::bluetooth_thread::BluetoothMethodMsg;
|
use net_traits::bluetooth_thread::BluetoothMethodMsg;
|
||||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
|
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
|
||||||
use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadContext, Metadata, ResourceThreads};
|
use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadContext, Metadata, ResourceThreads};
|
||||||
use net_traits::{RequestSource, CustomResponse, CustomResponseSender, IpcSend};
|
use net_traits::{IpcSend, LoadData as NetLoadData};
|
||||||
use network_listener::NetworkListener;
|
use network_listener::NetworkListener;
|
||||||
use parse::ParserRoot;
|
use parse::ParserRoot;
|
||||||
use parse::html::{ParseContext, parse_html};
|
use parse::html::{ParseContext, parse_html};
|
||||||
|
@ -216,8 +215,7 @@ enum MixedMessage {
|
||||||
FromScript(MainThreadScriptMsg),
|
FromScript(MainThreadScriptMsg),
|
||||||
FromDevtools(DevtoolScriptControlMsg),
|
FromDevtools(DevtoolScriptControlMsg),
|
||||||
FromImageCache(ImageCacheResult),
|
FromImageCache(ImageCacheResult),
|
||||||
FromScheduler(TimerEvent),
|
FromScheduler(TimerEvent)
|
||||||
FromNetwork(IpcSender<Option<CustomResponse>>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Messages used to control the script event loop
|
/// Messages used to control the script event loop
|
||||||
|
@ -342,12 +340,6 @@ pub struct ScriptThread {
|
||||||
/// events in the event queue.
|
/// events in the event queue.
|
||||||
chan: MainThreadScriptChan,
|
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,
|
dom_manipulation_task_source: DOMManipulationTaskSource,
|
||||||
|
|
||||||
user_interaction_task_source: UserInteractionTaskSource,
|
user_interaction_task_source: UserInteractionTaskSource,
|
||||||
|
@ -509,10 +501,10 @@ impl ScriptThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
// stores a service worker registration
|
// 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| {
|
SCRIPT_THREAD_ROOT.with(|root| {
|
||||||
let script_thread = unsafe { &*root.get().unwrap() };
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,9 +554,6 @@ impl ScriptThread {
|
||||||
let (ipc_devtools_sender, ipc_devtools_receiver) = ipc::channel().unwrap();
|
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 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.
|
// 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 (ipc_image_cache_channel, ipc_image_cache_port) = ipc::channel().unwrap();
|
||||||
let image_cache_port =
|
let image_cache_port =
|
||||||
|
@ -590,8 +579,6 @@ impl ScriptThread {
|
||||||
bluetooth_thread: state.bluetooth_thread,
|
bluetooth_thread: state.bluetooth_thread,
|
||||||
|
|
||||||
port: port,
|
port: port,
|
||||||
custom_message_chan: ipc_custom_resp_chan,
|
|
||||||
custom_message_port: custom_msg_port,
|
|
||||||
|
|
||||||
chan: MainThreadScriptChan(chan.clone()),
|
chan: MainThreadScriptChan(chan.clone()),
|
||||||
dom_manipulation_task_source: DOMManipulationTaskSource(chan.clone()),
|
dom_manipulation_task_source: DOMManipulationTaskSource(chan.clone()),
|
||||||
|
@ -653,7 +640,7 @@ impl ScriptThread {
|
||||||
/// Handle incoming control messages.
|
/// Handle incoming control messages.
|
||||||
fn handle_msgs(&self) -> bool {
|
fn handle_msgs(&self) -> bool {
|
||||||
use self::MixedMessage::{FromConstellation, FromDevtools, FromImageCache};
|
use self::MixedMessage::{FromConstellation, FromDevtools, FromImageCache};
|
||||||
use self::MixedMessage::{FromScheduler, FromScript, FromNetwork};
|
use self::MixedMessage::{FromScheduler, FromScript};
|
||||||
|
|
||||||
// Handle pending resize events.
|
// Handle pending resize events.
|
||||||
// Gather them first to avoid a double mut borrow on self.
|
// Gather them first to avoid a double mut borrow on self.
|
||||||
|
@ -687,7 +674,6 @@ impl ScriptThread {
|
||||||
let mut timer_event_port = sel.handle(&self.timer_event_port);
|
let mut timer_event_port = sel.handle(&self.timer_event_port);
|
||||||
let mut devtools_port = sel.handle(&self.devtools_port);
|
let mut devtools_port = sel.handle(&self.devtools_port);
|
||||||
let mut image_cache_port = sel.handle(&self.image_cache_port);
|
let mut image_cache_port = sel.handle(&self.image_cache_port);
|
||||||
let mut custom_message_port = sel.handle(&self.custom_message_port);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
script_port.add();
|
script_port.add();
|
||||||
control_port.add();
|
control_port.add();
|
||||||
|
@ -696,7 +682,6 @@ impl ScriptThread {
|
||||||
devtools_port.add();
|
devtools_port.add();
|
||||||
}
|
}
|
||||||
image_cache_port.add();
|
image_cache_port.add();
|
||||||
custom_message_port.add();
|
|
||||||
}
|
}
|
||||||
let ret = sel.wait();
|
let ret = sel.wait();
|
||||||
if ret == script_port.id() {
|
if ret == script_port.id() {
|
||||||
|
@ -709,8 +694,6 @@ impl ScriptThread {
|
||||||
FromDevtools(self.devtools_port.recv().unwrap())
|
FromDevtools(self.devtools_port.recv().unwrap())
|
||||||
} else if ret == image_cache_port.id() {
|
} else if ret == image_cache_port.id() {
|
||||||
FromImageCache(self.image_cache_port.recv().unwrap())
|
FromImageCache(self.image_cache_port.recv().unwrap())
|
||||||
} else if ret == custom_message_port.id() {
|
|
||||||
FromNetwork(self.custom_message_port.recv().unwrap())
|
|
||||||
} else {
|
} else {
|
||||||
panic!("unexpected select result")
|
panic!("unexpected select result")
|
||||||
}
|
}
|
||||||
|
@ -778,10 +761,7 @@ impl ScriptThread {
|
||||||
Err(_) => match self.timer_event_port.try_recv() {
|
Err(_) => match self.timer_event_port.try_recv() {
|
||||||
Err(_) => match self.devtools_port.try_recv() {
|
Err(_) => match self.devtools_port.try_recv() {
|
||||||
Err(_) => match self.image_cache_port.try_recv() {
|
Err(_) => match self.image_cache_port.try_recv() {
|
||||||
Err(_) => match self.custom_message_port.try_recv() {
|
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
Ok(ev) => event = FromNetwork(ev)
|
|
||||||
},
|
|
||||||
Ok(ev) => event = FromImageCache(ev),
|
Ok(ev) => event = FromImageCache(ev),
|
||||||
},
|
},
|
||||||
Ok(ev) => event = FromDevtools(ev),
|
Ok(ev) => event = FromDevtools(ev),
|
||||||
|
@ -807,7 +787,6 @@ impl ScriptThread {
|
||||||
},
|
},
|
||||||
FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg),
|
FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg),
|
||||||
FromScript(inner_msg) => self.handle_msg_from_script(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),
|
FromScheduler(inner_msg) => self.handle_timer_event(inner_msg),
|
||||||
FromDevtools(inner_msg) => self.handle_msg_from_devtools(inner_msg),
|
FromDevtools(inner_msg) => self.handle_msg_from_devtools(inner_msg),
|
||||||
FromImageCache(inner_msg) => self.handle_msg_from_image_cache(inner_msg),
|
FromImageCache(inner_msg) => self.handle_msg_from_image_cache(inner_msg),
|
||||||
|
@ -866,8 +845,7 @@ impl ScriptThread {
|
||||||
_ => ScriptThreadEventCategory::ScriptEvent
|
_ => ScriptThreadEventCategory::ScriptEvent
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MixedMessage::FromScheduler(_) => ScriptThreadEventCategory::TimerEvent,
|
MixedMessage::FromScheduler(_) => ScriptThreadEventCategory::TimerEvent
|
||||||
MixedMessage::FromNetwork(_) => ScriptThreadEventCategory::NetworkEvent
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1056,12 +1034,6 @@ impl ScriptThread {
|
||||||
msg.responder.unwrap().respond(msg.image_response);
|
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) {
|
fn handle_webdriver_msg(&self, pipeline_id: PipelineId, msg: WebDriverScriptCommand) {
|
||||||
let context = self.root_browsing_context();
|
let context = self.root_browsing_context();
|
||||||
match msg {
|
match msg {
|
||||||
|
@ -1457,8 +1429,33 @@ impl ScriptThread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_serviceworker_registration(&self, scope: Url, registration: &ServiceWorkerRegistration) {
|
fn handle_serviceworker_registration(&self,
|
||||||
self.registration_map.borrow_mut().insert(scope, JS::from_ref(registration));
|
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 {}", pipeline_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a request for the window title.
|
/// Handles a request for the window title.
|
||||||
|
@ -1601,7 +1598,6 @@ impl ScriptThread {
|
||||||
HistoryTraversalTaskSource(history_sender.clone()),
|
HistoryTraversalTaskSource(history_sender.clone()),
|
||||||
self.file_reading_task_source.clone(),
|
self.file_reading_task_source.clone(),
|
||||||
self.image_cache_channel.clone(),
|
self.image_cache_channel.clone(),
|
||||||
self.custom_message_chan.clone(),
|
|
||||||
self.image_cache_thread.clone(),
|
self.image_cache_thread.clone(),
|
||||||
self.resource_threads.clone(),
|
self.resource_threads.clone(),
|
||||||
self.bluetooth_thread.clone(),
|
self.bluetooth_thread.clone(),
|
||||||
|
@ -2112,8 +2108,7 @@ impl ScriptThread {
|
||||||
pipeline_id: Some(id),
|
pipeline_id: Some(id),
|
||||||
credentials_flag: true,
|
credentials_flag: true,
|
||||||
referrer_policy: load_data.referrer_policy,
|
referrer_policy: load_data.referrer_policy,
|
||||||
referrer_url: load_data.referrer_url,
|
referrer_url: load_data.referrer_url
|
||||||
source: RequestSource::Window(self.custom_message_chan.clone())
|
|
||||||
}, LoadConsumer::Listener(response_target), None)).unwrap();
|
}, LoadConsumer::Listener(response_target), None)).unwrap();
|
||||||
|
|
||||||
self.incomplete_loads.borrow_mut().push(incomplete);
|
self.incomplete_loads.borrow_mut().push(incomplete);
|
||||||
|
|
163
components/script/serviceworker_manager.rs
Normal file
163
components/script/serviceworker_manager.rs
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! The service worker manager persists the descriptor of any registered service workers.
|
||||||
|
//! It also stores an active workers map, which holds descriptors of running service workers.
|
||||||
|
//! If an active service worker timeouts, then it removes the descriptor entry from its
|
||||||
|
//! active_workers map
|
||||||
|
|
||||||
|
use devtools_traits::{DevtoolsPageInfo, ScriptToDevtoolsControlMsg};
|
||||||
|
use dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
||||||
|
use dom::serviceworkerregistration::longest_prefix_match;
|
||||||
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
|
use ipc_channel::router::ROUTER;
|
||||||
|
use net_traits::{CustomResponseMediator, CoreResourceMsg};
|
||||||
|
use script_traits::{ServiceWorkerMsg, ScopeThings, SWManagerMsg, SWManagerSenders};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::mpsc::{channel, Receiver};
|
||||||
|
use url::Url;
|
||||||
|
use util::thread::spawn_named;
|
||||||
|
|
||||||
|
pub struct ServiceWorkerManager {
|
||||||
|
// map of registered service worker descriptors
|
||||||
|
registered_workers: HashMap<Url, ScopeThings>,
|
||||||
|
// map of active service worker descriptors
|
||||||
|
active_workers: HashMap<Url, ScopeThings>,
|
||||||
|
// own sender to send messages here
|
||||||
|
own_sender: IpcSender<ServiceWorkerMsg>,
|
||||||
|
// receiver to receive messages from constellation
|
||||||
|
own_port: Receiver<ServiceWorkerMsg>,
|
||||||
|
// to receive resource messages
|
||||||
|
resource_receiver: Receiver<CustomResponseMediator>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServiceWorkerManager {
|
||||||
|
fn new(own_sender: IpcSender<ServiceWorkerMsg>,
|
||||||
|
from_constellation_receiver: Receiver<ServiceWorkerMsg>,
|
||||||
|
resource_port: Receiver<CustomResponseMediator>) -> ServiceWorkerManager {
|
||||||
|
ServiceWorkerManager {
|
||||||
|
registered_workers: HashMap::new(),
|
||||||
|
active_workers: HashMap::new(),
|
||||||
|
own_sender: own_sender,
|
||||||
|
own_port: from_constellation_receiver,
|
||||||
|
resource_receiver: resource_port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_manager(sw_senders: SWManagerSenders) {
|
||||||
|
let (own_sender, from_constellation_receiver) = ipc::channel().unwrap();
|
||||||
|
let (resource_chan, resource_port) = ipc::channel().unwrap();
|
||||||
|
let from_constellation = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(from_constellation_receiver);
|
||||||
|
let resource_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(resource_port);
|
||||||
|
let _ = sw_senders.resource_sender.send(CoreResourceMsg::NetworkMediator(resource_chan));
|
||||||
|
let _ = sw_senders.swmanager_sender.send(SWManagerMsg::OwnSender(own_sender.clone()));
|
||||||
|
spawn_named("ServiceWorkerManager".to_owned(), move || {
|
||||||
|
ServiceWorkerManager::new(own_sender, from_constellation, resource_port).handle_message();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prepare_activation(&mut self, load_url: &Url) {
|
||||||
|
let mut scope_url = None;
|
||||||
|
for scope in self.registered_workers.keys() {
|
||||||
|
if longest_prefix_match(&scope, load_url) {
|
||||||
|
scope_url = Some(scope.clone());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref scope_url) = scope_url {
|
||||||
|
if self.active_workers.contains_key(&scope_url) {
|
||||||
|
// do not run the same worker if already active.
|
||||||
|
warn!("Service worker for {:?} already active", scope_url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let scope_things = self.registered_workers.get(&scope_url);
|
||||||
|
if let Some(scope_things) = scope_things {
|
||||||
|
let (sender, receiver) = channel();
|
||||||
|
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
|
||||||
|
if let Some(ref chan) = scope_things.devtools_chan {
|
||||||
|
let title = format!("ServiceWorker for {}", scope_things.script_url);
|
||||||
|
let page_info = DevtoolsPageInfo {
|
||||||
|
title: title,
|
||||||
|
url: scope_things.script_url.clone(),
|
||||||
|
};
|
||||||
|
let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal((scope_things.pipeline_id,
|
||||||
|
Some(scope_things.worker_id)),
|
||||||
|
devtools_sender.clone(),
|
||||||
|
page_info));
|
||||||
|
};
|
||||||
|
ServiceWorkerGlobalScope::run_serviceworker_scope(scope_things.clone(),
|
||||||
|
sender,
|
||||||
|
receiver,
|
||||||
|
devtools_receiver,
|
||||||
|
self.own_sender.clone(),
|
||||||
|
scope_url.clone());
|
||||||
|
// We store the activated worker
|
||||||
|
self.active_workers.insert(scope_url.clone(), scope_things.clone());
|
||||||
|
} else {
|
||||||
|
warn!("Unable to activate service worker");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_message(&mut self) {
|
||||||
|
while self.receive_message() {
|
||||||
|
// process message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_message_from_constellation(&mut self, msg: ServiceWorkerMsg) -> bool {
|
||||||
|
match msg {
|
||||||
|
ServiceWorkerMsg::RegisterServiceWorker(scope_things, scope) => {
|
||||||
|
if self.registered_workers.contains_key(&scope) {
|
||||||
|
warn!("ScopeThings for {:?} already stored in SW-Manager", scope);
|
||||||
|
} else {
|
||||||
|
self.registered_workers.insert(scope, scope_things);
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
ServiceWorkerMsg::Timeout(scope) => {
|
||||||
|
if self.active_workers.contains_key(&scope) {
|
||||||
|
let _ = self.active_workers.remove(&scope);
|
||||||
|
} else {
|
||||||
|
warn!("ScopeThings for {:?} is not active", scope);
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
ServiceWorkerMsg::Exit => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn handle_message_from_resource(&mut self, mediator: CustomResponseMediator) -> bool {
|
||||||
|
self.prepare_activation(&mediator.load_url);
|
||||||
|
// TODO XXXcreativcoder This mediator will need to be send to the appropriate service worker
|
||||||
|
// so that it may do the sending of custom responses.
|
||||||
|
// For now we just send a None from here itself
|
||||||
|
let _ = mediator.response_chan.send(None);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
fn receive_message(&mut self) -> bool {
|
||||||
|
enum Message {
|
||||||
|
FromResource(CustomResponseMediator),
|
||||||
|
FromConstellation(ServiceWorkerMsg)
|
||||||
|
}
|
||||||
|
let message = {
|
||||||
|
let msg_from_constellation = &self.own_port;
|
||||||
|
let msg_from_resource = &self.resource_receiver;
|
||||||
|
select! {
|
||||||
|
msg = msg_from_constellation.recv() =>
|
||||||
|
Message::FromConstellation(msg.expect("Unexpected constellation channel panic in sw-manager")),
|
||||||
|
msg = msg_from_resource.recv() =>
|
||||||
|
Message::FromResource(msg.expect("Unexpected resource channel panic in sw-manager"))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match message {
|
||||||
|
Message::FromConstellation(msg) => self.handle_message_from_constellation(msg),
|
||||||
|
Message::FromResource(mediator) => self.handle_message_from_resource(mediator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,7 +36,7 @@ mod script_msg;
|
||||||
pub mod webdriver_msg;
|
pub mod webdriver_msg;
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use devtools_traits::ScriptToDevtoolsControlMsg;
|
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
use euclid::length::Length;
|
use euclid::length::Length;
|
||||||
use euclid::point::Point2D;
|
use euclid::point::Point2D;
|
||||||
|
@ -51,13 +51,14 @@ use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||||
use layers::geometry::DevicePixel;
|
use layers::geometry::DevicePixel;
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use msg::constellation_msg::{FrameId, FrameType, Image, Key, KeyModifiers, KeyState, LoadData};
|
use msg::constellation_msg::{FrameId, FrameType, Image, Key, KeyModifiers, KeyState, LoadData};
|
||||||
use msg::constellation_msg::{NavigationDirection, PanicMsg, PipelineId};
|
use msg::constellation_msg::{NavigationDirection, PanicMsg, PipelineId, ReferrerPolicy};
|
||||||
use msg::constellation_msg::{PipelineNamespaceId, SubpageId, WindowSizeType};
|
use msg::constellation_msg::{PipelineNamespaceId, SubpageId, WindowSizeType};
|
||||||
use net_traits::ResourceThreads;
|
|
||||||
use net_traits::bluetooth_thread::BluetoothMethodMsg;
|
use net_traits::bluetooth_thread::BluetoothMethodMsg;
|
||||||
use net_traits::image_cache_thread::ImageCacheThread;
|
use net_traits::image_cache_thread::ImageCacheThread;
|
||||||
use net_traits::response::HttpsState;
|
use net_traits::response::HttpsState;
|
||||||
|
use net_traits::{LoadOrigin, ResourceThreads};
|
||||||
use profile_traits::mem;
|
use profile_traits::mem;
|
||||||
|
use profile_traits::time as profile_time;
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::mpsc::{Sender, Receiver};
|
use std::sync::mpsc::{Sender, Receiver};
|
||||||
|
@ -67,6 +68,7 @@ use util::ipc::OptionalOpaqueIpcSender;
|
||||||
use webdriver_msg::{LoadStatus, WebDriverScriptCommand};
|
use webdriver_msg::{LoadStatus, WebDriverScriptCommand};
|
||||||
|
|
||||||
pub use script_msg::{LayoutMsg, ScriptMsg, EventResult, LogEntry};
|
pub use script_msg::{LayoutMsg, ScriptMsg, EventResult, LogEntry};
|
||||||
|
pub use script_msg::{ServiceWorkerMsg, ScopeThings, SWManagerMsg, SWManagerSenders};
|
||||||
|
|
||||||
/// The address of a node. Layout sends these back. They must be validated via
|
/// The address of a node. Layout sends these back. They must be validated via
|
||||||
/// `from_untrusted_node_address` before they can be used, because we do not trust layout.
|
/// `from_untrusted_node_address` before they can be used, because we do not trust layout.
|
||||||
|
@ -603,3 +605,49 @@ pub enum ConstellationMsg {
|
||||||
/// A log entry, with the pipeline id and thread name
|
/// A log entry, with the pipeline id and thread name
|
||||||
LogEntry(Option<PipelineId>, Option<String>, LogEntry),
|
LogEntry(Option<PipelineId>, Option<String>, LogEntry),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resources required by workerglobalscopes
|
||||||
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
|
pub struct WorkerGlobalScopeInit {
|
||||||
|
/// Chan to a resource thread
|
||||||
|
pub resource_threads: ResourceThreads,
|
||||||
|
/// Chan to the memory profiler
|
||||||
|
pub mem_profiler_chan: mem::ProfilerChan,
|
||||||
|
/// Chan to the time profiler
|
||||||
|
pub time_profiler_chan: profile_time::ProfilerChan,
|
||||||
|
/// To devtools sender
|
||||||
|
pub to_devtools_sender: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||||
|
/// From devtools sender
|
||||||
|
pub from_devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
|
||||||
|
/// Messages to send to constellation
|
||||||
|
pub constellation_chan: IpcSender<ScriptMsg>,
|
||||||
|
/// Message to send to the scheduler
|
||||||
|
pub scheduler_chan: IpcSender<TimerEventRequest>,
|
||||||
|
/// Sender which sends panic messages
|
||||||
|
pub panic_chan: IpcSender<PanicMsg>,
|
||||||
|
/// The worker id
|
||||||
|
pub worker_id: WorkerId,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Common entities representing a network load origin
|
||||||
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
|
pub struct WorkerScriptLoadOrigin {
|
||||||
|
/// referrer url
|
||||||
|
pub referrer_url: Option<Url>,
|
||||||
|
/// the referrer policy which is used
|
||||||
|
pub referrer_policy: Option<ReferrerPolicy>,
|
||||||
|
/// the pipeline id of the entity requesting the load
|
||||||
|
pub pipeline_id: Option<PipelineId>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LoadOrigin for WorkerScriptLoadOrigin {
|
||||||
|
fn referrer_url(&self) -> Option<Url> {
|
||||||
|
self.referrer_url.clone()
|
||||||
|
}
|
||||||
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
|
self.referrer_policy.clone()
|
||||||
|
}
|
||||||
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
|
self.pipeline_id.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,13 +8,17 @@ use IFrameLoadInfo;
|
||||||
use MouseButton;
|
use MouseButton;
|
||||||
use MouseEventType;
|
use MouseEventType;
|
||||||
use MozBrowserEvent;
|
use MozBrowserEvent;
|
||||||
|
use WorkerGlobalScopeInit;
|
||||||
|
use WorkerScriptLoadOrigin;
|
||||||
use canvas_traits::CanvasMsg;
|
use canvas_traits::CanvasMsg;
|
||||||
|
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use euclid::point::Point2D;
|
use euclid::point::Point2D;
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
use gfx_traits::LayerId;
|
use gfx_traits::LayerId;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
|
use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
|
||||||
use msg::constellation_msg::{NavigationDirection, PipelineId, SubpageId};
|
use msg::constellation_msg::{NavigationDirection, PipelineId, SubpageId};
|
||||||
|
use net_traits::CoreResourceMsg;
|
||||||
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
||||||
use style_traits::cursor::Cursor;
|
use style_traits::cursor::Cursor;
|
||||||
use style_traits::viewport::ViewportConstraints;
|
use style_traits::viewport::ViewportConstraints;
|
||||||
|
@ -131,6 +135,51 @@ pub enum ScriptMsg {
|
||||||
LogEntry(Option<PipelineId>, Option<String>, LogEntry),
|
LogEntry(Option<PipelineId>, Option<String>, LogEntry),
|
||||||
/// Notifies the constellation that this pipeline has exited.
|
/// Notifies the constellation that this pipeline has exited.
|
||||||
PipelineExited(PipelineId),
|
PipelineExited(PipelineId),
|
||||||
|
/// Store the data required to activate a service worker for the given scope
|
||||||
|
RegisterServiceWorker(ScopeThings, Url),
|
||||||
/// Requests that the compositor shut down.
|
/// Requests that the compositor shut down.
|
||||||
|
Exit
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Entities required to spawn service workers
|
||||||
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
|
pub struct ScopeThings {
|
||||||
|
/// script resource url
|
||||||
|
pub script_url: Url,
|
||||||
|
/// pipeline which requested the activation
|
||||||
|
pub pipeline_id: PipelineId,
|
||||||
|
/// network load origin of the resource
|
||||||
|
pub worker_load_origin: WorkerScriptLoadOrigin,
|
||||||
|
/// base resources required to create worker global scopes
|
||||||
|
pub init: WorkerGlobalScopeInit,
|
||||||
|
/// the port to receive devtools message from
|
||||||
|
pub devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||||
|
/// service worker id
|
||||||
|
pub worker_id: WorkerId,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Channels to allow service worker manager to communicate with constellation and resource thread
|
||||||
|
pub struct SWManagerSenders {
|
||||||
|
/// sender for communicating with constellation
|
||||||
|
pub swmanager_sender: IpcSender<SWManagerMsg>,
|
||||||
|
/// sender for communicating with resource thread
|
||||||
|
pub resource_sender: IpcSender<CoreResourceMsg>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Messages sent to Service Worker Manager thread
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub enum ServiceWorkerMsg {
|
||||||
|
/// Message to register the service worker
|
||||||
|
RegisterServiceWorker(ScopeThings, Url),
|
||||||
|
/// Timeout message sent by active service workers
|
||||||
|
Timeout(Url),
|
||||||
|
/// Exit the service worker manager
|
||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Messages outgoing from the Service Worker Manager thread to constellation
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub enum SWManagerMsg {
|
||||||
|
/// Provide the constellation with a means of communicating with the Service Worker Manager
|
||||||
|
OwnSender(IpcSender<ServiceWorkerMsg>),
|
||||||
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ use profile::mem as profile_mem;
|
||||||
use profile::time as profile_time;
|
use profile::time as profile_time;
|
||||||
use profile_traits::mem;
|
use profile_traits::mem;
|
||||||
use profile_traits::time;
|
use profile_traits::time;
|
||||||
use script_traits::{ConstellationMsg, ScriptMsg};
|
use script_traits::{ConstellationMsg, ScriptMsg, SWManagerSenders};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
|
@ -114,7 +114,6 @@ impl<Window> Browser<Window> where Window: WindowMethods + 'static {
|
||||||
// Global configuration options, parsed from the command line.
|
// Global configuration options, parsed from the command line.
|
||||||
let opts = opts::get();
|
let opts = opts::get();
|
||||||
|
|
||||||
script::init();
|
|
||||||
|
|
||||||
// Get both endpoints of a special channel for communication between
|
// Get both endpoints of a special channel for communication between
|
||||||
// the client window and the compositor. This channel is unique because
|
// the client window and the compositor. This channel is unique because
|
||||||
|
@ -160,7 +159,7 @@ impl<Window> Browser<Window> where Window: WindowMethods + 'static {
|
||||||
// Create the constellation, which maintains the engine
|
// Create the constellation, which maintains the engine
|
||||||
// pipelines, including the script and layout threads, as well
|
// pipelines, including the script and layout threads, as well
|
||||||
// as the navigation context.
|
// as the navigation context.
|
||||||
let constellation_chan = create_constellation(opts.clone(),
|
let (constellation_chan, sw_senders) = create_constellation(opts.clone(),
|
||||||
compositor_proxy.clone_compositor_proxy(),
|
compositor_proxy.clone_compositor_proxy(),
|
||||||
time_profiler_chan.clone(),
|
time_profiler_chan.clone(),
|
||||||
mem_profiler_chan.clone(),
|
mem_profiler_chan.clone(),
|
||||||
|
@ -168,6 +167,9 @@ impl<Window> Browser<Window> where Window: WindowMethods + 'static {
|
||||||
supports_clipboard,
|
supports_clipboard,
|
||||||
webrender_api_sender.clone());
|
webrender_api_sender.clone());
|
||||||
|
|
||||||
|
// Send the constellation's swmanager sender to service worker manager thread
|
||||||
|
script::init(sw_senders);
|
||||||
|
|
||||||
if cfg!(feature = "webdriver") {
|
if cfg!(feature = "webdriver") {
|
||||||
if let Some(port) = opts.webdriver_port {
|
if let Some(port) = opts.webdriver_port {
|
||||||
webdriver(port, constellation_chan.clone());
|
webdriver(port, constellation_chan.clone());
|
||||||
|
@ -227,7 +229,8 @@ fn create_constellation(opts: opts::Opts,
|
||||||
mem_profiler_chan: mem::ProfilerChan,
|
mem_profiler_chan: mem::ProfilerChan,
|
||||||
devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
|
devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
|
||||||
supports_clipboard: bool,
|
supports_clipboard: bool,
|
||||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Sender<ConstellationMsg> {
|
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
||||||
|
-> (Sender<ConstellationMsg>, SWManagerSenders) {
|
||||||
let bluetooth_thread: IpcSender<BluetoothMethodMsg> = BluetoothThreadFactory::new();
|
let bluetooth_thread: IpcSender<BluetoothMethodMsg> = BluetoothThreadFactory::new();
|
||||||
|
|
||||||
let (public_resource_threads, private_resource_threads) =
|
let (public_resource_threads, private_resource_threads) =
|
||||||
|
@ -239,6 +242,8 @@ fn create_constellation(opts: opts::Opts,
|
||||||
let font_cache_thread = FontCacheThread::new(public_resource_threads.sender(),
|
let font_cache_thread = FontCacheThread::new(public_resource_threads.sender(),
|
||||||
webrender_api_sender.as_ref().map(|wr| wr.create_api()));
|
webrender_api_sender.as_ref().map(|wr| wr.create_api()));
|
||||||
|
|
||||||
|
let resource_sender = public_resource_threads.sender();
|
||||||
|
|
||||||
let initial_state = InitialConstellationState {
|
let initial_state = InitialConstellationState {
|
||||||
compositor_proxy: compositor_proxy,
|
compositor_proxy: compositor_proxy,
|
||||||
devtools_chan: devtools_chan,
|
devtools_chan: devtools_chan,
|
||||||
|
@ -252,7 +257,7 @@ fn create_constellation(opts: opts::Opts,
|
||||||
supports_clipboard: supports_clipboard,
|
supports_clipboard: supports_clipboard,
|
||||||
webrender_api_sender: webrender_api_sender,
|
webrender_api_sender: webrender_api_sender,
|
||||||
};
|
};
|
||||||
let constellation_chan =
|
let (constellation_chan, from_swmanager_sender) =
|
||||||
Constellation::<script_layout_interface::message::Msg,
|
Constellation::<script_layout_interface::message::Msg,
|
||||||
layout_thread::LayoutThread,
|
layout_thread::LayoutThread,
|
||||||
script::script_thread::ScriptThread>::start(initial_state);
|
script::script_thread::ScriptThread>::start(initial_state);
|
||||||
|
@ -261,7 +266,13 @@ fn create_constellation(opts: opts::Opts,
|
||||||
constellation_chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
|
constellation_chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
|
||||||
};
|
};
|
||||||
|
|
||||||
constellation_chan
|
// channels to communicate with Service Worker Manager
|
||||||
|
let sw_senders = SWManagerSenders {
|
||||||
|
swmanager_sender: from_swmanager_sender,
|
||||||
|
resource_sender: resource_sender
|
||||||
|
};
|
||||||
|
|
||||||
|
(constellation_chan, sw_senders)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A logger that logs to two downstream loggers.
|
// A logger that logs to two downstream loggers.
|
||||||
|
@ -308,7 +319,9 @@ pub fn run_content_process(token: String) {
|
||||||
create_sandbox();
|
create_sandbox();
|
||||||
}
|
}
|
||||||
|
|
||||||
script::init();
|
// send the required channels to the service worker manager
|
||||||
|
let sw_senders = unprivileged_content.swmanager_senders();
|
||||||
|
script::init(sw_senders);
|
||||||
|
|
||||||
unprivileged_content.start_all::<script_layout_interface::message::Msg,
|
unprivileged_content.start_all::<script_layout_interface::message::Msg,
|
||||||
layout_thread::LayoutThread,
|
layout_thread::LayoutThread,
|
||||||
|
|
BIN
tests/html/service-worker/assets/tty.gif
Normal file
BIN
tests/html/service-worker/assets/tty.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
14
tests/html/service-worker/dashboard-page.html
Normal file
14
tests/html/service-worker/dashboard-page.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Dashboard Page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<a href="/">Back to home</a>
|
||||||
|
<h3>The dashboard page</h3>
|
||||||
|
<a href="http://github.com/servo/servo">Servo Project</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
13
tests/html/service-worker/demo_iframe.html
Normal file
13
tests/html/service-worker/demo_iframe.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>An iframe</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<a href="http://github.com/servo/servo">Servo Project</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
1
tests/html/service-worker/dummy.js
Normal file
1
tests/html/service-worker/dummy.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
console.log("dummy test file");
|
1
tests/html/service-worker/iframe_sw.js
Normal file
1
tests/html/service-worker/iframe_sw.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
console.log("iframe service worker active");
|
43
tests/html/service-worker/index.html
Normal file
43
tests/html/service-worker/index.html
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Service Worker Tests</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>This page tests the registration and initialization of Service Workers in Servo.</p>
|
||||||
|
<div id="registration">
|
||||||
|
<a href="/dashboard-page.html">Go to Dashboard</a>
|
||||||
|
<a href="/profile.html">Go to Profile</a>
|
||||||
|
<iframe id="iframe_sw" width="" height="200"></iframe>
|
||||||
|
<br>
|
||||||
|
<button onclick="register_zero()">Register for Root</button>
|
||||||
|
<button onclick="register_one()">Register for Dashboard</button>
|
||||||
|
<button onclick="register_two()">Register for Profile</button>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
var reg = navigator.serviceWorker.register('iframe_sw.js', { 'scope': '/demo_iframe.html' });
|
||||||
|
console.log("From client worker registered: ", navigator.serviceWorker.controller);
|
||||||
|
console.log("Registered script source: ", navigator.serviceWorker.controller.scriptURL);
|
||||||
|
document.getElementById('iframe_sw').src = 'demo_iframe.html';
|
||||||
|
|
||||||
|
function register_zero() {
|
||||||
|
var reg = navigator.serviceWorker.register('sw.js', { 'scope': './' });
|
||||||
|
console.log("From client worker registered: ", navigator.serviceWorker.controller);
|
||||||
|
console.log("Registered script source: ", navigator.serviceWorker.controller.scriptURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
function register_one() {
|
||||||
|
var reg = navigator.serviceWorker.register('sw_dashboard.js', { 'scope': '/dashboard' });
|
||||||
|
console.log("From client worker registered: ", navigator.serviceWorker.controller);
|
||||||
|
console.log("Registered script source: ", navigator.serviceWorker.controller.scriptURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
function register_two() {
|
||||||
|
var reg = navigator.serviceWorker.register('sw_profile.js', { 'scope': '/profile' });
|
||||||
|
console.log("From client worker registered: ", navigator.serviceWorker.controller);
|
||||||
|
console.log("Registered script source: ", navigator.serviceWorker.controller.scriptURL);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
14
tests/html/service-worker/profile.html
Normal file
14
tests/html/service-worker/profile.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Profile Page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<a href="/">Back to home</a>
|
||||||
|
<h3>The profile page</h3>
|
||||||
|
<a href="http://github.com/servo/servo">Servo Project</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
1
tests/html/service-worker/sw.js
Normal file
1
tests/html/service-worker/sw.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
console.log("root service worker: active");
|
2
tests/html/service-worker/sw_dashboard.js
Normal file
2
tests/html/service-worker/sw_dashboard.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
importScripts('dummy.js');
|
||||||
|
console.log("dashboard service worker: active");
|
1
tests/html/service-worker/sw_profile.js
Normal file
1
tests/html/service-worker/sw_profile.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
console.log("profile service worker: active");
|
|
@ -8,7 +8,7 @@ use ipc_channel::ipc;
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
||||||
use net_traits::LoadConsumer::Channel;
|
use net_traits::LoadConsumer::Channel;
|
||||||
use net_traits::ProgressMsg::{Payload, Done};
|
use net_traits::ProgressMsg::{Payload, Done};
|
||||||
use net_traits::{LoadData, LoadContext, NetworkError, LoadOrigin, RequestSource};
|
use net_traits::{LoadData, LoadContext, NetworkError, LoadOrigin};
|
||||||
use self::hyper::header::ContentType;
|
use self::hyper::header::ContentType;
|
||||||
use self::hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
|
use self::hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -22,9 +22,6 @@ impl LoadOrigin for DataLoadTest {
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn request_source(&self) -> RequestSource {
|
|
||||||
RequestSource::None
|
|
||||||
}
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ use net::hsts::HstsEntry;
|
||||||
use net::http_loader::{LoadErrorType, HttpResponse};
|
use net::http_loader::{LoadErrorType, HttpResponse};
|
||||||
use net::http_loader::{load, LoadError, HttpRequestFactory, HttpRequest, UIProvider, HttpState};
|
use net::http_loader::{load, LoadError, HttpRequestFactory, HttpRequest, UIProvider, HttpState};
|
||||||
use net::resource_thread::{AuthCacheEntry, CancellationListener};
|
use net::resource_thread::{AuthCacheEntry, CancellationListener};
|
||||||
use net_traits::{CustomResponse, RequestSource, Metadata, LoadOrigin};
|
use net_traits::{CustomResponse, Metadata, LoadOrigin};
|
||||||
use net_traits::{LoadData, CookieSource, LoadContext, IncludeSubdomains};
|
use net_traits::{LoadData, CookieSource, LoadContext, IncludeSubdomains};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::io::{self, Write, Read, Cursor};
|
use std::io::{self, Write, Read, Cursor};
|
||||||
|
@ -46,9 +46,6 @@ impl LoadOrigin for HttpTest {
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn request_source(&self) -> RequestSource {
|
|
||||||
RequestSource::None
|
|
||||||
}
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
Some(PipelineId::fake_root_pipeline_id())
|
Some(PipelineId::fake_root_pipeline_id())
|
||||||
}
|
}
|
||||||
|
@ -66,9 +63,6 @@ impl<'a> LoadOrigin for LoadOriginInfo<'a> {
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
self.referrer_policy.clone()
|
self.referrer_policy.clone()
|
||||||
}
|
}
|
||||||
fn request_source(&self) -> RequestSource {
|
|
||||||
RequestSource::None
|
|
||||||
}
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -176,11 +170,6 @@ fn redirect_with_headers(host: String, mut headers: Headers) -> MockResponse {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Source {
|
|
||||||
Window,
|
|
||||||
Worker
|
|
||||||
}
|
|
||||||
|
|
||||||
fn respond_404() -> MockResponse {
|
fn respond_404() -> MockResponse {
|
||||||
MockResponse::new(
|
MockResponse::new(
|
||||||
Headers::new(),
|
Headers::new(),
|
||||||
|
@ -426,7 +415,7 @@ fn test_check_default_headers_loaded_in_every_request() {
|
||||||
&AssertMustHaveHeadersRequestFactory {
|
&AssertMustHaveHeadersRequestFactory {
|
||||||
expected_headers: headers.clone(),
|
expected_headers: headers.clone(),
|
||||||
body: <[_]>::to_vec(&[])
|
body: <[_]>::to_vec(&[])
|
||||||
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
|
|
||||||
// Testing for method.POST
|
// Testing for method.POST
|
||||||
load_data.method = Method::Post;
|
load_data.method = Method::Post;
|
||||||
|
@ -437,7 +426,7 @@ fn test_check_default_headers_loaded_in_every_request() {
|
||||||
&AssertMustHaveHeadersRequestFactory {
|
&AssertMustHaveHeadersRequestFactory {
|
||||||
expected_headers: headers,
|
expected_headers: headers,
|
||||||
body: <[_]>::to_vec(&[])
|
body: <[_]>::to_vec(&[])
|
||||||
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -459,7 +448,7 @@ fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length
|
||||||
None, &AssertMustIncludeHeadersRequestFactory {
|
None, &AssertMustIncludeHeadersRequestFactory {
|
||||||
expected_headers: content_length,
|
expected_headers: content_length,
|
||||||
body: <[_]>::to_vec(&[])
|
body: <[_]>::to_vec(&[])
|
||||||
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -490,7 +479,7 @@ fn test_request_and_response_data_with_network_messages() {
|
||||||
request_headers.set(Host { hostname: "bar.foo".to_owned(), port: None });
|
request_headers.set(Host { hostname: "bar.foo".to_owned(), port: None });
|
||||||
load_data.headers = request_headers.clone();
|
load_data.headers = request_headers.clone();
|
||||||
let _ = load(&load_data, &ui_provider, &http_state, Some(devtools_chan), &Factory,
|
let _ = load(&load_data, &ui_provider, &http_state, Some(devtools_chan), &Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
|
|
||||||
// notification received from devtools
|
// notification received from devtools
|
||||||
let devhttprequest = expect_devtools_http_request(&devtools_port);
|
let devhttprequest = expect_devtools_http_request(&devtools_port);
|
||||||
|
@ -563,9 +552,6 @@ impl LoadOrigin for HttpTestNoPipeline {
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn request_source(&self) -> RequestSource {
|
|
||||||
RequestSource::None
|
|
||||||
}
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -594,7 +580,7 @@ fn test_request_and_response_message_from_devtool_without_pipeline_id() {
|
||||||
let (devtools_chan, devtools_port) = mpsc::channel::<DevtoolsControlMsg>();
|
let (devtools_chan, devtools_port) = mpsc::channel::<DevtoolsControlMsg>();
|
||||||
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), &HttpTestNoPipeline);
|
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), &HttpTestNoPipeline);
|
||||||
let _ = load(&load_data, &ui_provider, &http_state, Some(devtools_chan), &Factory,
|
let _ = load(&load_data, &ui_provider, &http_state, Some(devtools_chan), &Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
|
|
||||||
// notification received from devtools
|
// notification received from devtools
|
||||||
assert!(devtools_port.try_recv().is_err());
|
assert!(devtools_port.try_recv().is_err());
|
||||||
|
@ -629,7 +615,7 @@ fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() {
|
||||||
let ui_provider = TestProvider::new();
|
let ui_provider = TestProvider::new();
|
||||||
|
|
||||||
let _ = load(&load_data, &ui_provider, &http_state, None, &Factory,
|
let _ = load(&load_data, &ui_provider, &http_state, None, &Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -660,7 +646,8 @@ fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_co
|
||||||
&load_data, &ui_provider, &http_state, None,
|
&load_data, &ui_provider, &http_state, None,
|
||||||
&Factory,
|
&Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None))
|
&CancellationListener::new(None),
|
||||||
|
None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(read_response(&mut response), "Yay!");
|
assert_eq!(read_response(&mut response), "Yay!");
|
||||||
|
@ -695,7 +682,8 @@ fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_conte
|
||||||
&ui_provider, &http_state,
|
&ui_provider, &http_state,
|
||||||
None, &Factory,
|
None, &Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None))
|
&CancellationListener::new(None),
|
||||||
|
None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(read_response(&mut response), "Yay!");
|
assert_eq!(read_response(&mut response), "Yay!");
|
||||||
|
@ -740,7 +728,8 @@ fn test_load_doesnt_send_request_body_on_any_redirect() {
|
||||||
None,
|
None,
|
||||||
&Factory,
|
&Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None),
|
||||||
|
None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -770,7 +759,8 @@ fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_ar
|
||||||
None,
|
None,
|
||||||
&Factory,
|
&Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None),
|
||||||
|
None);
|
||||||
|
|
||||||
assert_eq!(http_state.hsts_list.read().unwrap().is_host_secure("mozilla.com"), false);
|
assert_eq!(http_state.hsts_list.read().unwrap().is_host_secure("mozilla.com"), false);
|
||||||
}
|
}
|
||||||
|
@ -802,7 +792,8 @@ fn test_load_adds_host_to_sts_list_when_url_is_https_and_sts_headers_are_present
|
||||||
None,
|
None,
|
||||||
&Factory,
|
&Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None),
|
||||||
|
None);
|
||||||
|
|
||||||
assert!(http_state.hsts_list.read().unwrap().is_host_secure("mozilla.com"));
|
assert!(http_state.hsts_list.read().unwrap().is_host_secure("mozilla.com"));
|
||||||
}
|
}
|
||||||
|
@ -836,7 +827,8 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_
|
||||||
None,
|
None,
|
||||||
&Factory,
|
&Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None),
|
||||||
|
None);
|
||||||
|
|
||||||
assert_cookie_for_domain(http_state.cookie_jar.clone(), "http://mozilla.com", "mozillaIs=theBest");
|
assert_cookie_for_domain(http_state.cookie_jar.clone(), "http://mozilla.com", "mozillaIs=theBest");
|
||||||
}
|
}
|
||||||
|
@ -870,7 +862,7 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re
|
||||||
expected_headers: cookie,
|
expected_headers: cookie,
|
||||||
body: <[_]>::to_vec(&*load_data.data.unwrap())
|
body: <[_]>::to_vec(&*load_data.data.unwrap())
|
||||||
}, DEFAULT_USER_AGENT.to_owned(),
|
}, DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -912,7 +904,7 @@ fn test_load_sends_secure_cookie_if_http_changed_to_https_due_to_entry_in_hsts_s
|
||||||
&AssertMustIncludeHeadersRequestFactory {
|
&AssertMustIncludeHeadersRequestFactory {
|
||||||
expected_headers: headers,
|
expected_headers: headers,
|
||||||
body: <[_]>::to_vec(&*load_data.data.unwrap())
|
body: <[_]>::to_vec(&*load_data.data.unwrap())
|
||||||
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -944,7 +936,7 @@ fn test_load_sends_cookie_if_nonhttp() {
|
||||||
&AssertMustIncludeHeadersRequestFactory {
|
&AssertMustIncludeHeadersRequestFactory {
|
||||||
expected_headers: headers,
|
expected_headers: headers,
|
||||||
body: <[_]>::to_vec(&*load_data.data.unwrap())
|
body: <[_]>::to_vec(&*load_data.data.unwrap())
|
||||||
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -973,7 +965,7 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl(
|
||||||
None,
|
None,
|
||||||
&Factory,
|
&Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None), None);
|
||||||
|
|
||||||
let mut cookie_jar = http_state.cookie_jar.write().unwrap();
|
let mut cookie_jar = http_state.cookie_jar.write().unwrap();
|
||||||
assert!(cookie_jar.cookies_for_url(&url, CookieSource::NonHTTP).is_none());
|
assert!(cookie_jar.cookies_for_url(&url, CookieSource::NonHTTP).is_none());
|
||||||
|
@ -1003,7 +995,7 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() {
|
||||||
None,
|
None,
|
||||||
&Factory,
|
&Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None), None);
|
||||||
|
|
||||||
assert_cookie_for_domain(http_state.cookie_jar.clone(), "http://mozilla.com", "");
|
assert_cookie_for_domain(http_state.cookie_jar.clone(), "http://mozilla.com", "");
|
||||||
}
|
}
|
||||||
|
@ -1037,7 +1029,7 @@ fn test_when_cookie_set_marked_httpsonly_secure_isnt_sent_on_http_request() {
|
||||||
&AssertMustNotIncludeHeadersRequestFactory {
|
&AssertMustNotIncludeHeadersRequestFactory {
|
||||||
headers_not_expected: vec!["Cookie".to_owned()],
|
headers_not_expected: vec!["Cookie".to_owned()],
|
||||||
body: <[_]>::to_vec(&*load_data.data.unwrap())
|
body: <[_]>::to_vec(&*load_data.data.unwrap())
|
||||||
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1060,7 +1052,7 @@ fn test_load_sets_content_length_to_length_of_request_body() {
|
||||||
expected_headers: content_len_headers,
|
expected_headers: content_len_headers,
|
||||||
body: <[_]>::to_vec(&*load_data.data.unwrap())
|
body: <[_]>::to_vec(&*load_data.data.unwrap())
|
||||||
}, DEFAULT_USER_AGENT.to_owned(),
|
}, DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1086,7 +1078,7 @@ fn test_load_uses_explicit_accept_from_headers_in_load_data() {
|
||||||
expected_headers: accept_headers,
|
expected_headers: accept_headers,
|
||||||
body: <[_]>::to_vec("Yay!".as_bytes())
|
body: <[_]>::to_vec("Yay!".as_bytes())
|
||||||
}, DEFAULT_USER_AGENT.to_owned(),
|
}, DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1114,7 +1106,7 @@ fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() {
|
||||||
expected_headers: accept_headers,
|
expected_headers: accept_headers,
|
||||||
body: <[_]>::to_vec("Yay!".as_bytes())
|
body: <[_]>::to_vec("Yay!".as_bytes())
|
||||||
}, DEFAULT_USER_AGENT.to_owned(),
|
}, DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1137,7 +1129,7 @@ fn test_load_uses_explicit_accept_encoding_from_load_data_headers() {
|
||||||
expected_headers: accept_encoding_headers,
|
expected_headers: accept_encoding_headers,
|
||||||
body: <[_]>::to_vec("Yay!".as_bytes())
|
body: <[_]>::to_vec("Yay!".as_bytes())
|
||||||
}, DEFAULT_USER_AGENT.to_owned(),
|
}, DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1161,7 +1153,7 @@ fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() {
|
||||||
expected_headers: accept_encoding_headers,
|
expected_headers: accept_encoding_headers,
|
||||||
body: <[_]>::to_vec("Yay!".as_bytes())
|
body: <[_]>::to_vec("Yay!".as_bytes())
|
||||||
}, DEFAULT_USER_AGENT.to_owned(),
|
}, DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1189,7 +1181,7 @@ fn test_load_errors_when_there_a_redirect_loop() {
|
||||||
let ui_provider = TestProvider::new();
|
let ui_provider = TestProvider::new();
|
||||||
|
|
||||||
match load(&load_data, &ui_provider, &http_state, None, &Factory,
|
match load(&load_data, &ui_provider, &http_state, None, &Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) {
|
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None) {
|
||||||
Err(ref load_err) if load_err.error == LoadErrorType::RedirectLoop => (),
|
Err(ref load_err) if load_err.error == LoadErrorType::RedirectLoop => (),
|
||||||
_ => panic!("expected max redirects to fail")
|
_ => panic!("expected max redirects to fail")
|
||||||
}
|
}
|
||||||
|
@ -1222,7 +1214,7 @@ fn test_load_errors_when_there_is_too_many_redirects() {
|
||||||
prefs::PrefValue::Number(redirect_limit));
|
prefs::PrefValue::Number(redirect_limit));
|
||||||
|
|
||||||
match load(&load_data, &ui_provider, &http_state, None, &Factory,
|
match load(&load_data, &ui_provider, &http_state, None, &Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) {
|
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None) {
|
||||||
Err(LoadError { error: LoadErrorType::MaxRedirects(num_redirects),
|
Err(LoadError { error: LoadErrorType::MaxRedirects(num_redirects),
|
||||||
url, .. }) => {
|
url, .. }) => {
|
||||||
assert_eq!(num_redirects, redirect_limit as u32);
|
assert_eq!(num_redirects, redirect_limit as u32);
|
||||||
|
@ -1264,7 +1256,7 @@ fn test_load_follows_a_redirect() {
|
||||||
let ui_provider = TestProvider::new();
|
let ui_provider = TestProvider::new();
|
||||||
|
|
||||||
match load(&load_data, &ui_provider, &http_state, None, &Factory,
|
match load(&load_data, &ui_provider, &http_state, None, &Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) {
|
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None) {
|
||||||
Err(e) => panic!("expected to follow a redirect {:?}", e),
|
Err(e) => panic!("expected to follow a redirect {:?}", e),
|
||||||
Ok(mut lr) => {
|
Ok(mut lr) => {
|
||||||
let response = read_response(&mut lr);
|
let response = read_response(&mut lr);
|
||||||
|
@ -1296,7 +1288,7 @@ fn test_load_errors_when_scheme_is_not_http_or_https() {
|
||||||
None,
|
None,
|
||||||
&DontConnectFactory,
|
&DontConnectFactory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None)) {
|
&CancellationListener::new(None), None) {
|
||||||
Err(ref load_err) if load_err.error == LoadErrorType::UnsupportedScheme { scheme: "ftp".into() } => (),
|
Err(ref load_err) if load_err.error == LoadErrorType::UnsupportedScheme { scheme: "ftp".into() } => (),
|
||||||
_ => panic!("expected ftp scheme to be unsupported")
|
_ => panic!("expected ftp scheme to be unsupported")
|
||||||
}
|
}
|
||||||
|
@ -1315,7 +1307,7 @@ fn test_load_errors_when_viewing_source_and_inner_url_scheme_is_not_http_or_http
|
||||||
None,
|
None,
|
||||||
&DontConnectFactory,
|
&DontConnectFactory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None)) {
|
&CancellationListener::new(None), None) {
|
||||||
Err(ref load_err) if load_err.error == LoadErrorType::UnsupportedScheme { scheme: "ftp".into() } => (),
|
Err(ref load_err) if load_err.error == LoadErrorType::UnsupportedScheme { scheme: "ftp".into() } => (),
|
||||||
_ => panic!("expected ftp scheme to be unsupported")
|
_ => panic!("expected ftp scheme to be unsupported")
|
||||||
}
|
}
|
||||||
|
@ -1357,7 +1349,7 @@ fn test_load_errors_when_cancelled() {
|
||||||
None,
|
None,
|
||||||
&Factory,
|
&Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&cancel_listener) {
|
&cancel_listener, None) {
|
||||||
Err(ref load_err) if load_err.error == LoadErrorType::Cancelled => (),
|
Err(ref load_err) if load_err.error == LoadErrorType::Cancelled => (),
|
||||||
_ => panic!("expected load cancelled error!")
|
_ => panic!("expected load cancelled error!")
|
||||||
}
|
}
|
||||||
|
@ -1427,7 +1419,7 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() {
|
||||||
None,
|
None,
|
||||||
&Factory,
|
&Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None)) {
|
&CancellationListener::new(None), None) {
|
||||||
Err(e) => panic!("expected to follow a redirect {:?}", e),
|
Err(e) => panic!("expected to follow a redirect {:?}", e),
|
||||||
Ok(mut lr) => {
|
Ok(mut lr) => {
|
||||||
let response = read_response(&mut lr);
|
let response = read_response(&mut lr);
|
||||||
|
@ -1473,7 +1465,7 @@ fn test_redirect_from_x_to_x_provides_x_with_cookie_from_first_response() {
|
||||||
None,
|
None,
|
||||||
&Factory,
|
&Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(),
|
DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None)) {
|
&CancellationListener::new(None), None) {
|
||||||
Err(e) => panic!("expected to follow a redirect {:?}", e),
|
Err(e) => panic!("expected to follow a redirect {:?}", e),
|
||||||
Ok(mut lr) => {
|
Ok(mut lr) => {
|
||||||
let response = read_response(&mut lr);
|
let response = read_response(&mut lr);
|
||||||
|
@ -1515,7 +1507,7 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() {
|
||||||
None, &AssertMustIncludeHeadersRequestFactory {
|
None, &AssertMustIncludeHeadersRequestFactory {
|
||||||
expected_headers: auth_header,
|
expected_headers: auth_header,
|
||||||
body: <[_]>::to_vec(&[])
|
body: <[_]>::to_vec(&[])
|
||||||
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1542,7 +1534,7 @@ fn test_auth_ui_sets_header_on_401() {
|
||||||
None, &AssertAuthHeaderRequestFactory {
|
None, &AssertAuthHeaderRequestFactory {
|
||||||
expected_headers: auth_header,
|
expected_headers: auth_header,
|
||||||
body: <[_]>::to_vec(&[])
|
body: <[_]>::to_vec(&[])
|
||||||
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None)) {
|
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None) {
|
||||||
Err(e) => panic!("response contained error {:?}", e),
|
Err(e) => panic!("response contained error {:?}", e),
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
assert_eq!(response.metadata.status, Some(RawStatus(200, Cow::Borrowed("Ok"))));
|
assert_eq!(response.metadata.status, Some(RawStatus(200, Cow::Borrowed("Ok"))));
|
||||||
|
@ -1575,7 +1567,7 @@ fn test_auth_ui_needs_www_auth() {
|
||||||
|
|
||||||
let response = load(&load_data, &AuthProvider, &http_state,
|
let response = load(&load_data, &AuthProvider, &http_state,
|
||||||
None, &Factory, DEFAULT_USER_AGENT.to_owned(),
|
None, &Factory, DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None), None);
|
||||||
match response {
|
match response {
|
||||||
Err(e) => panic!("response contained error {:?}", e),
|
Err(e) => panic!("response contained error {:?}", e),
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
|
@ -1604,7 +1596,7 @@ fn assert_referer_header_matches(origin_info: &LoadOrigin,
|
||||||
expected_headers: referer_headers,
|
expected_headers: referer_headers,
|
||||||
body: <[_]>::to_vec(&[])
|
body: <[_]>::to_vec(&[])
|
||||||
}, DEFAULT_USER_AGENT.to_owned(),
|
}, DEFAULT_USER_AGENT.to_owned(),
|
||||||
&CancellationListener::new(None));
|
&CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_referer_header_not_included(origin_info: &LoadOrigin, request_url: &str) {
|
fn assert_referer_header_not_included(origin_info: &LoadOrigin, request_url: &str) {
|
||||||
|
@ -1622,7 +1614,7 @@ fn assert_referer_header_not_included(origin_info: &LoadOrigin, request_url: &st
|
||||||
&AssertMustNotIncludeHeadersRequestFactory {
|
&AssertMustNotIncludeHeadersRequestFactory {
|
||||||
headers_not_expected: vec!["Referer".to_owned()],
|
headers_not_expected: vec!["Referer".to_owned()],
|
||||||
body: <[_]>::to_vec(&[])
|
body: <[_]>::to_vec(&[])
|
||||||
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1860,7 +1852,7 @@ fn test_no_referer_set_with_noreferrer_policy() {
|
||||||
assert_referer_header_not_included(&origin_info, request_url)
|
assert_referer_header_not_included(&origin_info, request_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_request_with_source(source: Source, expected_body: Vec<u8>) -> (Metadata, String) {
|
fn load_request_for_custom_response(expected_body: Vec<u8>) -> (Metadata, String) {
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
|
|
||||||
|
@ -1880,16 +1872,11 @@ fn load_request_with_source(source: Source, expected_body: Vec<u8>) -> (Metadata
|
||||||
let url = Url::parse("http://mozilla.com").unwrap();
|
let url = Url::parse("http://mozilla.com").unwrap();
|
||||||
let http_state = HttpState::new();
|
let http_state = HttpState::new();
|
||||||
let ui_provider = TestProvider::new();
|
let ui_provider = TestProvider::new();
|
||||||
let mut load_data = LoadData::new(LoadContext::Browsing, url.clone(), &HttpTest);
|
let load_data = LoadData::new(LoadContext::Browsing, url.clone(), &HttpTest);
|
||||||
|
|
||||||
match source {
|
|
||||||
Source::Window => load_data.source = RequestSource::Window(sender.clone()),
|
|
||||||
Source::Worker => load_data.source = RequestSource::Worker(sender.clone()),
|
|
||||||
}
|
|
||||||
|
|
||||||
let join_handle = thread::spawn(move || {
|
let join_handle = thread::spawn(move || {
|
||||||
let response = load(&load_data.clone(), &ui_provider, &http_state,
|
let response = load(&load_data.clone(), &ui_provider, &http_state,
|
||||||
None, &Factory, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
None, &Factory, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), Some(sender));
|
||||||
match response {
|
match response {
|
||||||
Ok(mut response) => {
|
Ok(mut response) => {
|
||||||
let metadata = response.metadata.clone();
|
let metadata = response.metadata.clone();
|
||||||
|
@ -1900,24 +1887,16 @@ fn load_request_with_source(source: Source, expected_body: Vec<u8>) -> (Metadata
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let network_sender = receiver.recv().unwrap();
|
let mediator = receiver.recv().unwrap();
|
||||||
network_sender.send(Some(mock_response)).unwrap();
|
mediator.response_chan.send(Some(mock_response)).unwrap();
|
||||||
let (metadata, body) = join_handle.join().unwrap();
|
let (metadata, body) = join_handle.join().unwrap();
|
||||||
(metadata, body)
|
(metadata, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_custom_response_from_window() {
|
fn test_custom_response() {
|
||||||
let expected_body = b"Yay! From Window".to_vec();
|
let expected_body = b"Yay!".to_vec();
|
||||||
let (metadata, body) = load_request_with_source(Source::Window, expected_body.clone());
|
let (metadata, body) = load_request_for_custom_response(expected_body.clone());
|
||||||
assert_eq!(metadata.status, Some(RawStatus(200, Cow::Borrowed("OK"))));
|
|
||||||
assert_eq!(body, String::from_utf8(expected_body).unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_custom_response_from_worker() {
|
|
||||||
let expected_body = b"Yay! From Worker".to_vec();
|
|
||||||
let (metadata, body) = load_request_with_source(Source::Worker, expected_body.clone());
|
|
||||||
assert_eq!(metadata.status, Some(RawStatus(200, Cow::Borrowed("OK"))));
|
assert_eq!(metadata.status, Some(RawStatus(200, Cow::Borrowed("OK"))));
|
||||||
assert_eq!(body, String::from_utf8(expected_body).unwrap());
|
assert_eq!(body, String::from_utf8(expected_body).unwrap());
|
||||||
}
|
}
|
||||||
|
@ -1963,7 +1942,7 @@ fn test_content_blocked() {
|
||||||
None, &AssertMustNotIncludeHeadersRequestFactory {
|
None, &AssertMustNotIncludeHeadersRequestFactory {
|
||||||
headers_not_expected: vec!["Cookie".to_owned()],
|
headers_not_expected: vec!["Cookie".to_owned()],
|
||||||
body: b"hi".to_vec(),
|
body: b"hi".to_vec(),
|
||||||
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
}, DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
match response {
|
match response {
|
||||||
Ok(_) => {},
|
Ok(_) => {},
|
||||||
_ => panic!("request should have succeeded without cookies"),
|
_ => panic!("request should have succeeded without cookies"),
|
||||||
|
@ -1974,7 +1953,7 @@ fn test_content_blocked() {
|
||||||
let response = load(
|
let response = load(
|
||||||
&load_data, &ui_provider, &http_state,
|
&load_data, &ui_provider, &http_state,
|
||||||
None, &Factory,
|
None, &Factory,
|
||||||
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None));
|
DEFAULT_USER_AGENT.to_owned(), &CancellationListener::new(None), None);
|
||||||
match response {
|
match response {
|
||||||
Err(LoadError { error: LoadErrorType::ContentBlocked, .. }) => {},
|
Err(LoadError { error: LoadErrorType::ContentBlocked, .. }) => {},
|
||||||
_ => panic!("request should have been blocked"),
|
_ => panic!("request should have been blocked"),
|
||||||
|
|
|
@ -8,7 +8,7 @@ use net::filemanager_thread::{FileManagerThreadFactory, TFDProvider};
|
||||||
use net::resource_thread::new_core_resource_thread;
|
use net::resource_thread::new_core_resource_thread;
|
||||||
use net_traits::hosts::{parse_hostsfile, host_replacement};
|
use net_traits::hosts::{parse_hostsfile, host_replacement};
|
||||||
use net_traits::{CoreResourceMsg, LoadData, LoadConsumer, LoadContext};
|
use net_traits::{CoreResourceMsg, LoadData, LoadConsumer, LoadContext};
|
||||||
use net_traits::{NetworkError, ProgressMsg, LoadOrigin, RequestSource};
|
use net_traits::{NetworkError, ProgressMsg, LoadOrigin};
|
||||||
use profile_traits::time::ProfilerChan;
|
use profile_traits::time::ProfilerChan;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -31,9 +31,6 @@ impl LoadOrigin for ResourceTest {
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn request_source(&self) -> RequestSource {
|
|
||||||
RequestSource::None
|
|
||||||
}
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue