diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 3 | ||||
-rw-r--r-- | components/script/dom/file.rs | 16 | ||||
-rw-r--r-- | components/script/dom/filelist.rs | 6 | ||||
-rw-r--r-- | components/script/dom/htmlformelement.rs | 2 | ||||
-rw-r--r-- | components/script/dom/htmlinputelement.rs | 68 | ||||
-rw-r--r-- | components/script/dom/window.rs | 1 |
6 files changed, 84 insertions, 12 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 1acb5ee9e4b..4c6941a5f5e 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -60,7 +60,7 @@ use net_traits::image::base::{Image, ImageMetadata}; use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread}; use net_traits::response::HttpsState; use net_traits::storage_thread::StorageType; -use net_traits::{Metadata, NetworkError}; +use net_traits::{Metadata, NetworkError, ResourceThreads}; use offscreen_gl_context::GLLimits; use profile_traits::mem::ProfilerChan as MemProfilerChan; use profile_traits::time::ProfilerChan as TimeProfilerChan; @@ -321,6 +321,7 @@ no_jsmanaged_fields!(HttpsState); no_jsmanaged_fields!(SharedRt); no_jsmanaged_fields!(TouchpadPressurePhase); no_jsmanaged_fields!(ReferrerPolicy); +no_jsmanaged_fields!(ResourceThreads); impl JSTraceable for Box<ScriptChan + Send> { #[inline] diff --git a/components/script/dom/file.rs b/components/script/dom/file.rs index 9667182671a..4ece71a5ce3 100644 --- a/components/script/dom/file.rs +++ b/components/script/dom/file.rs @@ -10,6 +10,8 @@ use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::reflector::reflect_dom_object; use dom::blob::{Blob, DataSlice, blob_parts_to_bytes}; +use dom::window::Window; +use net_traits::filemanager_thread::SelectedFile; use std::sync::Arc; use time; use util::str::DOMString; @@ -45,6 +47,19 @@ impl File { FileBinding::Wrap) } + // Construct from selected file message from file manager thread + pub fn new_from_selected(window: &Window, selected: SelectedFile) -> Root<File> { + let name = DOMString::from(selected.filename.to_str().expect("File name encoding error")); + + // FIXME: fix this after PR #11221 is landed + let id = selected.id; + let slice = DataSlice::empty(); + + let global = GlobalRef::Window(window); + + File::new(global, slice, name, Some(selected.modified as i64), "") + } + // https://w3c.github.io/FileAPI/#file-constructor pub fn Constructor(global: GlobalRef, fileBits: Vec<BlobOrString>, @@ -64,7 +79,6 @@ impl File { pub fn name(&self) -> &DOMString { &self.name } - } impl FileMethods for File { diff --git a/components/script/dom/filelist.rs b/components/script/dom/filelist.rs index ef49e88da6d..bf7243d9e73 100644 --- a/components/script/dom/filelist.rs +++ b/components/script/dom/filelist.rs @@ -27,8 +27,10 @@ impl FileList { } #[allow(unrooted_must_root)] - pub fn new(window: &Window, files: Vec<JS<File>>) -> Root<FileList> { - reflect_dom_object(box FileList::new_inherited(files), GlobalRef::Window(window), FileListBinding::Wrap) + pub fn new(window: &Window, files: Vec<Root<File>>) -> Root<FileList> { + reflect_dom_object(box FileList::new_inherited(files.iter().map(|r| JS::from_rooted(&r)).collect()), + GlobalRef::Window(window), + FileListBinding::Wrap) } } diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 92df6695f48..aff02b534b1 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -615,7 +615,7 @@ impl HTMLFormElement { // Step 4 for datum in &mut ret { match &*datum.ty { - "file" | "textarea" => (), + "file" | "textarea" => (), // TODO _ => { datum.name = clean_crlf(&datum.name); datum.value = FormDatumValue::String(clean_crlf( match datum.value { diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index c2c76dd16e8..4eb1d4d9ba0 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -7,16 +7,19 @@ use dom::activation::{Activatable, ActivationSource, synthetic_click_activation} use dom::attr::{Attr, AttrValue}; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::EventBinding::EventMethods; +use dom::bindings::codegen::Bindings::FileListBinding::FileListMethods; use dom::bindings::codegen::Bindings::HTMLInputElementBinding; use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods; use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, LayoutJS, Root, RootedReference}; +use dom::bindings::js::{JS, LayoutJS, Root, RootedReference, MutNullableHeap}; use dom::document::Document; use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers, LayoutElementHelpers}; use dom::event::{Event, EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget; +use dom::file::File; +use dom::filelist::FileList; use dom::htmlelement::HTMLElement; use dom::htmlfieldsetelement::HTMLFieldSetElement; use dom::htmlformelement::{FormDatumValue, FormControl, FormDatum, FormSubmitter, HTMLFormElement}; @@ -27,7 +30,9 @@ use dom::node::{document_from_node, window_from_node}; use dom::nodelist::NodeList; use dom::validation::Validatable; use dom::virtualmethods::VirtualMethods; -use ipc_channel::ipc::IpcSender; +use ipc_channel::ipc::{self, IpcSender}; +use net_traits::IpcSend; +use net_traits::filemanager_thread::FileManagerThreadMsg; use script_traits::ScriptMsg as ConstellationMsg; use std::borrow::ToOwned; use std::cell::Cell; @@ -81,7 +86,7 @@ pub struct HTMLInputElement { // https://html.spec.whatwg.org/multipage/#concept-input-value-dirty-flag value_dirty: Cell<bool>, - // TODO: selected files for file input + filelist: MutNullableHeap<JS<FileList>>, } #[derive(JSTraceable)] @@ -130,6 +135,7 @@ impl HTMLInputElement { textinput: DOMRefCell::new(TextInput::new(Single, DOMString::new(), chan, None, SelectionDirection::None)), activation_state: DOMRefCell::new(InputActivationState::new()), value_dirty: Cell::new(false), + filelist: MutNullableHeap::new(None), } } @@ -354,8 +360,18 @@ impl HTMLInputElementMethods for HTMLInputElement { |a| DOMString::from(a.summarize().value)) } ValueMode::Filename => { - // TODO: return C:\fakepath\<first of selected files> when a file is selected - DOMString::from("") + let mut path = DOMString::from(""); + match self.filelist.get() { + Some(ref fl) => match fl.Item(0) { + Some(ref f) => { + path.push_str("C:\\fakepath\\"); + path.push_str(f.name()); + path + } + None => path, + }, + None => path, + } } } } @@ -373,7 +389,9 @@ impl HTMLInputElementMethods for HTMLInputElement { } ValueMode::Filename => { if value.is_empty() { - // TODO: empty list of selected files + let window = window_from_node(self); + let fl = FileList::new(window.r(), vec![]); + self.filelist.set(Some(&fl)); } else { return Err(Error::InvalidState); } @@ -1096,6 +1114,44 @@ impl Activatable for HTMLInputElement { EventBubbles::Bubbles, EventCancelable::NotCancelable); }, + InputType::InputFile => { + let window = window_from_node(self); + let filemanager = window.resource_threads().sender(); + + let mut files: Vec<Root<File>> = vec![]; + let mut error = None; + + if self.Multiple() { + let (chan, recv) = ipc::channel().expect("Error initializing channel"); + let msg = FileManagerThreadMsg::SelectFiles(chan); + let _ = filemanager.send(msg).unwrap(); + + match recv.recv().expect("IpcSender side error") { + Ok(selected_files) => { + for selected in selected_files { + files.push(File::new_from_selected(window.r(), selected)); + } + }, + Err(err) => error = Some(err), + }; + } else { + let (chan, recv) = ipc::channel().expect("Error initializing channel"); + let msg = FileManagerThreadMsg::SelectFile(chan); + let _ = filemanager.send(msg).unwrap(); + + match recv.recv().expect("IpcSender side error") { + Ok(selected) => files.push(File::new_from_selected(window.r(), selected)), + Err(err) => error = Some(err), + }; + } + + if let Some(err) = error { + debug!("Input file select error: {:?}", err); + } else { + let filelist = FileList::new(window.r(), files); + self.filelist.set(Some(&filelist)); + } + } _ => () } } diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 1fdcd07ba84..8fdb7049715 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1603,4 +1603,3 @@ fn debug_reflow_events(id: PipelineId, goal: &ReflowGoal, query_type: &ReflowQue println!("{}", debug_msg); } -no_jsmanaged_fields!(ResourceThreads); |