adding interface for custom responses

This commit is contained in:
Rahul Sharma 2016-05-01 01:11:15 +05:30
parent bcea0ada27
commit 3766cd1673
17 changed files with 663 additions and 146 deletions

View file

@ -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};
use net_traits::{AsyncResponseTarget, LoadContext, PendingAsyncLoad, CoreResourceThread, ResponseAction, RequestSource};
use platform::font_context::FontContextHandle;
use platform::font_list::SANS_SERIF_FONT_FAMILY;
use platform::font_list::for_each_available_family;
@ -186,7 +186,8 @@ impl FontCache {
url.clone(),
None,
None,
None);
None,
RequestSource::None);
let (data_sender, data_receiver) = ipc::channel().unwrap();
let data_target = AsyncResponseTarget {
sender: data_sender,

View file

@ -5,8 +5,9 @@
use about_loader;
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};
use net_traits::{LoadConsumer, LoadData, Metadata, NetworkError, LoadOrigin, RequestSource};
use resource_thread::{CancellationListener, ProgressSender};
use resource_thread::{send_error, start_sending_sniffed_opt};
use std::borrow::ToOwned;
@ -30,6 +31,22 @@ enum LoadResult {
Finished,
}
struct FileLoadOrigin;
impl LoadOrigin for FileLoadOrigin {
fn referrer_url(&self) -> Option<Url> {
None
}
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
None
}
fn request_source(&self) -> RequestSource {
RequestSource::None
}
fn pipeline_id(&self) -> Option<PipelineId> {
None
}
}
fn read_block(reader: &mut File) -> Result<ReadStatus, String> {
let mut buf = vec![0; READ_SIZE];
match reader.read(&mut buf) {
@ -84,11 +101,12 @@ pub fn factory(load_data: LoadData,
// http://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open
// but, we'll go for a "file not found!"
let url = Url::parse("about:not-found").unwrap();
let load_data_404 = LoadData::new(load_data.context, url, None, None, None);
let load_data_404 = LoadData::new(load_data.context, url, &FileLoadOrigin);
about_loader::factory(load_data_404, senders, classifier, cancel_listener);
return;
}
};
if cancel_listener.is_cancelled() {
if let Ok(progress_chan) = get_progress_chan(load_data, file_path,
senders, classifier, &[]) {
@ -96,6 +114,7 @@ pub fn factory(load_data: LoadData,
}
return;
}
match read_block(reader) {
Ok(ReadStatus::Partial(buf)) => {
let progress_chan = get_progress_chan(load_data, file_path,

View file

@ -13,15 +13,16 @@ use flate2::read::{DeflateDecoder, GzDecoder};
use hsts::{HstsEntry, HstsList, secure_url};
use hyper::Error as HttpError;
use hyper::client::{Pool, Request, Response};
use hyper::header::{Accept, AcceptEncoding, ContentLength, ContentType, Host, Referer};
use hyper::header::{Accept, AcceptEncoding, ContentLength, ContentEncoding, ContentType, Host, Referer};
use hyper::header::{Authorization, Basic};
use hyper::header::{ContentEncoding, Encoding, Header, Headers, Quality, QualityItem};
use hyper::header::{Encoding, Header, Headers, Quality, QualityItem};
use hyper::header::{Location, SetCookie, StrictTransportSecurity, UserAgent, qitem};
use hyper::http::RawStatus;
use hyper::method::Method;
use hyper::mime::{Mime, SubLevel, TopLevel};
use hyper::net::Fresh;
use hyper::status::{StatusClass, StatusCode};
use ipc_channel::ipc;
use log;
use mime_classifier::MIMEClassifier;
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
@ -29,7 +30,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};
use net_traits::{Metadata, NetworkError, RequestSource, CustomResponse};
use openssl::ssl::error::{SslError, OpensslError};
use profile_traits::time::{ProfilerCategory, profile, ProfilerChan, TimerMetadata};
use profile_traits::time::{TimerMetadataReflowType, TimerMetadataFrameType};
@ -39,7 +40,7 @@ use std::boxed::FnBox;
use std::collections::HashSet;
use std::error::Error;
use std::fmt;
use std::io::{self, Read, Write};
use std::io::{self, Cursor, Read, Write};
use std::sync::mpsc::Sender;
use std::sync::{Arc, RwLock};
use time;
@ -149,6 +150,17 @@ fn load_for_consumer(load_data: LoadData,
}
}
pub struct WrappedHttpResponse {
pub response: Response
}
impl Read for WrappedHttpResponse {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.response.read(buf)
}
}
pub trait HttpResponse: Read {
fn headers(&self) -> &Headers;
fn status(&self) -> StatusCode;
@ -173,20 +185,6 @@ pub trait HttpResponse: Read {
}
}
pub struct WrappedHttpResponse {
pub response: Response
}
impl Read for WrappedHttpResponse {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.response.read(buf)
}
}
impl HttpResponse for WrappedHttpResponse {
fn headers(&self) -> &Headers {
&self.response.headers
@ -205,6 +203,34 @@ impl HttpResponse for WrappedHttpResponse {
}
}
pub struct ReadableCustomResponse {
headers: Headers,
raw_status: RawStatus,
body: Cursor<Vec<u8>>
}
pub fn to_readable_response(custom_response: CustomResponse) -> ReadableCustomResponse {
ReadableCustomResponse {
headers: custom_response.headers,
raw_status: custom_response.raw_status,
body: Cursor::new(custom_response.body)
}
}
impl HttpResponse for ReadableCustomResponse {
fn headers(&self) -> &Headers { &self.headers }
fn status(&self) -> StatusCode {
StatusCode::Ok
}
fn status_raw(&self) -> &RawStatus { &self.raw_status }
}
impl Read for ReadableCustomResponse {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.body.read(buf)
}
}
pub trait HttpRequestFactory {
type R: HttpRequest;
@ -466,13 +492,13 @@ fn update_sts_list_from_response(url: &Url, response: &HttpResponse, hsts_list:
}
}
pub struct StreamedResponse<R: HttpResponse> {
decoder: Decoder<R>,
pub struct StreamedResponse {
decoder: Decoder,
pub metadata: Metadata
}
impl<R: HttpResponse> Read for StreamedResponse<R> {
impl Read for StreamedResponse {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self.decoder {
@ -484,12 +510,12 @@ impl<R: HttpResponse> Read for StreamedResponse<R> {
}
}
impl<R: HttpResponse> StreamedResponse<R> {
fn new(m: Metadata, d: Decoder<R>) -> StreamedResponse<R> {
impl StreamedResponse {
fn new(m: Metadata, d: Decoder) -> StreamedResponse {
StreamedResponse { metadata: m, decoder: d }
}
fn from_http_response(response: R, m: Metadata) -> Result<StreamedResponse<R>, LoadError> {
fn from_http_response(response: Box<HttpResponse>, m: Metadata) -> Result<StreamedResponse, LoadError> {
let decoder = match response.content_encoding() {
Some(Encoding::Gzip) => {
let result = GzDecoder::new(response);
@ -515,11 +541,11 @@ impl<R: HttpResponse> StreamedResponse<R> {
}
}
enum Decoder<R: Read> {
Gzip(GzDecoder<R>),
Deflate(DeflateDecoder<R>),
Brotli(Decompressor<R>),
Plain(R)
enum Decoder {
Gzip(GzDecoder<Box<HttpResponse>>),
Deflate(DeflateDecoder<Box<HttpResponse>>),
Brotli(Decompressor<Box<HttpResponse>>),
Plain(Box<HttpResponse>)
}
fn send_request_to_devtools(devtools_chan: Option<Sender<DevtoolsControlMsg>>,
@ -771,7 +797,7 @@ pub fn load<A, B>(load_data: &LoadData,
request_factory: &HttpRequestFactory<R=A>,
user_agent: String,
cancel_listener: &CancellationListener)
-> Result<StreamedResponse<A::R>, LoadError> where A: HttpRequest + 'static, B: UIProvider {
-> Result<StreamedResponse, LoadError> where A: HttpRequest + 'static, B: UIProvider {
let max_redirects = prefs::get_pref("network.http.redirection-limit").as_i64().unwrap() as u32;
let mut iters = 0;
// URL of the document being loaded, as seen by all the higher-level code.
@ -785,6 +811,20 @@ pub fn load<A, B>(load_data: &LoadData,
return Err(LoadError::new(doc_url, LoadErrorType::Cancelled));
}
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);
}
}
RequestSource::None => {}
}
// If the URL is a view-source scheme then the scheme data contains the
// real URL that should be used for which the source is to be viewed.
// Change our existing URL to that and keep note that we are viewing
@ -942,7 +982,7 @@ pub fn load<A, B>(load_data: &LoadData,
metadata.headers.clone(), metadata.status.clone(),
pipeline_id);
}
return StreamedResponse::from_http_response(response, metadata)
return StreamedResponse::from_http_response(box response, metadata)
}
}

View file

@ -5,12 +5,13 @@
use immeta::load_from_buf;
use ipc_channel::ipc::{self, IpcSender, IpcReceiver};
use ipc_channel::router::ROUTER;
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
use net_traits::image::base::{Image, ImageMetadata, load_from_memory, PixelFormat};
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};
use net_traits::{ResponseAction, LoadContext, NetworkError};
use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadData, CoreResourceThread, LoadOrigin};
use net_traits::{ResponseAction, LoadContext, NetworkError, RequestSource};
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
@ -304,6 +305,23 @@ fn convert_format(format: PixelFormat) -> webrender_traits::ImageFormat {
}
}
struct ImageCacheOrigin;
impl LoadOrigin for ImageCacheOrigin {
fn referrer_url(&self) -> Option<Url> {
None
}
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
None
}
fn request_source(&self) -> RequestSource {
RequestSource::None
}
fn pipeline_id(&self) -> Option<PipelineId> {
None
}
}
impl ImageCache {
fn run(core_resource_thread: CoreResourceThread,
webrender_api: Option<webrender_traits::RenderApi>,
@ -520,7 +538,9 @@ impl ImageCache {
CacheResult::Miss => {
// A new load request! Request the load from
// the resource thread.
let load_data = LoadData::new(LoadContext::Image, (*ref_url).clone(), None, None, None);
let load_data = LoadData::new(LoadContext::Image,
(*ref_url).clone(),
&ImageCacheOrigin);
let (action_sender, action_receiver) = ipc::channel().unwrap();
let response_target = AsyncResponseTarget {
sender: action_sender,

View file

@ -76,6 +76,30 @@ pub enum LoadContext {
CacheManifest,
}
#[derive(Clone, Debug, Deserialize, Serialize, HeapSizeOf)]
pub struct CustomResponse {
#[ignore_heap_size_of = "Defined in hyper"]
pub headers: Headers,
#[ignore_heap_size_of = "Defined in hyper"]
pub raw_status: RawStatus,
pub body: Vec<u8>
}
impl CustomResponse {
pub fn new(headers: Headers, raw_status: RawStatus, body: Vec<u8>) -> CustomResponse {
CustomResponse { headers: headers, raw_status: raw_status, body: body }
}
}
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, HeapSizeOf)]
pub struct LoadData {
pub url: Url,
@ -96,15 +120,14 @@ pub struct LoadData {
/// The policy and referring URL for the originator of this request
pub referrer_policy: Option<ReferrerPolicy>,
pub referrer_url: Option<Url>,
pub source: RequestSource,
}
impl LoadData {
pub fn new(context: LoadContext,
url: Url,
id: Option<PipelineId>,
referrer_policy: Option<ReferrerPolicy>,
referrer_url: Option<Url>) -> LoadData {
load_origin: &LoadOrigin) -> LoadData {
LoadData {
url: url,
method: Method::Get,
@ -112,15 +135,23 @@ impl LoadData {
preserved_headers: Headers::new(),
data: None,
cors: None,
pipeline_id: id,
pipeline_id: load_origin.pipeline_id(),
credentials_flag: true,
context: context,
referrer_policy: referrer_policy,
referrer_url: referrer_url
referrer_policy: load_origin.referrer_policy(),
referrer_url: load_origin.referrer_url(),
source: load_origin.request_source()
}
}
}
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>;
}
/// Interface for observing the final response for an asynchronous fetch operation.
pub trait AsyncFetchListener {
fn response_available(&self, response: response::Response);
@ -304,6 +335,7 @@ pub struct PendingAsyncLoad {
context: LoadContext,
referrer_policy: Option<ReferrerPolicy>,
referrer_url: Option<Url>,
source: RequestSource
}
struct PendingLoadGuard {
@ -324,13 +356,29 @@ impl Drop for PendingLoadGuard {
}
}
impl LoadOrigin for PendingAsyncLoad {
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.source.clone()
}
fn pipeline_id(&self) -> Option<PipelineId> {
self.pipeline
}
}
impl PendingAsyncLoad {
pub fn new(context: LoadContext,
core_resource_thread: CoreResourceThread,
url: Url,
pipeline: Option<PipelineId>,
referrer_policy: Option<ReferrerPolicy>,
referrer_url: Option<Url>)
referrer_url: Option<Url>,
source: RequestSource)
-> PendingAsyncLoad {
PendingAsyncLoad {
core_resource_thread: core_resource_thread,
@ -339,14 +387,18 @@ impl PendingAsyncLoad {
guard: PendingLoadGuard { loaded: false, },
context: context,
referrer_policy: referrer_policy,
referrer_url: referrer_url
referrer_url: referrer_url,
source: source
}
}
/// Initiate the network request associated with this pending load, using the provided target.
pub fn load_async(mut self, listener: AsyncResponseTarget) {
self.guard.neuter();
let load_data = LoadData::new(self.context, self.url, self.pipeline, self.referrer_policy, self.referrer_url);
let load_data = LoadData::new(self.context.clone(),
self.url.clone(),
&self);
let consumer = LoadConsumer::Listener(listener);
self.core_resource_thread.send(CoreResourceMsg::Load(load_data, consumer, None)).unwrap();
}
@ -460,11 +512,11 @@ pub enum ProgressMsg {
pub fn load_whole_resource(context: LoadContext,
core_resource_thread: &CoreResourceThread,
url: Url,
pipeline_id: Option<PipelineId>)
load_origin: &LoadOrigin)
-> Result<(Metadata, Vec<u8>), NetworkError> {
let (start_chan, start_port) = ipc::channel().unwrap();
core_resource_thread.send(CoreResourceMsg::Load(LoadData::new(context, url, pipeline_id, None, None),
LoadConsumer::Channel(start_chan), None)).unwrap();
let load_data = LoadData::new(context, url, load_origin);
core_resource_thread.send(CoreResourceMsg::Load(load_data, LoadConsumer::Channel(start_chan), None)).unwrap();
let response = start_port.recv().unwrap();
let mut buf = vec!();

View file

@ -8,8 +8,8 @@
use dom::bindings::js::JS;
use dom::document::Document;
use msg::constellation_msg::PipelineId;
use net_traits::AsyncResponseTarget;
use net_traits::{PendingAsyncLoad, CoreResourceThread, LoadContext};
use net_traits::{RequestSource, AsyncResponseTarget};
use std::sync::Arc;
use std::thread;
use url::Url;
@ -130,20 +130,27 @@ impl DocumentLoader {
/// Create a new pending network request, which can be initiated at some point in
/// the future.
pub fn prepare_async_load(&mut self, load: LoadType, referrer: &Document) -> PendingAsyncLoad {
pub fn prepare_async_load(&mut self,
load: LoadType,
referrer: &Document) -> PendingAsyncLoad {
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_thread).clone(),
url,
self.pipeline,
referrer.get_referrer_policy(),
Some(referrer.url().clone()))
Some(referrer.url().clone()),
RequestSource::Window(client_chan))
}
/// Create and initiate a new network request.
pub fn load_async(&mut self, load: LoadType, listener: AsyncResponseTarget, referrer: &Document) {
pub fn load_async(&mut self,
load: LoadType,
listener: AsyncResponseTarget,
referrer: &Document) {
let pending = self.prepare_async_load(load, referrer);
pending.load_async(listener)
}

View file

@ -18,8 +18,8 @@ use ipc_channel::ipc::IpcSender;
use js::jsapi::{CurrentGlobalOrNull, GetGlobalForObjectCrossCompartment};
use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue};
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
use msg::constellation_msg::{PanicMsg, PipelineId};
use net_traits::CoreResourceThread;
use msg::constellation_msg::{PipelineId, PanicMsg};
use net_traits::{CoreResourceThread, RequestSource};
use profile_traits::{mem, time};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
use script_thread::{MainThreadScriptChan, ScriptThread};
@ -65,6 +65,14 @@ 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 {

View file

@ -16,7 +16,8 @@ use dom::bindings::refcounted::LiveDOMReferences;
use dom::bindings::reflector::Reflectable;
use dom::bindings::structuredclone::StructuredCloneData;
use dom::messageevent::MessageEvent;
use dom::worker::{SimpleWorkerErrorHandler, SharedRt, TrustedWorkerAddress, WorkerMessageHandler};
use dom::worker::{SimpleWorkerErrorHandler, SharedRt, TrustedWorkerAddress};
use dom::worker::{WorkerScriptLoadOrigin, WorkerMessageHandler};
use dom::workerglobalscope::WorkerGlobalScope;
use dom::workerglobalscope::WorkerGlobalScopeInit;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
@ -26,7 +27,7 @@ use js::jsapi::{JSAutoCompartment, JSContext, RootedValue};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::PipelineId;
use net_traits::{LoadContext, load_whole_resource};
use net_traits::{LoadContext, load_whole_resource, CustomResponse};
use rand::random;
use script_runtime::ScriptThreadEventCategory::WorkerEvent;
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
@ -133,6 +134,7 @@ enum MixedMessage {
FromWorker((TrustedWorkerAddress, WorkerScriptMsg)),
FromScheduler((TrustedWorkerAddress, TimerEvent)),
FromDevtools(DevtoolScriptControlMsg),
FromNetwork(IpcSender<Option<CustomResponse>>),
}
// https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope
@ -215,18 +217,18 @@ impl DedicatedWorkerGlobalScope {
worker: TrustedWorkerAddress,
parent_sender: Box<ScriptChan + Send>,
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>) {
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
worker_load_origin: WorkerScriptLoadOrigin) {
let serialized_worker_url = worker_url.to_string();
let name = format!("WebWorker for {}", serialized_worker_url);
let panic_chan = init.panic_chan.clone();
spawn_named_with_send_on_panic(name, SCRIPT | IN_WORKER, move || {
let roots = RootCollection::new();
let _stack_roots_tls = StackRootTLS::new(&roots);
let (url, source) = match load_whole_resource(LoadContext::Script,
&init.core_resource_thread,
worker_url,
None) {
&worker_load_origin) {
Err(_) => {
println!("error loading script {}", serialized_worker_url);
parent_sender.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
@ -316,17 +318,20 @@ 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() {
@ -335,6 +340,8 @@ 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!")
}
@ -397,6 +404,10 @@ impl DedicatedWorkerGlobalScope {
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);
}
}
}
}

View file

@ -1354,7 +1354,7 @@ impl Document {
pub fn load_async(&self, load: LoadType, listener: AsyncResponseTarget) {
let mut loader = self.loader.borrow_mut();
loader.load_async(load, listener, self)
loader.load_async(load, listener, self);
}
pub fn finish_load(&self, load: LoadType) {

View file

@ -45,10 +45,10 @@ use libc;
use msg::constellation_msg::{LoadData, PanicMsg, PipelineId, SubpageId};
use msg::constellation_msg::{WindowSizeData, WindowSizeType};
use msg::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
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 profile_traits::mem;
use profile_traits::time::{ProfilerCategory, TimerMetadata, TimerMetadataFrameType};
@ -148,6 +148,8 @@ 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>,
#[ignore_heap_size_of = "TODO(#6911) newtypes containing unmeasurable types are hard"]
compositor: IpcSender<ScriptToCompositorMsg>,
browsing_context: MutNullableHeap<JS<BrowsingContext>>,
@ -303,6 +305,10 @@ 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;
@ -1443,6 +1449,7 @@ impl Window {
history_task_source: HistoryTraversalTaskSource,
file_task_source: FileReadingTaskSource,
image_cache_chan: ImageCacheChan,
custom_message_chan: IpcSender<CustomResponseSender>,
compositor: IpcSender<ScriptToCompositorMsg>,
image_cache_thread: ImageCacheThread,
resource_threads: ResourceThreads,
@ -1480,6 +1487,7 @@ 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(),
compositor: compositor,

View file

@ -24,10 +24,13 @@ use js::jsapi::{HandleValue, JSContext, JSRuntime, RootedValue};
use js::jsapi::{JSAutoCompartment, JS_RequestInterruptCallback};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
use net_traits::{RequestSource, LoadOrigin};
use script_thread::Runnable;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{Sender, channel};
use std::sync::{Arc, Mutex};
use url::Url;
use util::str::DOMString;
pub type TrustedWorkerAddress = Trusted<Worker>;
@ -45,6 +48,29 @@ pub struct Worker {
runtime: Arc<Mutex<Option<SharedRt>>>
}
#[derive(Clone)]
pub struct WorkerScriptLoadOrigin {
referrer_url: Option<Url>,
referrer_policy: Option<ReferrerPolicy>,
request_source: RequestSource,
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()
}
}
impl Worker {
fn new_inherited(sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
closing: Arc<AtomicBool>) -> Worker {
@ -82,6 +108,13 @@ impl Worker {
let worker_ref = Trusted::new(worker.r());
let worker_id = global.get_next_worker_id();
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 optional_sender = match global.devtools_chan() {
Some(ref chan) => {
@ -114,7 +147,7 @@ impl Worker {
DedicatedWorkerGlobalScope::run_worker_scope(
init, worker_url, global.pipeline(), devtools_receiver, worker.runtime.clone(), worker_ref,
global.script_chan(), sender, receiver);
global.script_chan(), sender, receiver, worker_load_origin);
Ok(worker)
}

View file

@ -17,12 +17,13 @@ use dom::eventtarget::EventTarget;
use dom::window::{base64_atob, base64_btoa};
use dom::workerlocation::WorkerLocation;
use dom::workernavigator::WorkerNavigator;
use ipc_channel::ipc::IpcSender;
use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER;
use js::jsapi::{HandleValue, JSContext, JSRuntime, RootedValue};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::{PanicMsg, PipelineId};
use net_traits::{LoadContext, CoreResourceThread, load_whole_resource};
use msg::constellation_msg::{PipelineId, ReferrerPolicy, PanicMsg};
use net_traits::{LoadContext, CoreResourceThread, load_whole_resource, RequestSource, LoadOrigin, CustomResponseSender};
use profile_traits::{mem, time};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
use script_traits::ScriptMsg as ConstellationMsg;
@ -101,6 +102,12 @@ 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 {
@ -110,7 +117,8 @@ impl WorkerGlobalScope {
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
timer_event_chan: IpcSender<TimerEvent>)
-> 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)),
@ -133,6 +141,8 @@ 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
}
}
@ -182,6 +192,14 @@ 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)
}
@ -210,6 +228,21 @@ impl WorkerGlobalScope {
}
}
impl LoadOrigin for WorkerGlobalScope {
fn referrer_url(&self) -> Option<Url> {
None
}
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
None
}
fn request_source(&self) -> RequestSource {
RequestSource::None
}
fn pipeline_id(&self) -> Option<PipelineId> {
Some(self.pipeline())
}
}
impl WorkerGlobalScopeMethods for WorkerGlobalScope {
// https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-self
fn Self_(&self) -> Root<WorkerGlobalScope> {
@ -236,7 +269,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
let mut rval = RootedValue::new(self.runtime.cx(), UndefinedValue());
for url in urls {
let (url, source) = match load_whole_resource(LoadContext::Script, &self.core_resource_thread, url, None) {
let (url, source) = match load_whole_resource(LoadContext::Script, &self.core_resource_thread, url, self) {
Err(_) => return Err(Error::Network),
Ok((metadata, bytes)) => {
(metadata.final_url, String::from_utf8(bytes).unwrap())

View file

@ -44,9 +44,10 @@ use ipc_channel::router::ROUTER;
use js::jsapi::JS_ClearPendingException;
use js::jsapi::{JSContext, JS_ParseJSON, RootedValue};
use js::jsval::{JSVal, NullValue, UndefinedValue};
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
use net_traits::CoreResourceMsg::Load;
use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkError};
use net_traits::{LoadConsumer, LoadContext, LoadData, ResourceCORSData, CoreResourceThread};
use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkError, RequestSource};
use net_traits::{LoadConsumer, LoadContext, LoadData, ResourceCORSData, CoreResourceThread, LoadOrigin};
use network_listener::{NetworkListener, PreInvoke};
use parse::html::{ParseContext, parse_html};
use parse::xml::{self, parse_xml};
@ -295,6 +296,26 @@ impl XMLHttpRequest {
}
}
impl LoadOrigin for XMLHttpRequest {
fn referrer_url(&self) -> Option<Url> {
None
}
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
None
}
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())
}
}
impl XMLHttpRequestMethods for XMLHttpRequest {
// https://xhr.spec.whatwg.org/#handler-xhr-onreadystatechange
event_handler!(readystatechange, GetOnreadystatechange, SetOnreadystatechange);
@ -572,14 +593,11 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
// Step 5
let global = self.global();
let pipeline_id = global.r().pipeline();
//TODO - set referrer_policy/referrer_url in load_data
let mut load_data =
LoadData::new(LoadContext::Browsing,
self.request_url.borrow().clone().unwrap(),
Some(pipeline_id),
None,
None);
self);
if load_data.url.origin().ne(&global.r().get_url().origin()) {
load_data.credentials_flag = self.WithCredentials();
}

View file

@ -65,8 +65,8 @@ use msg::webdriver_msg::WebDriverScriptCommand;
use net_traits::LoadData as NetLoadData;
use net_traits::bluetooth_thread::BluetoothMethodMsg;
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadContext, Metadata};
use net_traits::{ResourceThreads, IpcSend};
use net_traits::{AsyncResponseTarget, CoreResourceMsg, LoadConsumer, LoadContext, Metadata, ResourceThreads};
use net_traits::{RequestSource, CustomResponse, CustomResponseSender, IpcSend};
use network_listener::NetworkListener;
use parse::ParserRoot;
use parse::html::{ParseContext, parse_html};
@ -205,6 +205,7 @@ enum MixedMessage {
FromDevtools(DevtoolScriptControlMsg),
FromImageCache(ImageCacheResult),
FromScheduler(TimerEvent),
FromNetwork(IpcSender<Option<CustomResponse>>),
}
/// Messages used to control the script event loop
@ -321,6 +322,12 @@ 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,
@ -537,6 +544,9 @@ 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 =
@ -559,6 +569,9 @@ impl ScriptThread {
bluetooth_thread: state.bluetooth_thread,
port: port,
custom_message_chan: ipc_custom_resp_chan,
custom_message_port: custom_msg_port,
chan: MainThreadScriptChan(chan.clone()),
dom_manipulation_task_source: DOMManipulationTaskSource(chan.clone()),
user_interaction_task_source: UserInteractionTaskSource(chan.clone()),
@ -620,7 +633,8 @@ impl ScriptThread {
/// Handle incoming control messages.
fn handle_msgs(&self) -> bool {
use self::MixedMessage::{FromScript, FromConstellation, FromScheduler, FromDevtools, FromImageCache};
use self::MixedMessage::{FromConstellation, FromDevtools, FromImageCache};
use self::MixedMessage::{FromScheduler, FromScript, FromNetwork};
// Handle pending resize events.
// Gather them first to avoid a double mut borrow on self.
@ -654,6 +668,7 @@ 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();
@ -662,6 +677,7 @@ impl ScriptThread {
devtools_port.add();
}
image_cache_port.add();
custom_message_port.add();
}
let ret = sel.wait();
if ret == script_port.id() {
@ -674,6 +690,8 @@ 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")
}
@ -736,7 +754,10 @@ 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(_) => break,
Err(_) => match self.custom_message_port.try_recv() {
Err(_) => break,
Ok(ev) => event = FromNetwork(ev)
},
Ok(ev) => event = FromImageCache(ev),
},
Ok(ev) => event = FromDevtools(ev),
@ -762,6 +783,7 @@ 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),
@ -821,6 +843,7 @@ impl ScriptThread {
}
},
MixedMessage::FromScheduler(_) => ScriptThreadEventCategory::TimerEvent,
MixedMessage::FromNetwork(_) => ScriptThreadEventCategory::NetworkEvent
}
}
@ -990,6 +1013,12 @@ 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 {
@ -1439,6 +1468,7 @@ impl ScriptThread {
HistoryTraversalTaskSource(history_sender.clone()),
FileReadingTaskSource(file_sender.clone()),
self.image_cache_channel.clone(),
self.custom_message_chan.clone(),
self.compositor.borrow_mut().clone(),
self.image_cache_thread.clone(),
self.resource_threads.clone(),
@ -1907,6 +1937,7 @@ impl ScriptThread {
credentials_flag: true,
referrer_policy: load_data.referrer_policy,
referrer_url: load_data.referrer_url,
source: RequestSource::Window(self.custom_message_chan.clone())
}, LoadConsumer::Listener(response_target), None)).unwrap();
self.incomplete_loads.borrow_mut().push(incomplete);