aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorRahul Sharma <rsconceptx@gmail.com>2016-06-09 18:52:52 +0530
committerRahul Sharma <rsconceptx@gmail.com>2016-07-16 23:29:44 +0530
commit1e6293ea1d06120c9f3488d7d32c24d8d92df6b1 (patch)
treeffc6addc9aff4eeb5562fd1b3b588603532b38c4 /components
parente8fa02a07f3ee8965c022df4e92d5bdb0fccdb0b (diff)
downloadservo-1e6293ea1d06120c9f3488d7d32c24d8d92df6b1.tar.gz
servo-1e6293ea1d06120c9f3488d7d32c24d8d92df6b1.zip
Integrate service worker manager thread
Diffstat (limited to 'components')
-rw-r--r--components/constellation/constellation.rs105
-rw-r--r--components/constellation/pipeline.rs10
-rw-r--r--components/gfx/font_cache_thread.rs5
-rw-r--r--components/net/file_loader.rs5
-rw-r--r--components/net/http_loader.rs34
-rw-r--r--components/net/image_cache_thread.rs5
-rw-r--r--components/net/resource_thread.rs10
-rw-r--r--components/net_traits/lib.rs31
-rw-r--r--components/script/document_loader.rs7
-rw-r--r--components/script/dom/abstractworker.rs26
-rw-r--r--components/script/dom/bindings/global.rs10
-rw-r--r--components/script/dom/dedicatedworkerglobalscope.rs37
-rw-r--r--components/script/dom/serviceworker.rs81
-rw-r--r--components/script/dom/serviceworkercontainer.rs2
-rw-r--r--components/script/dom/serviceworkerglobalscope.rs230
-rw-r--r--components/script/dom/serviceworkerregistration.rs44
-rw-r--r--components/script/dom/window.rs10
-rw-r--r--components/script/dom/worker.rs26
-rw-r--r--components/script/dom/workerglobalscope.rs93
-rw-r--r--components/script/dom/xmlhttprequest.rs9
-rw-r--r--components/script/lib.rs9
-rw-r--r--components/script/script_thread.rs77
-rw-r--r--components/script/serviceworker_manager.rs123
-rw-r--r--components/script_traits/lib.rs54
-rw-r--r--components/script_traits/script_msg.rs45
-rw-r--r--components/servo/lib.rs31
26 files changed, 619 insertions, 500 deletions
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index b262684d5d9..81587cf0c1b 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -35,19 +35,20 @@ use net_traits::bluetooth_thread::BluetoothMethodMsg;
use net_traits::filemanager_thread::FileManagerThreadMsg;
use net_traits::image_cache_thread::ImageCacheThread;
use net_traits::storage_thread::StorageThreadMsg;
-use net_traits::{self, ResourceThreads, IpcSend};
+use net_traits::{self, ResourceThreads, IpcSend, CustomResponseMediator, CoreResourceMsg};
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use pipeline::{ChildProcess, InitialPipelineState, Pipeline};
use profile_traits::mem;
use profile_traits::time;
use rand::{random, Rng, SeedableRng, StdRng};
-use script_traits::webdriver_msg;
use script_traits::{AnimationState, AnimationTickType, CompositorEvent};
use script_traits::{ConstellationControlMsg, ConstellationMsg as FromCompositorMsg};
use script_traits::{DocumentState, LayoutControlMsg};
use script_traits::{IFrameLoadInfo, IFrameSandboxState, TimerEventRequest};
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::collections::{HashMap, VecDeque};
use std::io::Error as IOError;
@@ -97,6 +98,9 @@ pub struct Constellation<Message, LTF, STF> {
/// Receives messages from scripts.
script_receiver: Receiver<FromScriptMsg>,
+ /// Receive messages from resource thread
+ resource_receiver: Receiver<CustomResponseMediator>,
+
/// Receives messages from the compositor
compositor_receiver: Receiver<FromCompositorMsg>,
@@ -125,6 +129,15 @@ pub struct Constellation<Message, LTF, STF> {
/// A channel through which messages can be sent to the bluetooth thread.
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.)
pipelines: HashMap<PipelineId, Pipeline>,
@@ -410,9 +423,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
where LTF: LayoutThreadFactory<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();
+ // 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 || {
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);
@@ -423,6 +440,15 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
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 (resource_ipc_sender, resource_ipc_receiver) = ipc::channel().expect("ipc channel failure");
+ let resource_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(resource_ipc_receiver);
+
+ state.public_resource_threads.sender()
+ .send(CoreResourceMsg::NetworkMediator(resource_ipc_sender))
+ .expect("network sender sending failure");
+
+ let swmanager_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(swmanager_receiver);
+
let mut constellation: Constellation<Message, LTF, STF> = Constellation {
script_sender: ipc_script_sender,
layout_sender: ipc_layout_sender,
@@ -438,6 +464,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
private_resource_threads: state.private_resource_threads,
image_cache_thread: state.image_cache_thread,
font_cache_thread: state.font_cache_thread,
+ swmanager_chan: None,
+ swmanager_receiver: swmanager_receiver,
+ swmanager_sender: sw_mgr_clone,
+ resource_receiver: resource_receiver,
pipelines: HashMap::new(),
frames: HashMap::new(),
subpage_map: HashMap::new(),
@@ -482,7 +512,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
PipelineNamespace::install(namespace_id);
constellation.run();
});
- compositor_sender
+ (compositor_sender, swmanager_sender)
}
fn run(&mut self) {
@@ -534,6 +564,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
compositor_proxy: self.compositor_proxy.clone_compositor_proxy(),
devtools_chan: self.devtools_chan.clone(),
bluetooth_thread: self.bluetooth_thread.clone(),
+ swmanager_thread: self.swmanager_sender.clone(),
image_cache_thread: self.image_cache_thread.clone(),
font_cache_thread: self.font_cache_thread.clone(),
resource_threads: resource_threads,
@@ -607,6 +638,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
Compositor(FromCompositorMsg),
Layout(FromLayoutMsg),
Panic(PanicMsg),
+ FromSWManager(SWManagerMsg),
+ FromResource(CustomResponseMediator),
}
// Get one incoming request.
@@ -625,6 +658,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let receiver_from_compositor = &self.compositor_receiver;
let receiver_from_layout = &self.layout_receiver;
let receiver_from_panic = &self.panic_receiver;
+ let receiver_from_swmanager = &self.swmanager_receiver;
+ let receiver_from_resource = &self.resource_receiver;
select! {
msg = receiver_from_script.recv() =>
Request::Script(msg.expect("Unexpected script channel panic in constellation")),
@@ -633,7 +668,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
msg = receiver_from_layout.recv() =>
Request::Layout(msg.expect("Unexpected layout channel panic in constellation")),
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")),
+ msg = receiver_from_resource.recv() =>
+ Request::FromResource(msg.expect("Unexpected panic channel panic in constellation"))
}
};
@@ -650,6 +689,29 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
Request::Panic(message) => {
self.handle_request_from_panic(message);
},
+ Request::FromSWManager(message) => {
+ self.handle_request_from_swmanager(message);
+ }
+ Request::FromResource(message) => {
+ self.handle_request_from_resource(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);
+ }
+ }
+ }
+
+ fn handle_request_from_resource(&self, mediator: CustomResponseMediator) {
+ if let Some(ref mgr) = self.swmanager_chan {
+ let _ = mgr.send(ServiceWorkerMsg::ActivateWorker(mediator));
+ } else {
+ warn!("activation request to service worker manager failed");
}
}
@@ -923,6 +985,14 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
FromScriptMsg::GetScrollOffset(pid, lid, send) => {
self.compositor_proxy.send(ToCompositorMsg::GetScrollOffset(pid, lid, send));
}
+ FromScriptMsg::NetworkRequest(mediator) => {
+ debug!("activation request for service worker received");
+ self.handle_activate_worker(mediator);
+ }
+ FromScriptMsg::RegisterServiceWorker(scope_things, scope) => {
+ debug!("constellation got store registration scope message");
+ self.handle_register_serviceworker(scope_things, scope);
+ }
}
}
@@ -950,6 +1020,22 @@ 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_activate_worker(&self, mediator: CustomResponseMediator) {
+ if let Some(ref mgr) = self.swmanager_chan {
+ let _ = mgr.send(ServiceWorkerMsg::ActivateWorker(mediator));
+ } else {
+ warn!("activation request to service worker manager failed");
+ }
+ }
+
fn handle_exit(&mut self) {
// TODO: add a timer, which forces shutdown if threads aren't responsive.
if self.shutting_down { return; }
@@ -999,6 +1085,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
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.");
self.font_cache_thread.exit();
diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs
index c07891984ed..240ee99e4f7 100644
--- a/components/constellation/pipeline.rs
+++ b/components/constellation/pipeline.rs
@@ -25,7 +25,7 @@ use net_traits::image_cache_thread::ImageCacheThread;
use profile_traits::mem as profile_mem;
use profile_traits::time;
use script_traits::{ConstellationControlMsg, InitialScriptState, MozBrowserEvent};
-use script_traits::{LayoutControlMsg, LayoutMsg, NewLayoutInfo, ScriptMsg};
+use script_traits::{LayoutControlMsg, LayoutMsg, NewLayoutInfo, ScriptMsg, SWManagerMsg};
use script_traits::{ScriptThreadFactory, TimerEventRequest, WindowSizeData};
use std::collections::HashMap;
use std::io::Error as IOError;
@@ -99,6 +99,8 @@ pub struct InitialPipelineState {
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
/// A channel to the bluetooth thread.
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.
pub image_cache_thread: ImageCacheThread,
/// A channel to the font cache thread.
@@ -222,6 +224,7 @@ impl Pipeline {
scheduler_chan: state.scheduler_chan,
devtools_chan: script_to_devtools_chan,
bluetooth_thread: state.bluetooth_thread,
+ swmanager_thread: state.swmanager_thread,
image_cache_thread: state.image_cache_thread,
font_cache_thread: state.font_cache_thread,
resource_threads: state.resource_threads,
@@ -414,6 +417,7 @@ pub struct UnprivilegedPipelineContent {
scheduler_chan: IpcSender<TimerEventRequest>,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
+ swmanager_thread: IpcSender<SWManagerMsg>,
image_cache_thread: ImageCacheThread,
font_cache_thread: FontCacheThread,
resource_threads: ResourceThreads,
@@ -546,4 +550,8 @@ impl UnprivilegedPipelineContent {
pub fn prefs(&self) -> HashMap<String, Pref> {
self.prefs.clone()
}
+
+ pub fn swmanager_chan(&self) -> IpcSender<SWManagerMsg> {
+ self.swmanager_thread.clone()
+ }
}
diff --git a/components/gfx/font_cache_thread.rs b/components/gfx/font_cache_thread.rs
index 6e60e2b6dd2..314def3b2cf 100644
--- a/components/gfx/font_cache_thread.rs
+++ b/components/gfx/font_cache_thread.rs
@@ -6,7 +6,7 @@ use font_template::{FontTemplate, FontTemplateDescriptor};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
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_list::SANS_SERIF_FONT_FAMILY;
use platform::font_list::for_each_available_family;
@@ -211,8 +211,7 @@ impl FontCache {
url.clone(),
None,
None,
- None,
- RequestSource::None);
+ None);
let (data_sender, data_receiver) = ipc::channel().unwrap();
let data_target = AsyncResponseTarget {
sender: data_sender,
diff --git a/components/net/file_loader.rs b/components/net/file_loader.rs
index 271baca74f6..2edc9dfa15d 100644
--- a/components/net/file_loader.rs
+++ b/components/net/file_loader.rs
@@ -7,7 +7,7 @@ use mime_classifier::MimeClassifier;
use mime_guess::guess_mime_type;
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
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::{send_error, start_sending_sniffed_opt};
use std::borrow::ToOwned;
@@ -39,9 +39,6 @@ impl LoadOrigin for FileLoadOrigin {
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
None
}
- fn request_source(&self) -> RequestSource {
- RequestSource::None
- }
fn pipeline_id(&self) -> Option<PipelineId> {
None
}
diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs
index 9a028e5ce59..d8344e12502 100644
--- a/components/net/http_loader.rs
+++ b/components/net/http_loader.rs
@@ -24,7 +24,7 @@ use hyper::method::Method;
use hyper::mime::{Mime, SubLevel, TopLevel};
use hyper::net::Fresh;
use hyper::status::{StatusClass, StatusCode};
-use ipc_channel::ipc;
+use ipc_channel::ipc::{self, IpcSender};
use log;
use mime_classifier::MimeClassifier;
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::response::HttpsState;
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::ssl::error::{SslError, OpensslError};
use profile_traits::time::{ProfilerCategory, profile, ProfilerChan, TimerMetadata};
@@ -59,6 +59,7 @@ pub fn factory(user_agent: String,
http_state: HttpState,
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
profiler_chan: ProfilerChan,
+ constellation_chan: Option<IpcSender<CustomResponseMediator>>,
connector: Arc<Pool<Connector>>)
-> Box<FnBox(LoadData,
LoadConsumer,
@@ -78,6 +79,7 @@ pub fn factory(user_agent: String,
connector,
http_state,
devtools_chan,
+ constellation_chan,
cancel_listener,
user_agent)
})
@@ -131,6 +133,7 @@ fn load_for_consumer(load_data: LoadData,
connector: Arc<Pool<Connector>>,
http_state: HttpState,
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
+ constellation_chan: Option<IpcSender<CustomResponseMediator>>,
cancel_listener: CancellationListener,
user_agent: String) {
let factory = NetworkHttpRequestFactory {
@@ -140,7 +143,7 @@ fn load_for_consumer(load_data: LoadData,
let ui_provider = TFDProvider;
match load(&load_data, &ui_provider, &http_state,
devtools_chan, &factory,
- user_agent, &cancel_listener) {
+ user_agent, &cancel_listener, constellation_chan) {
Err(error) => {
match error.error {
LoadErrorType::ConnectionAborted { .. } => unreachable!(),
@@ -860,7 +863,8 @@ pub fn load<A, B>(load_data: &LoadData,
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
request_factory: &HttpRequestFactory<R=A>,
user_agent: String,
- cancel_listener: &CancellationListener)
+ cancel_listener: &CancellationListener,
+ constellation_chan: Option<IpcSender<CustomResponseMediator>>)
-> Result<StreamedResponse, LoadError> where A: HttpRequest + 'static, B: UIProvider {
let max_redirects = PREFS.get("network.http.redirection-limit").as_i64().unwrap() as u32;
let mut iters = 0;
@@ -878,17 +882,19 @@ pub fn load<A, B>(load_data: &LoadData,
}
let (msg_sender, msg_receiver) = ipc::channel().unwrap();
- match load_data.source {
- RequestSource::Window(ref sender) | RequestSource::Worker(ref sender) => {
- sender.send(msg_sender.clone()).unwrap();
- let received_msg = msg_receiver.recv().unwrap();
- if let Some(custom_response) = received_msg {
- let metadata = Metadata::default(doc_url.clone());
- let readable_response = to_readable_response(custom_response);
- return StreamedResponse::from_http_response(box readable_response, metadata);
- }
+ let response_mediator = CustomResponseMediator {
+ response_chan: msg_sender,
+ load_url: doc_url.clone()
+ };
+ if let Some(sender) = constellation_chan {
+ let _ = sender.send(response_mediator);
+ if let Ok(Some(custom_response)) = msg_receiver.try_recv() {
+ let metadata = Metadata::default(doc_url.clone());
+ let readable_response = to_readable_response(custom_response);
+ return StreamedResponse::from_http_response(box readable_response, metadata);
}
- RequestSource::None => {}
+ } else {
+ debug!("Did not receive a custom response");
}
// If the URL is a view-source scheme then the scheme data contains the
diff --git a/components/net/image_cache_thread.rs b/components/net/image_cache_thread.rs
index fd6f62ebbea..49a5a6e69f7 100644
--- a/components/net/image_cache_thread.rs
+++ b/components/net/image_cache_thread.rs
@@ -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::{ImageCacheResult, ImageOrMetadataAvailable, ImageResponse, UsePlaceholder};
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::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -313,9 +313,6 @@ impl LoadOrigin for ImageCacheOrigin {
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
None
}
- fn request_source(&self) -> RequestSource {
- RequestSource::None
- }
fn pipeline_id(&self) -> Option<PipelineId> {
None
}
diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs
index 2bf6f38e331..64f96876ea7 100644
--- a/components/net/resource_thread.rs
+++ b/components/net/resource_thread.rs
@@ -30,7 +30,7 @@ use net_traits::request::{Request, RequestInit};
use net_traits::storage_thread::StorageThreadMsg;
use net_traits::{AsyncResponseTarget, Metadata, ProgressMsg, ResponseAction, CoreResourceThread};
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 profile_traits::time::ProfilerChan;
use rustc_serialize::json;
@@ -202,7 +202,7 @@ pub fn new_core_resource_thread(user_agent: String,
}
struct ResourceChannelManager {
- resource_manager: CoreResourceManager,
+ resource_manager: CoreResourceManager
}
fn create_resource_groups() -> (ResourceGroup, ResourceGroup) {
@@ -279,6 +279,9 @@ impl ResourceChannelManager {
let mut cookie_jar = group.cookie_jar.write().unwrap();
consumer.send(cookie_jar.cookies_for_url(&url, source)).unwrap();
}
+ CoreResourceMsg::NetworkMediator(mediator_chan) => {
+ self.resource_manager.constellation_chan = Some(mediator_chan)
+ }
CoreResourceMsg::GetCookiesDataForUrl(url, consumer, source) => {
let mut cookie_jar = group.cookie_jar.write().unwrap();
let cookies = cookie_jar.cookies_data_for_url(&url, source).collect();
@@ -456,6 +459,7 @@ pub struct CoreResourceManager {
user_agent: String,
mime_classifier: Arc<MimeClassifier>,
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
+ constellation_chan: Option<IpcSender<CustomResponseMediator>>,
profiler_chan: ProfilerChan,
filemanager_chan: IpcSender<FileManagerThreadMsg>,
cancel_load_map: HashMap<ResourceId, Sender<()>>,
@@ -471,6 +475,7 @@ impl CoreResourceManager {
user_agent: user_agent,
mime_classifier: Arc::new(MimeClassifier::new()),
devtools_chan: devtools_channel,
+ constellation_chan: None,
profiler_chan: profiler_chan,
filemanager_chan: filemanager_chan,
cancel_load_map: HashMap::new(),
@@ -542,6 +547,7 @@ impl CoreResourceManager {
http_state,
self.devtools_chan.clone(),
self.profiler_chan.clone(),
+ self.constellation_chan.clone(),
resource_grp.connector.clone())
},
"data" => from_factory(data_loader::factory),
diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs
index 875bbd106aa..8e7bb996697 100644
--- a/components/net_traits/lib.rs
+++ b/components/net_traits/lib.rs
@@ -97,13 +97,10 @@ impl CustomResponse {
}
}
-pub type CustomResponseSender = IpcSender<Option<CustomResponse>>;
-
-#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
-pub enum RequestSource {
- 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)]
+pub struct CustomResponseMediator {
+ pub response_chan: IpcSender<Option<CustomResponse>>,
+ pub load_url: Url
}
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
@@ -126,9 +123,7 @@ pub struct LoadData {
pub context: LoadContext,
/// The policy and referring URL for the originator of this request
pub referrer_policy: Option<ReferrerPolicy>,
- pub referrer_url: Option<Url>,
- pub source: RequestSource,
-
+ pub referrer_url: Option<Url>
}
impl LoadData {
@@ -147,7 +142,6 @@ impl LoadData {
context: context,
referrer_policy: load_origin.referrer_policy(),
referrer_url: load_origin.referrer_url().clone(),
- source: load_origin.request_source()
}
}
}
@@ -155,7 +149,6 @@ impl LoadData {
pub trait LoadOrigin {
fn referrer_url(&self) -> Option<Url>;
fn referrer_policy(&self) -> Option<ReferrerPolicy>;
- fn request_source(&self) -> RequestSource;
fn pipeline_id(&self) -> Option<PipelineId>;
}
@@ -436,6 +429,8 @@ pub enum CoreResourceMsg {
Cancel(ResourceId),
/// Synchronization message solely for knowing the state of the ResourceChannelManager loop
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
// and exit
Exit(IpcSender<()>),
@@ -451,8 +446,7 @@ pub struct PendingAsyncLoad {
guard: PendingLoadGuard,
context: LoadContext,
referrer_policy: Option<ReferrerPolicy>,
- referrer_url: Option<Url>,
- source: RequestSource
+ referrer_url: Option<Url>
}
struct PendingLoadGuard {
@@ -480,9 +474,6 @@ impl LoadOrigin for PendingAsyncLoad {
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
self.referrer_policy.clone()
}
- fn request_source(&self) -> RequestSource {
- self.source.clone()
- }
fn pipeline_id(&self) -> Option<PipelineId> {
self.pipeline
}
@@ -494,8 +485,7 @@ impl PendingAsyncLoad {
url: Url,
pipeline: Option<PipelineId>,
referrer_policy: Option<ReferrerPolicy>,
- referrer_url: Option<Url>,
- source: RequestSource)
+ referrer_url: Option<Url>)
-> PendingAsyncLoad {
PendingAsyncLoad {
core_resource_thread: core_resource_thread,
@@ -504,8 +494,7 @@ impl PendingAsyncLoad {
guard: PendingLoadGuard { loaded: false, },
context: context,
referrer_policy: referrer_policy,
- referrer_url: referrer_url,
- source: source
+ referrer_url: referrer_url
}
}
diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs
index a68038572f2..04e266994c2 100644
--- a/components/script/document_loader.rs
+++ b/components/script/document_loader.rs
@@ -8,8 +8,7 @@
use dom::bindings::js::JS;
use dom::document::Document;
use msg::constellation_msg::PipelineId;
-use net_traits::{PendingAsyncLoad, LoadContext};
-use net_traits::{RequestSource, AsyncResponseTarget};
+use net_traits::{PendingAsyncLoad, AsyncResponseTarget, LoadContext};
use net_traits::{ResourceThreads, IpcSend};
use std::thread;
use url::Url;
@@ -130,14 +129,12 @@ impl DocumentLoader {
let context = load.to_load_context();
let url = load.url().clone();
self.add_blocking_load(load);
- let client_chan = referrer.window().custom_message_chan();
PendingAsyncLoad::new(context,
self.resource_threads.sender(),
url,
self.pipeline,
referrer.get_referrer_policy(),
- Some(referrer.url().clone()),
- RequestSource::Window(client_chan))
+ Some(referrer.url().clone()))
}
/// Create and initiate a new network request.
diff --git a/components/script/dom/abstractworker.rs b/components/script/dom/abstractworker.rs
index f9ff583a0dd..4f2f029800b 100644
--- a/components/script/dom/abstractworker.rs
+++ b/components/script/dom/abstractworker.rs
@@ -8,10 +8,7 @@ use dom::bindings::str::DOMString;
use dom::bindings::structuredclone::StructuredCloneData;
use js::jsapi::{JSRuntime, JS_RequestInterruptCallback};
use js::rust::Runtime;
-use msg::constellation_msg::{PipelineId, ReferrerPolicy};
-use net_traits::{LoadOrigin, RequestSource};
use script_runtime::CommonScriptMsg;
-use url::Url;
/// Messages used to control the worker event loops
pub enum WorkerScriptMsg {
@@ -21,29 +18,6 @@ pub enum WorkerScriptMsg {
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 addr: Trusted<T>,
}
diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs
index 22cb256bd04..5adcbb67818 100644
--- a/components/script/dom/bindings/global.rs
+++ b/components/script/dom/bindings/global.rs
@@ -20,7 +20,7 @@ use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue};
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
use msg::constellation_msg::{PipelineId, PanicMsg};
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 script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
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.
pub fn pipeline(&self) -> PipelineId {
match *self {
diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs
index 87ac897a4e4..cf5537676e0 100644
--- a/components/script/dom/dedicatedworkerglobalscope.rs
+++ b/components/script/dom/dedicatedworkerglobalscope.rs
@@ -4,7 +4,7 @@
use devtools;
use devtools_traits::DevtoolScriptControlMsg;
-use dom::abstractworker::{WorkerScriptLoadOrigin, WorkerScriptMsg, SharedRt , SimpleWorkerErrorHandler};
+use dom::abstractworker::{WorkerScriptMsg, SharedRt , SimpleWorkerErrorHandler};
use dom::abstractworkerglobalscope::{SendableWorkerScriptChan, WorkerThreadWorkerChan};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding;
@@ -21,7 +21,6 @@ use dom::bindings::structuredclone::StructuredCloneData;
use dom::messageevent::MessageEvent;
use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler};
use dom::workerglobalscope::WorkerGlobalScope;
-use dom::workerglobalscope::WorkerGlobalScopeInit;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
use js::jsapi::{HandleValue, JS_SetInterruptCallback};
@@ -29,12 +28,13 @@ use js::jsapi::{JSAutoCompartment, JSContext};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
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::ScriptThreadEventCategory::WorkerEvent;
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::sync::atomic::AtomicBool;
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
use std::sync::{Arc, Mutex};
use url::Url;
@@ -70,8 +70,7 @@ impl<'a> Drop for AutoWorkerReset<'a> {
enum MixedMessage {
FromWorker((TrustedWorkerAddress, WorkerScriptMsg)),
FromScheduler((TrustedWorkerAddress, TimerEvent)),
- FromDevtools(DevtoolScriptControlMsg),
- FromNetwork(IpcSender<Option<CustomResponse>>),
+ FromDevtools(DevtoolScriptControlMsg)
}
// https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope
@@ -102,14 +101,16 @@ impl DedicatedWorkerGlobalScope {
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
timer_event_chan: IpcSender<TimerEvent>,
- timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>)
+ timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>,
+ closing: Arc<AtomicBool>)
-> DedicatedWorkerGlobalScope {
DedicatedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope::new_inherited(init,
worker_url,
runtime,
from_devtools_receiver,
- timer_event_chan),
+ timer_event_chan,
+ Some(closing)),
id: id,
receiver: receiver,
own_sender: own_sender,
@@ -128,7 +129,8 @@ impl DedicatedWorkerGlobalScope {
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
timer_event_chan: IpcSender<TimerEvent>,
- timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>)
+ timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>,
+ closing: Arc<AtomicBool>)
-> Root<DedicatedWorkerGlobalScope> {
let cx = runtime.cx();
let scope = box DedicatedWorkerGlobalScope::new_inherited(init,
@@ -140,7 +142,8 @@ impl DedicatedWorkerGlobalScope {
own_sender,
receiver,
timer_event_chan,
- timer_event_port);
+ timer_event_port,
+ closing);
DedicatedWorkerGlobalScopeBinding::Wrap(cx, scope)
}
@@ -154,7 +157,8 @@ impl DedicatedWorkerGlobalScope {
parent_sender: Box<ScriptChan + Send>,
own_sender: Sender<(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 name = format!("WebWorker for {}", serialized_worker_url);
let panic_chan = init.panic_chan.clone();
@@ -193,7 +197,7 @@ impl DedicatedWorkerGlobalScope {
let global = DedicatedWorkerGlobalScope::new(
init, url, id, devtools_mpsc_port, runtime,
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
// registration (#6631), so we instead use a random number and cross our fingers.
let scope = global.upcast::<WorkerGlobalScope>();
@@ -254,20 +258,17 @@ impl DedicatedWorkerGlobalScope {
let worker_port = &self.receiver;
let timer_event_port = &self.timer_event_port;
let devtools_port = scope.from_devtools_receiver();
- let msg_port = scope.custom_message_port();
let sel = Select::new();
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 msg_port_handle = sel.handle(msg_port);
unsafe {
worker_handle.add();
timer_event_handle.add();
if scope.from_devtools_sender().is_some() {
devtools_handle.add();
}
- msg_port_handle.add();
}
let ret = sel.wait();
if ret == worker_handle.id() {
@@ -276,8 +277,6 @@ impl DedicatedWorkerGlobalScope {
Ok(MixedMessage::FromScheduler(try!(timer_event_port.recv())))
} else if ret == devtools_handle.id() {
Ok(MixedMessage::FromDevtools(try!(devtools_port.recv())))
- } else if ret == msg_port_handle.id() {
- Ok(MixedMessage::FromNetwork(try!(msg_port.recv())))
} else {
panic!("unexpected select result!")
}
@@ -339,10 +338,6 @@ impl DedicatedWorkerGlobalScope {
MixedMessage::FromWorker((linked_worker, msg)) => {
let _ar = AutoWorkerReset::new(self, linked_worker);
self.handle_script_event(msg);
- },
- MixedMessage::FromNetwork(network_sender) => {
- // We send None as of now
- let _ = network_sender.send(None);
}
}
}
diff --git a/components/script/dom/serviceworker.rs b/components/script/dom/serviceworker.rs
index ad303d45915..19af9b09ba4 100644
--- a/components/script/dom/serviceworker.rs
+++ b/components/script/dom/serviceworker.rs
@@ -2,8 +2,8 @@
* 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/. */
+use dom::abstractworker::WorkerScriptMsg;
use dom::abstractworker::{SimpleWorkerErrorHandler, WorkerErrorHandler};
-use dom::abstractworker::{WorkerScriptMsg, WorkerScriptLoadOrigin, SharedRt};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
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::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::{DOMString, USVString};
-use dom::client::Client;
use dom::errorevent::ErrorEvent;
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
-use dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
-use dom::workerglobalscope::prepare_workerscope_init;
-use ipc_channel::ipc;
use js::jsval::UndefinedValue;
use script_thread::Runnable;
use std::cell::Cell;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::mpsc::{Sender, channel};
-use std::sync::{Arc, Mutex};
+use std::sync::mpsc::Sender;
use url::Url;
pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>;
@@ -35,36 +29,27 @@ pub struct ServiceWorker {
eventtarget: EventTarget,
script_url: DOMRefCell<String>,
state: Cell<ServiceWorkerState>,
- closing: Arc<AtomicBool>,
#[ignore_heap_size_of = "Defined in std"]
- sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
- #[ignore_heap_size_of = "Defined in rust-mozjs"]
- runtime: Arc<Mutex<Option<SharedRt>>>,
+ sender: Option<Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>>,
skip_waiting: Cell<bool>
}
impl ServiceWorker {
- fn new_inherited(sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
- closing: Arc<AtomicBool>,
- script_url: &str,
+ fn new_inherited(script_url: &str,
skip_waiting: bool) -> ServiceWorker {
ServiceWorker {
eventtarget: EventTarget::new_inherited(),
- closing: closing,
- sender: sender,
+ sender: None,
script_url: DOMRefCell::new(String::from(script_url)),
state: Cell::new(ServiceWorkerState::Installing),
- runtime: Arc::new(Mutex::new(None)),
skip_waiting: Cell::new(skip_waiting)
}
}
pub fn new(global: GlobalRef,
- closing: Arc<AtomicBool>,
- sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
script_url: &str,
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) {
@@ -72,23 +57,19 @@ impl ServiceWorker {
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) {
self.state.set(state);
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,
filename: DOMString, lineno: u32, colno: u32) {
let worker = address.root();
- if worker.is_closing() {
- return;
- }
-
let global = worker.r().global();
rooted!(in(global.r().get_cx()) let error = UndefinedValue());
let errorevent = ErrorEvent::new(global.r(), atom!("error"),
@@ -97,42 +78,12 @@ impl ServiceWorker {
errorevent.upcast::<Event>().fire(worker.upcast());
}
- #[allow(unsafe_code)]
- pub fn init_service_worker(global: GlobalRef,
- script_url: Url,
- skip_waiting: bool) -> Root<ServiceWorker> {
- let (sender, receiver) = channel();
- let closing = Arc::new(AtomicBool::new(false));
- let worker = ServiceWorker::new(global,
- closing.clone(),
- sender.clone(),
- script_url.as_str(),
- 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
+ pub fn install_serviceworker(global: GlobalRef,
+ script_url: Url,
+ skip_waiting: bool) -> Root<ServiceWorker> {
+ ServiceWorker::new(global,
+ script_url.as_str(),
+ skip_waiting)
}
}
diff --git a/components/script/dom/serviceworkercontainer.rs b/components/script/dom/serviceworkercontainer.rs
index 744daba7b91..17fea7100be 100644
--- a/components/script/dom/serviceworkercontainer.rs
+++ b/components/script/dom/serviceworkercontainer.rs
@@ -98,7 +98,7 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer {
script_url,
scope_str.clone(),
self);
- ScriptThread::set_registration(scope, &*worker_registration);
+ ScriptThread::set_registration(scope, &*worker_registration, self.global().r().pipeline());
Ok(worker_registration)
}
}
diff --git a/components/script/dom/serviceworkerglobalscope.rs b/components/script/dom/serviceworkerglobalscope.rs
index cbe195d1b8e..4841e0ff08a 100644
--- a/components/script/dom/serviceworkerglobalscope.rs
+++ b/components/script/dom/serviceworkerglobalscope.rs
@@ -4,8 +4,7 @@
use devtools;
use devtools_traits::DevtoolScriptControlMsg;
-use dom::abstractworker::{WorkerScriptLoadOrigin, WorkerScriptMsg, SharedRt, SimpleWorkerErrorHandler};
-use dom::abstractworkerglobalscope::{SendableWorkerScriptChan, WorkerThreadWorkerChan};
+use dom::abstractworker::WorkerScriptMsg;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
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::inheritance::Castable;
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::str::DOMString;
-use dom::client::Client;
use dom::messageevent::MessageEvent;
use dom::serviceworker::TrustedServiceWorkerAddress;
use dom::workerglobalscope::WorkerGlobalScope;
-use dom::workerglobalscope::WorkerGlobalScopeInit;
-use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
+use ipc_channel::ipc::{self, IpcSender, IpcReceiver};
use ipc_channel::router::ROUTER;
use js::jsapi::{JS_SetInterruptCallback, JSAutoCompartment, JSContext};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::PipelineId;
-use net_traits::{LoadContext, load_whole_resource, CustomResponse, IpcSend};
-use rand::random;
-use script_runtime::ScriptThreadEventCategory::ServiceWorkerEvent;
-use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
-use script_traits::{TimerEvent, TimerSource};
-use std::mem::replace;
+use net_traits::{LoadContext, load_whole_resource, IpcSend};
+use script_runtime::{CommonScriptMsg, StackRootTLS, get_reports, new_rt_and_cx};
+use script_traits::{TimerEvent, WorkerGlobalScopeInit, ScopeThings, ServiceWorkerMsg};
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
-use std::sync::{Arc, Mutex};
-use std::time::Instant;
+use std::thread;
+use std::time::Duration;
use url::Url;
use util::prefs::PREFS;
use util::thread::spawn_named;
use util::thread_state;
use util::thread_state::{IN_WORKER, SCRIPT};
-/// Set the `worker` field of a related ServiceWorkerGlobalScope object to a particular
-/// 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 {
+pub enum MixedMessage {
FromServiceWorker((TrustedServiceWorkerAddress, WorkerScriptMsg)),
- FromScheduler((TrustedServiceWorkerAddress, TimerEvent)),
FromDevtools(DevtoolScriptControlMsg),
- FromNetwork(IpcSender<Option<CustomResponse>>),
+ FromTimeoutThread(()),
}
#[dom_struct]
@@ -84,14 +51,13 @@ pub struct ServiceWorkerGlobalScope {
#[ignore_heap_size_of = "Defined in std"]
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
#[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>"]
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"]
- service_worker_client: Trusted<Client>
+ swmanager_sender: IpcSender<ServiceWorkerMsg>,
+ #[ignore_heap_size_of = "Defined in std"]
+ scope_url: Url
}
impl ServiceWorkerGlobalScope {
@@ -100,26 +66,27 @@ impl ServiceWorkerGlobalScope {
id: PipelineId,
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
runtime: Runtime,
- parent_sender: Box<ScriptChan + Send>,
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
timer_event_chan: IpcSender<TimerEvent>,
- timer_event_port: Receiver<(TrustedServiceWorkerAddress, TimerEvent)>,
- client: Trusted<Client>)
+ timer_event_port: Receiver<()>,
+ swmanager_sender: IpcSender<ServiceWorkerMsg>,
+ scope_url: Url)
-> ServiceWorkerGlobalScope {
ServiceWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope::new_inherited(init,
worker_url,
runtime,
from_devtools_receiver,
- timer_event_chan),
+ timer_event_chan,
+ None),
id: id,
receiver: receiver,
- own_sender: own_sender,
timer_event_port: timer_event_port,
- parent_sender: parent_sender,
+ own_sender: own_sender,
worker: DOMRefCell::new(None),
- service_worker_client: client
+ swmanager_sender: swmanager_sender,
+ scope_url: scope_url
}
}
@@ -128,12 +95,12 @@ impl ServiceWorkerGlobalScope {
id: PipelineId,
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
runtime: Runtime,
- parent_sender: Box<ScriptChan + Send>,
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
timer_event_chan: IpcSender<TimerEvent>,
- timer_event_port: Receiver<(TrustedServiceWorkerAddress, TimerEvent)>,
- client: Trusted<Client>)
+ timer_event_port: Receiver<()>,
+ swmanager_sender: IpcSender<ServiceWorkerMsg>,
+ scope_url: Url)
-> Root<ServiceWorkerGlobalScope> {
let cx = runtime.cx();
let scope = box ServiceWorkerGlobalScope::new_inherited(init,
@@ -141,42 +108,39 @@ impl ServiceWorkerGlobalScope {
id,
from_devtools_receiver,
runtime,
- parent_sender,
own_sender,
receiver,
timer_event_chan,
timer_event_port,
- client);
+ swmanager_sender,
+ scope_url);
ServiceWorkerGlobalScopeBinding::Wrap(cx, scope)
}
#[allow(unsafe_code)]
- pub fn run_serviceworker_scope(init: WorkerGlobalScopeInit,
- worker_url: Url,
- id: PipelineId,
- from_devtools_receiver: IpcReceiver<DevtoolScriptControlMsg>,
- main_thread_rt: Arc<Mutex<Option<SharedRt>>>,
- worker: TrustedServiceWorkerAddress,
- parent_sender: Box<ScriptChan + Send>,
+ pub fn run_serviceworker_scope(scope_things: ScopeThings,
own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
- client: Trusted<Client>,
- worker_load_origin: WorkerScriptLoadOrigin) {
- let serialized_worker_url = worker_url.to_string();
+ devtools_receiver: IpcReceiver<DevtoolScriptControlMsg>,
+ swmanager_sender: IpcSender<ServiceWorkerMsg>,
+ 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 || {
thread_state::initialize(SCRIPT | IN_WORKER);
-
let roots = RootCollection::new();
let _stack_roots_tls = StackRootTLS::new(&roots);
-
let (url, source) = match load_whole_resource(LoadContext::Script,
&init.resource_threads.sender(),
- worker_url,
+ script_url,
&worker_load_origin) {
Err(_) => {
println!("error loading script {}", serialized_worker_url);
- parent_sender.send(CommonScriptMsg::RunnableMsg(ServiceWorkerEvent,
- box SimpleWorkerErrorHandler::new(worker))).unwrap();
return;
}
Ok((metadata, bytes)) => {
@@ -185,25 +149,18 @@ impl ServiceWorkerGlobalScope {
};
let runtime = unsafe { new_rt_and_cx() };
- *main_thread_rt.lock().unwrap() = Some(SharedRt::new(&runtime));
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();
- let (timer_ipc_chan, timer_ipc_port) = ipc::channel().unwrap();
- let worker_for_route = worker.clone();
- 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();
- });
+ // 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_chan, timer_port) = channel();
let global = ServiceWorkerGlobalScope::new(
- init, url, id, devtools_mpsc_port, runtime,
- parent_sender.clone(), own_sender, receiver,
- timer_ipc_chan, timer_rx, client);
- // 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.
+ init, url, pipeline_id, devtools_mpsc_port, runtime,
+ own_sender, receiver,
+ timer_ipc_chan, timer_port, swmanager_sender, scope_url);
let scope = global.upcast::<WorkerGlobalScope>();
unsafe {
@@ -211,35 +168,25 @@ impl ServiceWorkerGlobalScope {
JS_SetInterruptCallback(scope.runtime(), Some(interrupt_callback));
}
- if scope.is_closing() {
- return;
- }
+ scope.execute_script(DOMString::from(source));
- {
- let _ar = AutoWorkerReset::new(global.r(), worker);
- 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
- let sw_lifetime = Instant::now();
+ // Service workers are time limited
+ spawn_named("SWTimeoutThread".to_owned(), move || {
let sw_lifetime_timeout = PREFS.get("dom.serviceworker.timeout_seconds").as_u64().unwrap();
- while let Ok(event) = global.receive_event() {
- if scope.is_closing() {
- break;
- }
- global.handle_event(event);
- if sw_lifetime.elapsed().as_secs() == sw_lifetime_timeout {
- break;
- }
+ 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() {
+ if !global.handle_event(event) {
+ break;
}
- }, reporter_name, parent_sender, CommonScriptMsg::CollectReports);
+ }
});
}
- fn handle_event(&self, event: MixedMessage) {
+ fn handle_event(&self, event: MixedMessage) -> bool {
match event {
MixedMessage::FromDevtools(msg) => {
let global_ref = GlobalRef::Worker(self.upcast());
@@ -252,26 +199,15 @@ impl ServiceWorkerGlobalScope {
devtools::handle_wants_live_notifications(&global_ref, bool_val),
_ => debug!("got an unusable devtools control message inside the worker!"),
}
- },
- 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.")
- }
- }
+ true
}
- MixedMessage::FromServiceWorker((linked_worker, msg)) => {
- let _ar = AutoWorkerReset::new(self, linked_worker);
+ MixedMessage::FromServiceWorker((_, msg)) => {
self.handle_script_event(msg);
- },
- MixedMessage::FromNetwork(network_sender) => {
- // We send None as of now
- let _ = network_sender.send(None);
+ true
+ }
+ MixedMessage::FromTimeoutThread(_) => {
+ 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> {
let scope = self.upcast::<WorkerGlobalScope>();
let worker_port = &self.receiver;
- let timer_event_port = &self.timer_event_port;
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 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 msg_port_handle = sel.handle(msg_port);
+ let mut timer_port_handle = sel.handle(timer_event_port);
unsafe {
worker_handle.add();
- timer_event_handle.add();
if scope.from_devtools_sender().is_some() {
devtools_handle.add();
}
- msg_port_handle.add();
+ timer_port_handle.add();
}
+
let ret = sel.wait();
if ret == worker_handle.id() {
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())))
- } else if ret == msg_port_handle.id() {
- Ok(MixedMessage::FromNetwork(try!(msg_port.recv())))
+ } else if ret == timer_port_handle.id() {
+ Ok(MixedMessage::FromTimeoutThread(try!(timer_event_port.recv())))
} else {
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 {
self.id
}
@@ -352,15 +277,6 @@ impl ServiceWorkerGlobalScope {
pub fn process_event(&self, msg: CommonScriptMsg) {
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)]
diff --git a/components/script/dom/serviceworkerregistration.rs b/components/script/dom/serviceworkerregistration.rs
index 358331afffc..e20b7e06c47 100644
--- a/components/script/dom/serviceworkerregistration.rs
+++ b/components/script/dom/serviceworkerregistration.rs
@@ -11,6 +11,8 @@ use dom::bindings::str::USVString;
use dom::eventtarget::EventTarget;
use dom::serviceworker::ServiceWorker;
use dom::serviceworkercontainer::Controllable;
+use dom::workerglobalscope::prepare_workerscope_init;
+use script_traits::{WorkerScriptLoadOrigin, ScopeThings};
use url::Url;
#[dom_struct]
@@ -19,7 +21,7 @@ pub struct ServiceWorkerRegistration {
active: Option<JS<ServiceWorker>>,
installing: Option<JS<ServiceWorker>>,
waiting: Option<JS<ServiceWorker>>,
- scope: String,
+ scope: String
}
impl ServiceWorkerRegistration {
@@ -29,7 +31,7 @@ impl ServiceWorkerRegistration {
active: Some(JS::from_ref(active_sw)),
installing: None,
waiting: None,
- scope: scope
+ scope: scope,
}
}
#[allow(unrooted_must_root)]
@@ -37,11 +39,47 @@ impl ServiceWorkerRegistration {
script_url: Url,
scope: String,
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);
container.set_controller(&*active_worker.clone());
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 {
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 30ab695f9b7..991e8fbfadc 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -44,10 +44,10 @@ use js::rust::CompileOptionsWrapper;
use js::rust::Runtime;
use libc;
use msg::constellation_msg::{FrameType, LoadData, PanicMsg, PipelineId, SubpageId, WindowSizeType};
+use net_traits::ResourceThreads;
use net_traits::bluetooth_thread::BluetoothMethodMsg;
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
use net_traits::storage_thread::StorageType;
-use net_traits::{ResourceThreads, CustomResponseSender};
use num_traits::ToPrimitive;
use open;
use profile_traits::mem;
@@ -155,8 +155,6 @@ pub struct Window {
image_cache_thread: ImageCacheThread,
#[ignore_heap_size_of = "channels are hard"]
image_cache_chan: ImageCacheChan,
- #[ignore_heap_size_of = "channels are hard"]
- custom_message_chan: IpcSender<CustomResponseSender>,
browsing_context: MutNullableHeap<JS<BrowsingContext>>,
performance: MutNullableHeap<JS<Performance>>,
navigation_start: u64,
@@ -314,10 +312,6 @@ impl Window {
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 {
let worker_id = self.next_worker_id.get();
let WorkerId(id_num) = worker_id;
@@ -1605,7 +1599,6 @@ impl Window {
history_task_source: HistoryTraversalTaskSource,
file_task_source: FileReadingTaskSource,
image_cache_chan: ImageCacheChan,
- custom_message_chan: IpcSender<CustomResponseSender>,
image_cache_thread: ImageCacheThread,
resource_threads: ResourceThreads,
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
@@ -1641,7 +1634,6 @@ impl Window {
history_traversal_task_source: history_task_source,
file_reading_task_source: file_task_source,
image_cache_chan: image_cache_chan,
- custom_message_chan: custom_message_chan,
console: Default::default(),
crypto: Default::default(),
navigator: Default::default(),
diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs
index 2cf1d1c4e46..c318672fb7a 100644
--- a/components/script/dom/worker.rs
+++ b/components/script/dom/worker.rs
@@ -2,9 +2,9 @@
* 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/. */
-
+use devtools_traits::{ScriptToDevtoolsControlMsg, DevtoolsPageInfo};
+use dom::abstractworker::WorkerScriptMsg;
use dom::abstractworker::{SimpleWorkerErrorHandler, SharedRt, WorkerErrorHandler};
-use dom::abstractworker::{WorkerScriptLoadOrigin, WorkerScriptMsg};
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::WorkerBinding;
use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods;
@@ -26,6 +26,7 @@ use ipc_channel::ipc;
use js::jsapi::{HandleValue, JSContext, JSAutoCompartment};
use js::jsval::UndefinedValue;
use script_thread::Runnable;
+use script_traits::WorkerScriptLoadOrigin;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{Sender, channel};
use std::sync::{Arc, Mutex};
@@ -81,21 +82,28 @@ impl Worker {
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 worker_id = global.get_next_worker_id();
+ if let Some(ref chan) = global.devtools_chan() {
+ let pipeline_id = global.pipeline();
+ 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(),
+ page_info));
+ }
- let init = prepare_workerscope_init(global,
- "Worker".to_owned(),
- worker_url.clone(),
- devtools_sender.clone(),
- closing);
+ let init = prepare_workerscope_init(global, Some(devtools_sender));
DedicatedWorkerGlobalScope::run_worker_scope(
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)
}
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index 67b7a54951d..cd8476b49d6 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at 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::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
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::workerlocation::WorkerLocation;
use dom::workernavigator::WorkerNavigator;
-use ipc_channel::ipc::{self, IpcSender};
-use ipc_channel::router::ROUTER;
+use ipc_channel::ipc::IpcSender;
use js::jsapi::{HandleValue, JSContext, JSRuntime};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::{PipelineId, ReferrerPolicy, PanicMsg};
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 script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, maybe_take_panic_result};
use script_thread::RunnableWrapper;
use script_traits::ScriptMsg as ConstellationMsg;
+use script_traits::WorkerGlobalScopeInit;
use script_traits::{MsDuration, TimerEvent, TimerEventId, TimerEventRequest, TimerSource};
use std::cell::Cell;
use std::default::Default;
@@ -48,52 +48,19 @@ pub enum WorkerGlobalScopeTypeId {
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,
- worker_type: String,
- worker_url: Url,
- devtools_sender: IpcSender<DevtoolScriptControlMsg>,
- closing: Arc<AtomicBool>) -> WorkerGlobalScopeInit {
+ devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>) -> WorkerGlobalScopeInit {
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 {
resource_threads: global.resource_threads(),
mem_profiler_chan: global.mem_profiler_chan().clone(),
to_devtools_sender: global.devtools_chan(),
time_profiler_chan: global.time_profiler_chan().clone(),
- from_devtools_sender: optional_sender,
+ from_devtools_sender: devtools_sender,
constellation_chan: global.constellation_chan().clone(),
panic_chan: global.panic_chan().clone(),
scheduler_chan: global.scheduler_chan().clone(),
- worker_id: worker_id,
- closing: closing,
+ worker_id: worker_id
};
init
@@ -105,7 +72,7 @@ pub struct WorkerGlobalScope {
eventtarget: EventTarget,
worker_id: WorkerId,
worker_url: Url,
- closing: Arc<AtomicBool>,
+ closing: Option<Arc<AtomicBool>>,
#[ignore_heap_size_of = "Defined in js"]
runtime: Runtime,
next_worker_id: Cell<WorkerId>,
@@ -146,12 +113,6 @@ pub struct WorkerGlobalScope {
#[ignore_heap_size_of = "Defined in ipc-channel"]
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 {
@@ -159,16 +120,15 @@ impl WorkerGlobalScope {
worker_url: Url,
runtime: Runtime,
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
- timer_event_chan: IpcSender<TimerEvent>)
+ timer_event_chan: IpcSender<TimerEvent>,
+ closing: Option<Arc<AtomicBool>>)
-> WorkerGlobalScope {
- let (msg_chan, msg_port) = ipc::channel().unwrap();
- let custom_msg_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(msg_port);
WorkerGlobalScope {
eventtarget: EventTarget::new_inherited(),
next_worker_id: Cell::new(WorkerId(0)),
worker_id: init.worker_id,
worker_url: worker_url,
- closing: init.closing,
+ closing: closing,
runtime: runtime,
resource_threads: init.resource_threads,
location: Default::default(),
@@ -185,8 +145,6 @@ impl WorkerGlobalScope {
constellation_chan: init.constellation_chan,
scheduler_chan: init.scheduler_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()
}
- 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 {
- self.closing.load(Ordering::SeqCst)
+ if let Some(ref closing) = self.closing {
+ closing.load(Ordering::SeqCst)
+ } else {
+ false
+ }
}
pub fn resource_threads(&self) -> &ResourceThreads {
@@ -273,7 +227,7 @@ impl WorkerGlobalScope {
pub fn get_runnable_wrapper(&self) -> 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> {
None
}
- fn request_source(&self) -> RequestSource {
- RequestSource::None
- }
fn pipeline_id(&self) -> Option<PipelineId> {
Some(self.pipeline())
}
@@ -451,13 +402,10 @@ impl WorkerGlobalScope {
pub fn script_chan(&self) -> Box<ScriptChan + Send> {
let dedicated =
self.downcast::<DedicatedWorkerGlobalScope>();
- let service_worker = self.downcast::<ServiceWorkerGlobalScope>();
if let Some(dedicated) = dedicated {
return dedicated.script_chan();
- } else if let Some(service_worker) = service_worker {
- return service_worker.script_chan();
} 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>) {
let dedicated = self.downcast::<DedicatedWorkerGlobalScope>();
- let service_worker = self.downcast::<ServiceWorkerGlobalScope>();
if let Some(dedicated) = dedicated {
return dedicated.new_script_pair();
- } else if let Some(service_worker) = service_worker {
- return service_worker.new_script_pair();
} else {
- panic!("need to implement a sender for SharedWorker")
+ panic!("need to implement a sender for SharedWorker/ServiceWorker")
}
}
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index ed254f8c007..9ac02936673 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -47,7 +47,7 @@ use net_traits::CoreResourceMsg::Fetch;
use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode};
use net_traits::trim_http_whitespace;
use net_traits::{CoreResourceThread, LoadOrigin};
-use net_traits::{FetchResponseListener, Metadata, NetworkError, RequestSource};
+use net_traits::{FetchResponseListener, Metadata, NetworkError};
use network_listener::{NetworkListener, PreInvoke};
use parse::html::{ParseContext, parse_html};
use parse::xml::{self, parse_xml};
@@ -274,13 +274,6 @@ impl LoadOrigin for XMLHttpRequest {
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
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> {
let global = self.global();
Some(global.r().pipeline())
diff --git a/components/script/lib.rs b/components/script/lib.rs
index 2744115aff1..604e3770176 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -106,6 +106,7 @@ pub mod parse;
pub mod script_runtime;
#[allow(unsafe_code)]
pub mod script_thread;
+mod serviceworker_manager;
mod task_source;
pub mod textinput;
mod timers;
@@ -113,7 +114,10 @@ mod unpremultiplytable;
mod webdriver_handlers;
use dom::bindings::codegen::RegisterBindings;
+use ipc_channel::ipc::IpcSender;
use js::jsapi::{Handle, JSContext, JSObject, SetDOMProxyInformation};
+use script_traits::SWManagerMsg;
+use serviceworker_manager::ServiceWorkerManager;
use std::ptr;
use util::opts;
@@ -159,11 +163,14 @@ fn perform_platform_specific_initialization() {
fn perform_platform_specific_initialization() {}
#[allow(unsafe_code)]
-pub fn init() {
+pub fn init(from_swmanager_sender: IpcSender<SWManagerMsg>) {
unsafe {
SetDOMProxyInformation(ptr::null(), 0, Some(script_thread::shadow_check_callback));
}
+ // Spawn the service worker manager passing the constellation sender
+ ServiceWorkerManager::spawn_manager(from_swmanager_sender);
+
// Create the global vtables used by the (generated) DOM
// bindings to implement JS proxies.
RegisterBindings::RegisterProxyHandlers();
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 07779fbebd2..57bd85ec1ec 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -65,12 +65,11 @@ use js::jsval::UndefinedValue;
use js::rust::Runtime;
use mem::heap_size_of_self_and_children;
use msg::constellation_msg::{FrameType, LoadData, PanicMsg, PipelineId, PipelineNamespace};
-use msg::constellation_msg::{ReferrerPolicy, SubpageId, WindowSizeType};
-use net_traits::LoadData as NetLoadData;
+use msg::constellation_msg::{SubpageId, WindowSizeType, ReferrerPolicy};
use net_traits::bluetooth_thread::BluetoothMethodMsg;
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadContext, Metadata, ResourceThreads};
-use net_traits::{RequestSource, CustomResponse, CustomResponseSender, IpcSend};
+use net_traits::{IpcSend, LoadData as NetLoadData};
use network_listener::NetworkListener;
use parse::ParserRoot;
use parse::html::{ParseContext, parse_html};
@@ -216,8 +215,7 @@ enum MixedMessage {
FromScript(MainThreadScriptMsg),
FromDevtools(DevtoolScriptControlMsg),
FromImageCache(ImageCacheResult),
- FromScheduler(TimerEvent),
- FromNetwork(IpcSender<Option<CustomResponse>>),
+ FromScheduler(TimerEvent)
}
/// Messages used to control the script event loop
@@ -342,12 +340,6 @@ pub struct ScriptThread {
/// events in the event queue.
chan: MainThreadScriptChan,
- /// A handle to network event messages
- custom_message_chan: IpcSender<CustomResponseSender>,
-
- /// The port which receives a sender from the network
- custom_message_port: Receiver<CustomResponseSender>,
-
dom_manipulation_task_source: DOMManipulationTaskSource,
user_interaction_task_source: UserInteractionTaskSource,
@@ -509,10 +501,10 @@ impl ScriptThread {
}
// stores a service worker registration
- pub fn set_registration(scope_url: Url, registration:&ServiceWorkerRegistration) {
+ pub fn set_registration(scope_url: Url, registration:&ServiceWorkerRegistration, pipeline_id: PipelineId) {
SCRIPT_THREAD_ROOT.with(|root| {
let script_thread = unsafe { &*root.get().unwrap() };
- script_thread.handle_serviceworker_registration(scope_url, registration);
+ script_thread.handle_serviceworker_registration(scope_url, registration, pipeline_id);
});
}
@@ -562,9 +554,6 @@ impl ScriptThread {
let (ipc_devtools_sender, ipc_devtools_receiver) = ipc::channel().unwrap();
let devtools_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_devtools_receiver);
- let (ipc_custom_resp_chan, ipc_custom_resp_port) = ipc::channel().unwrap();
- let custom_msg_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_custom_resp_port);
-
// Ask the router to proxy IPC messages from the image cache thread to us.
let (ipc_image_cache_channel, ipc_image_cache_port) = ipc::channel().unwrap();
let image_cache_port =
@@ -590,8 +579,6 @@ impl ScriptThread {
bluetooth_thread: state.bluetooth_thread,
port: port,
- custom_message_chan: ipc_custom_resp_chan,
- custom_message_port: custom_msg_port,
chan: MainThreadScriptChan(chan.clone()),
dom_manipulation_task_source: DOMManipulationTaskSource(chan.clone()),
@@ -653,7 +640,7 @@ impl ScriptThread {
/// Handle incoming control messages.
fn handle_msgs(&self) -> bool {
use self::MixedMessage::{FromConstellation, FromDevtools, FromImageCache};
- use self::MixedMessage::{FromScheduler, FromScript, FromNetwork};
+ use self::MixedMessage::{FromScheduler, FromScript};
// Handle pending resize events.
// Gather them first to avoid a double mut borrow on self.
@@ -687,7 +674,6 @@ impl ScriptThread {
let mut timer_event_port = sel.handle(&self.timer_event_port);
let mut devtools_port = sel.handle(&self.devtools_port);
let mut image_cache_port = sel.handle(&self.image_cache_port);
- let mut custom_message_port = sel.handle(&self.custom_message_port);
unsafe {
script_port.add();
control_port.add();
@@ -696,7 +682,6 @@ impl ScriptThread {
devtools_port.add();
}
image_cache_port.add();
- custom_message_port.add();
}
let ret = sel.wait();
if ret == script_port.id() {
@@ -709,8 +694,6 @@ impl ScriptThread {
FromDevtools(self.devtools_port.recv().unwrap())
} else if ret == image_cache_port.id() {
FromImageCache(self.image_cache_port.recv().unwrap())
- } else if ret == custom_message_port.id() {
- FromNetwork(self.custom_message_port.recv().unwrap())
} else {
panic!("unexpected select result")
}
@@ -778,10 +761,7 @@ impl ScriptThread {
Err(_) => match self.timer_event_port.try_recv() {
Err(_) => match self.devtools_port.try_recv() {
Err(_) => match self.image_cache_port.try_recv() {
- Err(_) => match self.custom_message_port.try_recv() {
- Err(_) => break,
- Ok(ev) => event = FromNetwork(ev)
- },
+ Err(_) => break,
Ok(ev) => event = FromImageCache(ev),
},
Ok(ev) => event = FromDevtools(ev),
@@ -807,7 +787,6 @@ impl ScriptThread {
},
FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg),
FromScript(inner_msg) => self.handle_msg_from_script(inner_msg),
- FromNetwork(inner_msg) => self.handle_msg_from_network(inner_msg),
FromScheduler(inner_msg) => self.handle_timer_event(inner_msg),
FromDevtools(inner_msg) => self.handle_msg_from_devtools(inner_msg),
FromImageCache(inner_msg) => self.handle_msg_from_image_cache(inner_msg),
@@ -866,8 +845,7 @@ impl ScriptThread {
_ => ScriptThreadEventCategory::ScriptEvent
}
},
- MixedMessage::FromScheduler(_) => ScriptThreadEventCategory::TimerEvent,
- MixedMessage::FromNetwork(_) => ScriptThreadEventCategory::NetworkEvent
+ MixedMessage::FromScheduler(_) => ScriptThreadEventCategory::TimerEvent
}
}
@@ -1056,12 +1034,6 @@ impl ScriptThread {
msg.responder.unwrap().respond(msg.image_response);
}
- fn handle_msg_from_network(&self, msg: IpcSender<Option<CustomResponse>>) {
- // We may detect controlling service workers here
- // We send None as default
- let _ = msg.send(None);
- }
-
fn handle_webdriver_msg(&self, pipeline_id: PipelineId, msg: WebDriverScriptCommand) {
let context = self.root_browsing_context();
match msg {
@@ -1457,8 +1429,33 @@ impl ScriptThread {
}
}
- fn handle_serviceworker_registration(&self, scope: Url, registration: &ServiceWorkerRegistration) {
- self.registration_map.borrow_mut().insert(scope, JS::from_ref(registration));
+ fn handle_serviceworker_registration(&self,
+ scope: Url,
+ registration: &ServiceWorkerRegistration,
+ pipeline_id: PipelineId) {
+ {
+ let ref mut reg_ref = *self.registration_map.borrow_mut();
+ // according to spec we should replace if an older registration exists for
+ // same scope otherwise just insert the new one
+ let _ = reg_ref.remove(&scope);
+ reg_ref.insert(scope.clone(), JS::from_ref(registration));
+ }
+
+ // send ScopeThings to sw-manager
+ let ref maybe_registration_ref = *self.registration_map.borrow();
+ let maybe_registration = match maybe_registration_ref.get(&scope) {
+ Some(r) => r,
+ None => return
+ };
+ if let Some(context) = self.root_browsing_context().find(pipeline_id) {
+ let window = context.active_window();
+ let global_ref = GlobalRef::Window(window.r());
+ let script_url = maybe_registration.get_installed().get_script_url();
+ let scope_things = ServiceWorkerRegistration::create_scope_things(global_ref, script_url);
+ let _ = self.constellation_chan.send(ConstellationMsg::RegisterServiceWorker(scope_things, scope));
+ } else {
+ warn!("Registration failed for {}", pipeline_id);
+ }
}
/// Handles a request for the window title.
@@ -1601,7 +1598,6 @@ impl ScriptThread {
HistoryTraversalTaskSource(history_sender.clone()),
self.file_reading_task_source.clone(),
self.image_cache_channel.clone(),
- self.custom_message_chan.clone(),
self.image_cache_thread.clone(),
self.resource_threads.clone(),
self.bluetooth_thread.clone(),
@@ -2112,8 +2108,7 @@ impl ScriptThread {
pipeline_id: Some(id),
credentials_flag: true,
referrer_policy: load_data.referrer_policy,
- referrer_url: load_data.referrer_url,
- source: RequestSource::Window(self.custom_message_chan.clone())
+ referrer_url: load_data.referrer_url
}, LoadConsumer::Listener(response_target), None)).unwrap();
self.incomplete_loads.borrow_mut().push(incomplete);
diff --git a/components/script/serviceworker_manager.rs b/components/script/serviceworker_manager.rs
new file mode 100644
index 00000000000..d394a9908ee
--- /dev/null
+++ b/components/script/serviceworker_manager.rs
@@ -0,0 +1,123 @@
+/* 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, IpcReceiver};
+use script_traits::{ServiceWorkerMsg, ScopeThings, SWManagerMsg};
+use std::collections::HashMap;
+use std::sync::mpsc::channel;
+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: IpcReceiver<ServiceWorkerMsg>,
+}
+
+impl ServiceWorkerManager {
+ fn new(own_sender: IpcSender<ServiceWorkerMsg>,
+ from_constellation_receiver: IpcReceiver<ServiceWorkerMsg>) -> ServiceWorkerManager {
+ ServiceWorkerManager {
+ registered_workers: HashMap::new(),
+ active_workers: HashMap::new(),
+ own_sender: own_sender,
+ own_port: from_constellation_receiver
+ }
+ }
+
+ pub fn spawn_manager(from_swmanager_sender: IpcSender<SWManagerMsg>) {
+ let (own_sender, from_constellation_receiver) = ipc::channel().unwrap();
+ from_swmanager_sender.send(SWManagerMsg::OwnSender(own_sender.clone())).unwrap();
+ spawn_named("ServiceWorkerManager".to_owned(), move || {
+ ServiceWorkerManager::new(own_sender, from_constellation_receiver).start();
+ });
+ }
+
+ 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());
+ // store the worker in active_workers map
+ self.active_workers.insert(scope_url.clone(), scope_things.clone());
+ } else {
+ warn!("Unable to activate service worker");
+ }
+ }
+ }
+
+ fn start(&mut self) {
+ while let Ok(msg) = self.own_port.recv() {
+ 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);
+ }
+ }
+ ServiceWorkerMsg::Timeout(scope) => {
+ if self.active_workers.contains_key(&scope) {
+ let _ = self.active_workers.remove(&scope);
+ } else {
+ warn!("ScopeThings for {:?} is not active", scope);
+ }
+ }
+ ServiceWorkerMsg::ActivateWorker(mediator) => {
+ self.prepare_activation(&mediator.load_url);
+ // TODO XXXcreativcoder this net_sender 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);
+
+ }
+ ServiceWorkerMsg::Exit => break
+ }
+ }
+ }
+}
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 967303e63b8..af3844f84ba 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -36,7 +36,7 @@ mod script_msg;
pub mod webdriver_msg;
use app_units::Au;
-use devtools_traits::ScriptToDevtoolsControlMsg;
+use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
use euclid::Size2D;
use euclid::length::Length;
use euclid::point::Point2D;
@@ -51,13 +51,14 @@ use ipc_channel::ipc::{IpcReceiver, IpcSender};
use layers::geometry::DevicePixel;
use libc::c_void;
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 net_traits::ResourceThreads;
use net_traits::bluetooth_thread::BluetoothMethodMsg;
use net_traits::image_cache_thread::ImageCacheThread;
use net_traits::response::HttpsState;
+use net_traits::{LoadOrigin, ResourceThreads};
use profile_traits::mem;
+use profile_traits::time as profile_time;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::HashMap;
use std::sync::mpsc::{Sender, Receiver};
@@ -67,6 +68,7 @@ use util::ipc::OptionalOpaqueIpcSender;
use webdriver_msg::{LoadStatus, WebDriverScriptCommand};
pub use script_msg::{LayoutMsg, ScriptMsg, EventResult, LogEntry};
+pub use script_msg::{ServiceWorkerMsg, ScopeThings, SWManagerMsg};
/// 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.
@@ -603,3 +605,49 @@ pub enum ConstellationMsg {
/// A log entry, with the pipeline id and thread name
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()
+ }
+}
diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs
index e510a74a9c1..959050ee2ea 100644
--- a/components/script_traits/script_msg.rs
+++ b/components/script_traits/script_msg.rs
@@ -8,13 +8,17 @@ use IFrameLoadInfo;
use MouseButton;
use MouseEventType;
use MozBrowserEvent;
+use WorkerGlobalScopeInit;
+use WorkerScriptLoadOrigin;
use canvas_traits::CanvasMsg;
+use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
use euclid::point::Point2D;
use euclid::size::Size2D;
use gfx_traits::LayerId;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
use msg::constellation_msg::{NavigationDirection, PipelineId, SubpageId};
+use net_traits::CustomResponseMediator;
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use style_traits::cursor::Cursor;
use style_traits::viewport::ViewportConstraints;
@@ -106,6 +110,8 @@ pub enum ScriptMsg {
ActivateDocument(PipelineId),
/// Set the document state for a pipeline (used by screenshot / reftests)
SetDocumentState(PipelineId, DocumentState),
+ /// Message from network to constellation
+ NetworkRequest(CustomResponseMediator),
/// Update the pipeline Url, which can change after redirections.
SetFinalUrl(PipelineId, Url),
/// Check if an alert dialog box should be presented
@@ -131,6 +137,45 @@ pub enum ScriptMsg {
LogEntry(Option<PipelineId>, Option<String>, LogEntry),
/// Notifies the constellation that this pipeline has exited.
PipelineExited(PipelineId),
+ /// Store the data required to activate a service worker for the given scope
+ RegisterServiceWorker(ScopeThings, Url),
/// 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,
+}
+
+/// Messages sent to Service Worker Manager thread
+#[derive(Deserialize, Serialize)]
+pub enum ServiceWorkerMsg {
+ /// Message to register the service worker
+ RegisterServiceWorker(ScopeThings, Url),
+ /// Message to activate the worker
+ ActivateWorker(CustomResponseMediator),
+ /// Timeout message sent by active service workers
+ Timeout(Url),
+ /// Exit the service worker manager
Exit,
}
+
+/// Messages outgoing from the Service Worker Manager thread
+#[derive(Deserialize, Serialize)]
+pub enum SWManagerMsg {
+ /// Provide the constellation with a means of communicating with the Service Worker Manager
+ OwnSender(IpcSender<ServiceWorkerMsg>),
+}
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index 20aee632c1d..0b8f5756a36 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -83,7 +83,7 @@ use profile::mem as profile_mem;
use profile::time as profile_time;
use profile_traits::mem;
use profile_traits::time;
-use script_traits::{ConstellationMsg, ScriptMsg};
+use script_traits::{ConstellationMsg, ScriptMsg, SWManagerMsg};
use std::cmp::max;
use std::rc::Rc;
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.
let opts = opts::get();
- script::init();
// Get both endpoints of a special channel for communication between
// the client window and the compositor. This channel is unique because
@@ -160,13 +159,16 @@ impl<Window> Browser<Window> where Window: WindowMethods + 'static {
// Create the constellation, which maintains the engine
// pipelines, including the script and layout threads, as well
// as the navigation context.
- let constellation_chan = create_constellation(opts.clone(),
- compositor_proxy.clone_compositor_proxy(),
- time_profiler_chan.clone(),
- mem_profiler_chan.clone(),
- devtools_chan,
- supports_clipboard,
- webrender_api_sender.clone());
+ let (constellation_chan, swmanager_sender) = create_constellation(opts.clone(),
+ compositor_proxy.clone_compositor_proxy(),
+ time_profiler_chan.clone(),
+ mem_profiler_chan.clone(),
+ devtools_chan,
+ supports_clipboard,
+ webrender_api_sender.clone());
+
+ // Send the constellation's swmanager sender to service worker manager thread
+ script::init(swmanager_sender);
if cfg!(feature = "webdriver") {
if let Some(port) = opts.webdriver_port {
@@ -227,7 +229,8 @@ fn create_constellation(opts: opts::Opts,
mem_profiler_chan: mem::ProfilerChan,
devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
supports_clipboard: bool,
- webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Sender<ConstellationMsg> {
+ webrender_api_sender: Option<webrender_traits::RenderApiSender>)
+ -> (Sender<ConstellationMsg>, IpcSender<SWManagerMsg>) {
let bluetooth_thread: IpcSender<BluetoothMethodMsg> = BluetoothThreadFactory::new();
let (public_resource_threads, private_resource_threads) =
@@ -252,7 +255,7 @@ fn create_constellation(opts: opts::Opts,
supports_clipboard: supports_clipboard,
webrender_api_sender: webrender_api_sender,
};
- let constellation_chan =
+ let (constellation_chan, from_swmanager_sender) =
Constellation::<script_layout_interface::message::Msg,
layout_thread::LayoutThread,
script::script_thread::ScriptThread>::start(initial_state);
@@ -261,7 +264,7 @@ fn create_constellation(opts: opts::Opts,
constellation_chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
};
- constellation_chan
+ (constellation_chan, from_swmanager_sender)
}
// A logger that logs to two downstream loggers.
@@ -308,7 +311,9 @@ pub fn run_content_process(token: String) {
create_sandbox();
}
- script::init();
+ // Send the constellation sender to service worker manager thread
+ let from_swmanager_sender = unprivileged_content.swmanager_chan();
+ script::init(from_swmanager_sender);
unprivileged_content.start_all::<script_layout_interface::message::Msg,
layout_thread::LayoutThread,