script/dom/filesystem/
filesystemdirectoryreader.rs1use std::cell::Cell;
6use std::rc::Rc;
7
8use dom_struct::dom_struct;
9use js::context::JSContext;
10use script_bindings::cell::DomRefCell;
11use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
12
13use crate::dom::bindings::callback::ExceptionHandling;
14use crate::dom::bindings::codegen::Bindings::FileSystemDirectoryReaderBinding::{
15 FileSystemDirectoryReaderMethods, FileSystemEntriesCallback,
16};
17use crate::dom::bindings::codegen::Bindings::FileSystemEntryBinding::ErrorCallback;
18use crate::dom::bindings::refcounted::Trusted;
19use crate::dom::bindings::reflector::DomGlobal;
20use crate::dom::bindings::root::{Dom, DomRoot};
21use crate::dom::filesystemdirectoryentry::FileSystemDirectoryEntry;
22use crate::dom::globalscope::GlobalScope;
23
24#[dom_struct]
25pub(crate) struct FileSystemDirectoryReader {
26 reflector_: Reflector,
27 dir: Dom<FileSystemDirectoryEntry>,
28 idx: Cell<usize>,
29 reading_flag: Cell<bool>,
30 done_flag: Cell<bool>,
31 pending_callbacks: DomRefCell<Vec<PendingEntriesCallback>>,
32 next_callback: Cell<usize>,
33}
34
35#[derive(JSTraceable, MallocSizeOf)]
36struct PendingEntriesCallback {
37 id: usize,
38 #[conditional_malloc_size_of]
39 callback: Rc<FileSystemEntriesCallback>,
40}
41
42impl FileSystemDirectoryReader {
43 fn new_inherited(dir: &FileSystemDirectoryEntry) -> FileSystemDirectoryReader {
44 FileSystemDirectoryReader {
45 reflector_: Reflector::new(),
46 dir: Dom::from_ref(dir),
47 idx: Cell::new(0),
48 reading_flag: Cell::new(false),
49 done_flag: Cell::new(false),
50 pending_callbacks: Default::default(),
51 next_callback: Cell::new(0),
52 }
53 }
54
55 pub(crate) fn new(
56 cx: &mut JSContext,
57 global: &GlobalScope,
58 dir: &FileSystemDirectoryEntry,
59 ) -> DomRoot<FileSystemDirectoryReader> {
60 reflect_dom_object_with_cx(
61 Box::new(FileSystemDirectoryReader::new_inherited(dir)),
62 global,
63 cx,
64 )
65 }
66}
67
68impl FileSystemDirectoryReaderMethods<crate::DomTypeHolder> for FileSystemDirectoryReader {
69 fn ReadEntries(
71 &self,
72 success_callback: Rc<FileSystemEntriesCallback>,
73 _error_callback: Option<Rc<ErrorCallback>>,
74 ) {
75 let id = self.next_callback.get();
80 let pending_callback = PendingEntriesCallback {
81 id,
82 callback: success_callback,
83 };
84 self.pending_callbacks.borrow_mut().push(pending_callback);
85 self.next_callback.set(id + 1);
86
87 let this = Trusted::new(self);
88 self.global()
89 .task_manager()
90 .dom_manipulation_task_source()
91 .queue(task!(invoke_read_entries: move |cx| {
92 let this = this.root();
93 let maybe_index = this
94 .pending_callbacks
95 .borrow()
96 .iter()
97 .position(|val| val.id == id);
98 if let Some(index) = maybe_index {
99 let callback = this
100 .pending_callbacks
101 .borrow_mut()
102 .swap_remove(index)
103 .callback;
104 let entries = if this.done_flag.get() {
105 Vec::new()
106 } else {
107 this.done_flag.set(true);
108 this.dir.children()
109 };
110 let _ = callback.Call__(cx, entries, ExceptionHandling::Report);
111 }
112 }));
113 }
114}