mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Redirect document loads manually
This commit is contained in:
parent
779edd7c4a
commit
541baafe1c
17 changed files with 376 additions and 52 deletions
|
@ -60,7 +60,7 @@ use dom::worklet::WorkletThreadPool;
|
|||
use dom::workletglobalscope::WorkletGlobalScopeInit;
|
||||
use euclid::Rect;
|
||||
use euclid::point::Point2D;
|
||||
use hyper::header::{ContentType, HttpDate, LastModified, Headers};
|
||||
use hyper::header::{ContentType, HttpDate, Headers, LastModified};
|
||||
use hyper::header::ReferrerPolicy as ReferrerPolicyHeader;
|
||||
use hyper::mime::{Mime, SubLevel, TopLevel};
|
||||
use hyper_serde::Serde;
|
||||
|
@ -74,12 +74,11 @@ use js::rust::Runtime;
|
|||
use mem::heap_size_of_self_and_children;
|
||||
use microtask::{MicrotaskQueue, Microtask};
|
||||
use msg::constellation_msg::{BrowsingContextId, FrameType, PipelineId, PipelineNamespace, TopLevelBrowsingContextId};
|
||||
use net_traits::{CoreResourceMsg, FetchMetadata, FetchResponseListener};
|
||||
use net_traits::{IpcSend, Metadata, ReferrerPolicy, ResourceThreads};
|
||||
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg};
|
||||
use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads};
|
||||
use net_traits::image_cache::{ImageCache, PendingImageResponse};
|
||||
use net_traits::request::{CredentialsMode, Destination, RequestInit};
|
||||
use net_traits::request::{CredentialsMode, Destination, RedirectMode, RequestInit};
|
||||
use net_traits::storage_thread::StorageType;
|
||||
use network_listener::NetworkListener;
|
||||
use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan};
|
||||
use profile_traits::time::{self, ProfilerCategory, profile};
|
||||
use script_layout_interface::message::{self, NewLayoutThreadInfo, ReflowQueryType};
|
||||
|
@ -105,7 +104,7 @@ use std::option::Option;
|
|||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use std::result::Result;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::{Receiver, Select, Sender, channel};
|
||||
use std::thread;
|
||||
|
@ -411,6 +410,8 @@ pub struct ScriptThread {
|
|||
window_proxies: DOMRefCell<HashMap<BrowsingContextId, JS<WindowProxy>>>,
|
||||
/// A list of data pertaining to loads that have not yet received a network response
|
||||
incomplete_loads: DOMRefCell<Vec<InProgressLoad>>,
|
||||
/// A vector containing parser contexts which have not yet been fully processed
|
||||
incomplete_parser_contexts: DOMRefCell<Vec<(PipelineId, ParserContext)>>,
|
||||
/// A map to store service worker registrations for a given origin
|
||||
registration_map: DOMRefCell<HashMap<ServoUrl, JS<ServiceWorkerRegistration>>>,
|
||||
/// A job queue for Service Workers keyed by their scope url
|
||||
|
@ -574,7 +575,7 @@ impl ScriptThreadFactory for ScriptThread {
|
|||
let origin = MutableOrigin::new(load_data.url.origin());
|
||||
let new_load = InProgressLoad::new(id, browsing_context_id, top_level_browsing_context_id, parent_info,
|
||||
layout_chan, window_size, load_data.url.clone(), origin);
|
||||
script_thread.start_page_load(new_load, load_data);
|
||||
script_thread.pre_page_load(new_load, load_data);
|
||||
|
||||
let reporter_name = format!("script-reporter-{}", id);
|
||||
mem_profiler_chan.run_with_memory_reporting(|| {
|
||||
|
@ -758,6 +759,7 @@ impl ScriptThread {
|
|||
documents: DOMRefCell::new(Documents::new()),
|
||||
window_proxies: DOMRefCell::new(HashMap::new()),
|
||||
incomplete_loads: DOMRefCell::new(vec!()),
|
||||
incomplete_parser_contexts: DOMRefCell::new(vec!()),
|
||||
registration_map: DOMRefCell::new(HashMap::new()),
|
||||
job_queue_map: Rc::new(JobQueue::new()),
|
||||
|
||||
|
@ -1105,6 +1107,14 @@ impl ScriptThread {
|
|||
|
||||
fn handle_msg_from_constellation(&self, msg: ConstellationControlMsg) {
|
||||
match msg {
|
||||
ConstellationControlMsg::NavigationResponse(id, fetch_data) => {
|
||||
match fetch_data {
|
||||
FetchResponseMsg::ProcessResponse(metadata) => self.handle_fetch_metadata(id, metadata),
|
||||
FetchResponseMsg::ProcessResponseChunk(chunk) => self.handle_fetch_chunk(id, chunk),
|
||||
FetchResponseMsg::ProcessResponseEOF(eof) => self.handle_fetch_eof(id, eof),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
},
|
||||
ConstellationControlMsg::Navigate(parent_pipeline_id, browsing_context_id, load_data, replace) =>
|
||||
self.handle_navigate(parent_pipeline_id, Some(browsing_context_id), load_data, replace),
|
||||
ConstellationControlMsg::SendEvent(id, event) =>
|
||||
|
@ -1396,7 +1406,7 @@ impl ScriptThread {
|
|||
if load_data.url.as_str() == "about:blank" {
|
||||
self.start_page_load_about_blank(new_load);
|
||||
} else {
|
||||
self.start_page_load(new_load, load_data);
|
||||
self.pre_page_load(new_load, load_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2225,45 +2235,67 @@ impl ScriptThread {
|
|||
window.evaluate_media_queries_and_report_changes();
|
||||
}
|
||||
|
||||
/// Initiate a non-blocking fetch for a specified resource. Stores the InProgressLoad
|
||||
/// Instructs the constellation to fetch the document that will be loaded. Stores the InProgressLoad
|
||||
/// argument until a notification is received that the fetch is complete.
|
||||
fn start_page_load(&self, incomplete: InProgressLoad, mut load_data: LoadData) {
|
||||
fn pre_page_load(&self, incomplete: InProgressLoad, load_data: LoadData) {
|
||||
let id = incomplete.pipeline_id.clone();
|
||||
|
||||
let context = Arc::new(Mutex::new(ParserContext::new(id, load_data.url.clone())));
|
||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||
let listener = NetworkListener {
|
||||
context: context,
|
||||
task_source: self.networking_task_source.clone(),
|
||||
wrapper: None,
|
||||
};
|
||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||
listener.notify_fetch(message.to().unwrap());
|
||||
});
|
||||
|
||||
if load_data.url.scheme() == "javascript" {
|
||||
load_data.url = ServoUrl::parse("about:blank").unwrap();
|
||||
}
|
||||
|
||||
let request = RequestInit {
|
||||
let mut req_init = RequestInit {
|
||||
url: load_data.url.clone(),
|
||||
method: load_data.method,
|
||||
destination: Destination::Document,
|
||||
credentials_mode: CredentialsMode::Include,
|
||||
use_url_credentials: true,
|
||||
origin: load_data.url,
|
||||
origin: load_data.url.clone(),
|
||||
pipeline_id: Some(id),
|
||||
referrer_url: load_data.referrer_url,
|
||||
referrer_policy: load_data.referrer_policy,
|
||||
headers: load_data.headers,
|
||||
body: load_data.data,
|
||||
redirect_mode: RedirectMode::Manual,
|
||||
.. RequestInit::default()
|
||||
};
|
||||
|
||||
self.resource_threads.send(CoreResourceMsg::Fetch(request, action_sender)).unwrap();
|
||||
if req_init.url.scheme() == "javascript" {
|
||||
req_init.url = ServoUrl::parse("about:blank").unwrap();
|
||||
}
|
||||
|
||||
let context = ParserContext::new(id, load_data.url);
|
||||
self.incomplete_parser_contexts.borrow_mut().push((id, context));
|
||||
|
||||
self.constellation_chan.send(ConstellationMsg::InitiateNavigateRequest(req_init, id)).unwrap();
|
||||
self.incomplete_loads.borrow_mut().push(incomplete);
|
||||
}
|
||||
|
||||
fn handle_fetch_metadata(&self, id: PipelineId, fetch_metadata: Result<FetchMetadata, NetworkError>) {
|
||||
match fetch_metadata {
|
||||
Ok(_) => {},
|
||||
Err(ref e) => warn!("Network error: {:?}", e),
|
||||
};
|
||||
let mut incomplete_parser_contexts = self.incomplete_parser_contexts.borrow_mut();
|
||||
let parser = incomplete_parser_contexts.iter_mut().find(|&&mut (pipeline_id, _)| pipeline_id == id);
|
||||
if let Some(&mut (_, ref mut ctxt)) = parser {
|
||||
ctxt.process_response(fetch_metadata);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_fetch_chunk(&self, id: PipelineId, chunk: Vec<u8>) {
|
||||
let mut incomplete_parser_contexts = self.incomplete_parser_contexts.borrow_mut();
|
||||
let parser = incomplete_parser_contexts.iter_mut().find(|&&mut (pipeline_id, _)| pipeline_id == id);
|
||||
if let Some(&mut (_, ref mut ctxt)) = parser {
|
||||
ctxt.process_response_chunk(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_fetch_eof(&self, id: PipelineId, eof: Result<(), NetworkError>) {
|
||||
let idx = self.incomplete_parser_contexts.borrow().iter().position(|&(pipeline_id, _)| {
|
||||
pipeline_id == id
|
||||
});
|
||||
if let Some(idx) = idx {
|
||||
let (_, mut ctxt) = self.incomplete_parser_contexts.borrow_mut().remove(idx);
|
||||
ctxt.process_response_eof(eof);
|
||||
}
|
||||
}
|
||||
|
||||
/// Synchronously fetch `about:blank`. Stores the `InProgressLoad`
|
||||
/// argument until a notification is received that the fetch is complete.
|
||||
fn start_page_load_about_blank(&self, incomplete: InProgressLoad) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue