diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-06-02 14:49:21 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-02 14:49:21 -0700 |
commit | eac4f407e2bfa0055a698ca438972566f0814e43 (patch) | |
tree | 716e3d3096356721644c92e155c033599096adbc /components/script | |
parent | 54448305de3048f23004de0d9ee84efd25af8a79 (diff) | |
parent | 541baafe1c644f5276fe417a4d7e3696d3b22e68 (diff) | |
download | servo-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.rs | 1 | ||||
-rw-r--r-- | components/script/script_thread.rs | 90 |
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) { |