aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-06-02 14:49:21 -0700
committerGitHub <noreply@github.com>2017-06-02 14:49:21 -0700
commiteac4f407e2bfa0055a698ca438972566f0814e43 (patch)
tree716e3d3096356721644c92e155c033599096adbc /components/script
parent54448305de3048f23004de0d9ee84efd25af8a79 (diff)
parent541baafe1c644f5276fe417a4d7e3696d3b22e68 (diff)
downloadservo-eac4f407e2bfa0055a698ca438972566f0814e43.tar.gz
servo-eac4f407e2bfa0055a698ca438972566f0814e43.zip
Auto merge of #15354 - cynicaldevil:manual-redirect, r=jdm
Redirect document loads manually <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #14596 . r? @jdm I ran some tests at random from the `navigating-across-documents` folder, and they are passing. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15354) <!-- Reviewable:end -->
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/servoparser/mod.rs1
-rw-r--r--components/script/script_thread.rs90
2 files changed, 62 insertions, 29 deletions
diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs
index af017d58958..254c178f8f6 100644
--- a/components/script/dom/servoparser/mod.rs
+++ b/components/script/dom/servoparser/mod.rs
@@ -527,6 +527,7 @@ impl Tokenizer {
/// The context required for asynchronously fetching a document
/// and parsing it progressively.
+#[derive(JSTraceable)]
pub struct ParserContext {
/// The parser that initiated the request.
parser: Option<Trusted<ServoParser>>,
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 405616fedec..8dabb29c81b 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -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) {