script/dom/filesystem/
filesystemdirectoryreader.rs1use std::cell::Cell;
6
7use dom_struct::dom_struct;
8use js::context::JSContext;
9use script_bindings::cell::DomRefCell;
10use script_bindings::reflector::{Reflector, reflect_dom_object};
11
12use crate::dom::bindings::callback::{ExceptionHandling, RootedCallback, TracedCallback};
13use crate::dom::bindings::codegen::Bindings::FileSystemDirectoryReaderBinding::{
14 FileSystemDirectoryReaderMethods, FileSystemEntriesCallback,
15};
16use crate::dom::bindings::codegen::Bindings::FileSystemEntryBinding::ErrorCallback;
17use crate::dom::bindings::refcounted::Trusted;
18use crate::dom::bindings::reflector::DomGlobal;
19use crate::dom::bindings::root::{Dom, DomRoot};
20use crate::dom::filesystemdirectoryentry::FileSystemDirectoryEntry;
21use crate::dom::globalscope::GlobalScope;
22
23#[dom_struct]
24pub(crate) struct FileSystemDirectoryReader {
25 reflector_: Reflector,
26 dir: Dom<FileSystemDirectoryEntry>,
27 idx: Cell<usize>,
28 reading_flag: Cell<bool>,
29 done_flag: Cell<bool>,
30 pending_callbacks: DomRefCell<Vec<PendingEntriesCallback>>,
31 next_callback: Cell<usize>,
32}
33
34#[derive(JSTraceable, MallocSizeOf)]
35#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
36struct PendingEntriesCallback {
37 id: usize,
38 callback: TracedCallback<FileSystemEntriesCallback>,
39}
40
41impl FileSystemDirectoryReader {
42 fn new_inherited(dir: &FileSystemDirectoryEntry) -> FileSystemDirectoryReader {
43 FileSystemDirectoryReader {
44 reflector_: Reflector::new(),
45 dir: Dom::from_ref(dir),
46 idx: Cell::new(0),
47 reading_flag: Cell::new(false),
48 done_flag: Cell::new(false),
49 pending_callbacks: Default::default(),
50 next_callback: Cell::new(0),
51 }
52 }
53
54 pub(crate) fn new(
55 cx: &mut JSContext,
56 global: &GlobalScope,
57 dir: &FileSystemDirectoryEntry,
58 ) -> DomRoot<FileSystemDirectoryReader> {
59 reflect_dom_object(
60 cx,
61 Box::new(FileSystemDirectoryReader::new_inherited(dir)),
62 global,
63 )
64 }
65}
66
67impl FileSystemDirectoryReaderMethods<crate::DomTypeHolder> for FileSystemDirectoryReader {
68 fn ReadEntries(
70 &self,
71 success_callback: RootedCallback<FileSystemEntriesCallback>,
72 _error_callback: Option<RootedCallback<ErrorCallback>>,
73 ) {
74 let id = self.next_callback.get();
79 self.pending_callbacks
80 .borrow_mut()
81 .push(PendingEntriesCallback {
82 id,
83 callback: success_callback.to_traced(),
84 });
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 rooted!(&in(cx) 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}