diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-02-18 22:26:19 +0530 |
---|---|---|
committer | bors-servo <lbergstrom+bors@mozilla.com> | 2016-02-18 22:26:19 +0530 |
commit | fe70efe07f6d72665f10c752884e5705d5bdc600 (patch) | |
tree | 7030b6318f9bf6a8503d056354aea166dbceb25e | |
parent | 83be388f59b1bb4dfccc6ccd89022caa13b37a94 (diff) | |
parent | ace5b7a2e868ee32a9cfaec1bdb1adb23241a6ae (diff) | |
download | servo-fe70efe07f6d72665f10c752884e5705d5bdc600.tar.gz servo-fe70efe07f6d72665f10c752884e5705d5bdc600.zip |
Auto merge of #8952 - KiChjang:planned-navigation, r=Manishearth
Implement planned navigation
Fixes #3648.
Note that I have only implemented "mutate action URL" and "get action URL". The remaining ones can have E-less easy issues created for them.
<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8952)
<!-- Reviewable:end -->
-rw-r--r-- | components/profile/time.rs | 1 | ||||
-rw-r--r-- | components/profile_traits/time.rs | 1 | ||||
-rw-r--r-- | components/script/dom/htmlformelement.rs | 67 | ||||
-rw-r--r-- | components/script/script_thread.rs | 4 |
4 files changed, 63 insertions, 10 deletions
diff --git a/components/profile/time.rs b/components/profile/time.rs index f954912a130..5bb2a0cc0dc 100644 --- a/components/profile/time.rs +++ b/components/profile/time.rs @@ -96,6 +96,7 @@ impl Formattable for ProfilerCategory { ProfilerCategory::ScriptImageCacheMsg => "Script Image Cache Msg", ProfilerCategory::ScriptInputEvent => "Script Input Event", ProfilerCategory::ScriptNetworkEvent => "Script Network Event", + ProfilerCategory::ScriptPlannedNavigation => "Script Planned Navigation", ProfilerCategory::ScriptResize => "Script Resize", ProfilerCategory::ScriptEvent => "Script Event", ProfilerCategory::ScriptUpdateReplacedElement => "Script Update Replaced Element", diff --git a/components/profile_traits/time.rs b/components/profile_traits/time.rs index 44b12ccb63f..925ebe64c3d 100644 --- a/components/profile_traits/time.rs +++ b/components/profile_traits/time.rs @@ -65,6 +65,7 @@ pub enum ProfilerCategory { ScriptImageCacheMsg, ScriptInputEvent, ScriptNetworkEvent, + ScriptPlannedNavigation, ScriptResize, ScriptSetViewport, ScriptTimerEvent, diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 00e5b30889d..167e1698845 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -13,6 +13,7 @@ use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaEl use dom::bindings::conversions::DerivedFrom; use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId}; use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::Reflectable; use dom::document::Document; use dom::element::Element; @@ -31,22 +32,29 @@ use dom::htmlselectelement::HTMLSelectElement; use dom::htmltextareaelement::HTMLTextAreaElement; use dom::node::{Node, document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; +use dom::window::Window; use hyper::header::ContentType; use hyper::method::Method; use hyper::mime; -use msg::constellation_msg::LoadData; -use script_thread::{MainThreadScriptMsg, ScriptChan}; +use msg::constellation_msg::{LoadData, PipelineId}; +use script_thread::ScriptThreadEventCategory::FormPlannedNavigation; +use script_thread::{CommonScriptMsg, MainThreadScriptMsg, Runnable, ScriptChan}; use std::borrow::ToOwned; use std::cell::Cell; +use std::sync::mpsc::Sender; use string_cache::Atom; use url::form_urlencoded::serialize; use util::str::DOMString; +#[derive(JSTraceable, PartialEq, Clone, Copy, HeapSizeOf)] +pub struct GenerationId(u32); + #[dom_struct] pub struct HTMLFormElement { htmlelement: HTMLElement, marked_for_reset: Cell<bool>, elements: MutNullableHeap<JS<HTMLFormControlsCollection>>, + generation_id: Cell<GenerationId> } impl HTMLFormElement { @@ -57,6 +65,7 @@ impl HTMLFormElement { htmlelement: HTMLElement::new_inherited(localName, prefix, document), marked_for_reset: Cell::new(false), elements: Default::default(), + generation_id: Cell::new(GenerationId(0)) } } @@ -282,25 +291,48 @@ impl HTMLFormElement { }; // Step 18 + let win = window_from_node(self); match (&*scheme, method) { + // https://html.spec.whatwg.org/multipage/#submit-dialog (_, FormMethod::FormDialog) => return, // Unimplemented + // https://html.spec.whatwg.org/multipage/#submit-mutate-action ("http", FormMethod::FormGet) | ("https", FormMethod::FormGet) => { load_data.url.query = Some(parsed_data); - }, + self.plan_to_navigate(load_data, &win); + } + // https://html.spec.whatwg.org/multipage/#submit-body ("http", FormMethod::FormPost) | ("https", FormMethod::FormPost) => { load_data.method = Method::Post; load_data.data = Some(parsed_data.into_bytes()); - }, + } // https://html.spec.whatwg.org/multipage/#submit-get-action ("file", _) | ("about", _) | ("data", FormMethod::FormGet) | - ("ftp", _) | ("javascript", _) => (), + ("ftp", _) | ("javascript", _) => { + self.plan_to_navigate(load_data, &win); + } _ => return // Unimplemented (data and mailto) } + } - // This is wrong. https://html.spec.whatwg.org/multipage/#planned-navigation - let win = window_from_node(self); - win.main_thread_script_chan().send(MainThreadScriptMsg::Navigate( - win.pipeline(), load_data)).unwrap(); + /// [Planned navigation](https://html.spec.whatwg.org/multipage/#planned-navigation) + fn plan_to_navigate(&self, load_data: LoadData, window: &Window) { + // Step 1 + // Each planned navigation runnable is tagged with a generation ID, and + // before the runnable is handled, it first checks whether the HTMLFormElement's + // generation ID is the same as its own generation ID. + let GenerationId(prev_id) = self.generation_id.get(); + self.generation_id.set(GenerationId(prev_id + 1)); + // Step 2 + let nav = box PlannedNavigation { + load_data: load_data, + pipeline_id: window.pipeline(), + script_chan: window.main_thread_script_chan().clone(), + generation_id: self.generation_id.get(), + form: Trusted::new(self, window.dom_manipulation_task_source()) + }; + // Step 3 + window.dom_manipulation_task_source().send( + CommonScriptMsg::RunnableMsg(FormPlannedNavigation, nav)).unwrap(); } /// Interactively validate the constraints of form elements @@ -721,3 +753,20 @@ impl VirtualMethods for HTMLFormElement { } } } + +struct PlannedNavigation { + load_data: LoadData, + pipeline_id: PipelineId, + script_chan: Sender<MainThreadScriptMsg>, + generation_id: GenerationId, + form: Trusted<HTMLFormElement> +} + +impl Runnable for PlannedNavigation { + fn handler(self: Box<PlannedNavigation>) { + if self.generation_id == self.form.root().generation_id.get() { + let script_chan = self.script_chan.clone(); + script_chan.send(MainThreadScriptMsg::Navigate(self.pipeline_id, self.load_data)).unwrap(); + } + } +} diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index ff8b25b9d67..330bee776d3 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -228,14 +228,15 @@ pub enum ScriptThreadEventCategory { DocumentEvent, DomEvent, FileRead, + FormPlannedNavigation, ImageCacheMsg, InputEvent, NetworkEvent, Resize, ScriptEvent, - TimerEvent, SetViewport, StylesheetLoad, + TimerEvent, UpdateReplacedElement, WebSocketEvent, WorkerEvent, @@ -1076,6 +1077,7 @@ impl ScriptThread { ScriptThreadEventCategory::DocumentEvent => ProfilerCategory::ScriptDocumentEvent, ScriptThreadEventCategory::DomEvent => ProfilerCategory::ScriptDomEvent, ScriptThreadEventCategory::FileRead => ProfilerCategory::ScriptFileRead, + ScriptThreadEventCategory::FormPlannedNavigation => ProfilerCategory::ScriptPlannedNavigation, ScriptThreadEventCategory::ImageCacheMsg => ProfilerCategory::ScriptImageCacheMsg, ScriptThreadEventCategory::InputEvent => ProfilerCategory::ScriptInputEvent, ScriptThreadEventCategory::NetworkEvent => ProfilerCategory::ScriptNetworkEvent, |