diff --git a/src/components/script/dom/bindings/codegen/Bindings.conf b/src/components/script/dom/bindings/codegen/Bindings.conf index eba419c0a4f..3d21aa4f085 100644 --- a/src/components/script/dom/bindings/codegen/Bindings.conf +++ b/src/components/script/dom/bindings/codegen/Bindings.conf @@ -40,6 +40,7 @@ DOMInterfaces = { 'nativeType': 'EventListenerBinding::EventListener', }, 'EventTarget': {}, +'File': {}, 'FormData': {}, 'HTMLAnchorElement': {}, 'HTMLAppletElement': {}, diff --git a/src/components/script/dom/blob.rs b/src/components/script/dom/blob.rs index 6eff7b2b133..be94d5638cc 100644 --- a/src/components/script/dom/blob.rs +++ b/src/components/script/dom/blob.rs @@ -2,23 +2,32 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::codegen::InheritTypes::FileDerived; use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::error::Fallible; use dom::bindings::codegen::Bindings::BlobBinding; use dom::window::Window; +#[deriving(Encodable)] +pub enum BlobType { + BlobTypeId, + FileTypeId +} + #[deriving(Encodable)] pub struct Blob { pub reflector_: Reflector, - pub window: JS + pub window: JS, + pub type_: BlobType } impl Blob { pub fn new_inherited(window: &JSRef) -> Blob { Blob { reflector_: Reflector::new(), - window: JS::from_rooted(window) + window: JS::from_rooted(window), + type_: BlobTypeId } } @@ -41,3 +50,12 @@ impl Reflectable for Blob { &self.reflector_ } } + +impl FileDerived for Blob { + fn is_file(&self) -> bool { + match self.type_ { + FileTypeId => true, + _ => false + } + } +} \ No newline at end of file diff --git a/src/components/script/dom/file.rs b/src/components/script/dom/file.rs new file mode 100644 index 00000000000..ecaee0976f9 --- /dev/null +++ b/src/components/script/dom/file.rs @@ -0,0 +1,53 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::js::{JS, JSRef, Temporary}; +use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; +use dom::bindings::codegen::Bindings::FileBinding; +use dom::blob::{Blob, BlobType, FileTypeId}; +use dom::window::Window; +use servo_util::str::DOMString; + +#[deriving(Encodable)] +pub struct File { + pub blob: Blob, + pub name: DOMString, + pub window: JS, + pub type_: BlobType +} + +impl File { + pub fn new_inherited(window: &JSRef, _file_bits: &JSRef, name: DOMString) -> File { + File { + blob: Blob::new_inherited(window), + name: name, + window: JS::from_rooted(window), + type_: FileTypeId + } + // XXXManishearth Once Blob is able to store data + // the relevant subfields of file_bits should be copied over + } + + pub fn new(window: &JSRef, file_bits: &JSRef, name: DOMString) -> Temporary { + reflect_dom_object(box File::new_inherited(window, file_bits, name), + window, + FileBinding::Wrap) + } +} + +pub trait FileMethods { + fn Name(&self) -> DOMString; +} + +impl FileMethods for File { + fn Name(&self) -> DOMString { + self.name.clone() + } +} + +impl Reflectable for File { + fn reflector<'a>(&'a self) -> &'a Reflector { + self.blob.reflector() + } +} \ No newline at end of file diff --git a/src/components/script/dom/formdata.rs b/src/components/script/dom/formdata.rs index a20d1e66872..a38f1ea53f9 100644 --- a/src/components/script/dom/formdata.rs +++ b/src/components/script/dom/formdata.rs @@ -3,26 +3,29 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::Bindings::FormDataBinding; +use dom::bindings::codegen::InheritTypes::FileCast; +use dom::bindings::codegen::UnionTypes::FileOrString::{FileOrString, eFile, eString}; use dom::bindings::error::{Fallible}; -use dom::bindings::js::{JS, JSRef, Temporary, OptionalUnrootable}; +use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::trace::Traceable; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::blob::Blob; +use dom::file::File; use dom::htmlformelement::HTMLFormElement; use dom::window::Window; use servo_util::str::DOMString; -use collections::hashmap::HashMap; use std::cell::RefCell; +use collections::hashmap::HashMap; -#[deriving(Encodable)] +#[deriving(Encodable, Clone)] pub enum FormDatum { StringData(DOMString), - BlobData { blob: JS, name: DOMString } + FileData(JS) } #[deriving(Encodable)] pub struct FormData { - pub data: Traceable>>, + pub data: Traceable>>>, pub reflector_: Reflector, pub window: JS, pub form: Option> @@ -34,7 +37,7 @@ impl FormData { data: Traceable::new(RefCell::new(HashMap::new())), reflector_: Reflector::new(), window: JS::from_rooted(window), - form: form.unrooted(), + form: form.map(|f| JS::from_rooted(&f)), } } @@ -50,19 +53,53 @@ impl FormData { pub trait FormDataMethods { fn Append(&self, name: DOMString, value: &JSRef, filename: Option); fn Append_(&self, name: DOMString, value: DOMString); + fn Delete(&self, name: DOMString); + fn Get(&self, name: DOMString) -> Option; + fn Has(&self, name: DOMString) -> bool; + fn Set(&self, name: DOMString, value: &JSRef, filename: Option); + fn Set_(&self, name: DOMString, value: DOMString); } impl<'a> FormDataMethods for JSRef<'a, FormData> { fn Append(&self, name: DOMString, value: &JSRef, filename: Option) { - let blob = BlobData { - blob: JS::from_rooted(value), - name: filename.unwrap_or("default".to_string()) - }; - self.data.deref().borrow_mut().insert(name.clone(), blob); + let file = FileData(JS::from_rooted(&self.get_file_from_blob(value, filename))); + self.data.deref().borrow_mut().insert_or_update_with(name.clone(), vec!(file.clone()), + |_k, v| {v.push(file.clone());}); } fn Append_(&self, name: DOMString, value: DOMString) { - self.data.deref().borrow_mut().insert(name, StringData(value)); + self.data.deref().borrow_mut().insert_or_update_with(name, vec!(StringData(value.clone())), + |_k, v| {v.push(StringData(value.clone()));}); + } + + fn Delete(&self, name: DOMString) { + self.data.deref().borrow_mut().remove(&name); + } + + fn Get(&self, name: DOMString) -> Option { + if self.data.deref().borrow().contains_key_equiv(&name) { + match self.data.deref().borrow().get(&name).get(0).clone() { + StringData(ref s) => Some(eString(s.clone())), + FileData(ref f) => { + Some(eFile(f.clone())) + } + } + } else { + None + } + } + + fn Has(&self, name: DOMString) -> bool { + self.data.deref().borrow().contains_key_equiv(&name) + } + + fn Set(&self, name: DOMString, value: &JSRef, filename: Option) { + let file = FileData(JS::from_rooted(&self.get_file_from_blob(value, filename))); + self.data.deref().borrow_mut().insert(name, vec!(file)); + } + + fn Set_(&self, name: DOMString, value: DOMString) { + self.data.deref().borrow_mut().insert(name, vec!(StringData(value))); } } @@ -71,3 +108,16 @@ impl Reflectable for FormData { &self.reflector_ } } + +trait PrivateFormDataHelpers{ + fn get_file_from_blob(&self, value: &JSRef, filename: Option) -> Temporary; +} + +impl PrivateFormDataHelpers for FormData { + fn get_file_from_blob(&self, value: &JSRef, filename: Option) -> Temporary { + let global = self.window.root(); + let f: Option<&JSRef> = FileCast::to_ref(value); + let name = filename.unwrap_or(f.map(|inner| inner.name.clone()).unwrap_or("blob".to_string())); + File::new(&*global, value, name) + } +} \ No newline at end of file diff --git a/src/components/script/dom/webidls/File.webidl b/src/components/script/dom/webidls/File.webidl new file mode 100644 index 00000000000..0d5967b5e55 --- /dev/null +++ b/src/components/script/dom/webidls/File.webidl @@ -0,0 +1,15 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// http://dev.w3.org/2006/webapi/FileAPI/#dfn-file + +// [Constructor(sequence<(Blob or DOMString or ArrayBufferView or ArrayBuffer)> fileBits, +// [EnsureUTF16] DOMString fileName, optional FilePropertyBag options)] +interface File : Blob { + + readonly attribute DOMString name; + // readonly attribute Date lastModifiedDate; + +}; \ No newline at end of file diff --git a/src/components/script/dom/webidls/FormData.webidl b/src/components/script/dom/webidls/FormData.webidl index 4e4bef26850..cfa3e89b3cd 100644 --- a/src/components/script/dom/webidls/FormData.webidl +++ b/src/components/script/dom/webidls/FormData.webidl @@ -7,8 +7,16 @@ * http://xhr.spec.whatwg.org */ +typedef (File or DOMString) FormDataEntryValue; + [Constructor(optional HTMLFormElement form)] interface FormData { void append(DOMString name, Blob value, optional DOMString filename); void append(DOMString name, DOMString value); + void delete(DOMString name); + FormDataEntryValue? get(DOMString name); + // sequence getAll(DOMString name); + boolean has(DOMString name); + void set(DOMString name, Blob value, optional DOMString filename); + void set(DOMString name, DOMString value); }; diff --git a/src/components/script/script.rs b/src/components/script/script.rs index 05bf765128e..33b7eaa846a 100644 --- a/src/components/script/script.rs +++ b/src/components/script/script.rs @@ -83,6 +83,7 @@ pub mod dom { pub mod event; pub mod eventdispatcher; pub mod eventtarget; + pub mod file; pub mod formdata; pub mod htmlanchorelement; pub mod htmlappletelement;