windows_webview/
download.rs1use super::*;
2use crate::handler::subscription;
3
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6pub enum DownloadState {
7 InProgress,
9 Interrupted,
12 Completed,
14}
15
16impl DownloadState {
17 fn from_raw(value: COREWEBVIEW2_DOWNLOAD_STATE) -> Self {
18 match value {
19 1 => Self::Interrupted,
20 2 => Self::Completed,
21 _ => Self::InProgress,
22 }
23 }
24}
25
26#[derive(Clone, Copy, Debug, PartialEq, Eq)]
28#[non_exhaustive]
29pub enum DownloadInterruptReason {
30 None,
32 FileFailed,
34 FileAccessDenied,
36 FileNoSpace,
38 FileNameTooLong,
40 FileTooLarge,
42 FileMalicious,
44 FileTransientError,
46 FileBlockedByPolicy,
48 FileSecurityCheckFailed,
50 FileTooShort,
52 FileHashMismatch,
54 NetworkFailed,
56 NetworkTimeout,
58 NetworkDisconnected,
60 NetworkServerDown,
62 NetworkInvalidRequest,
64 ServerFailed,
66 ServerNoRange,
68 ServerBadContent,
70 ServerUnauthorized,
72 ServerCertificateProblem,
74 ServerForbidden,
76 ServerUnexpectedResponse,
78 ServerContentLengthMismatch,
80 ServerCrossOriginRedirect,
82 UserCanceled,
84 UserShutdown,
86 UserPaused,
88 DownloadProcessCrashed,
90 Unknown,
92}
93
94impl DownloadInterruptReason {
95 fn from_raw(value: COREWEBVIEW2_DOWNLOAD_INTERRUPT_REASON) -> Self {
96 match value {
97 0 => Self::None,
98 1 => Self::FileFailed,
99 2 => Self::FileAccessDenied,
100 3 => Self::FileNoSpace,
101 4 => Self::FileNameTooLong,
102 5 => Self::FileTooLarge,
103 6 => Self::FileMalicious,
104 7 => Self::FileTransientError,
105 8 => Self::FileBlockedByPolicy,
106 9 => Self::FileSecurityCheckFailed,
107 10 => Self::FileTooShort,
108 11 => Self::FileHashMismatch,
109 12 => Self::NetworkFailed,
110 13 => Self::NetworkTimeout,
111 14 => Self::NetworkDisconnected,
112 15 => Self::NetworkServerDown,
113 16 => Self::NetworkInvalidRequest,
114 17 => Self::ServerFailed,
115 18 => Self::ServerNoRange,
116 19 => Self::ServerBadContent,
117 20 => Self::ServerUnauthorized,
118 21 => Self::ServerCertificateProblem,
119 22 => Self::ServerForbidden,
120 23 => Self::ServerUnexpectedResponse,
121 24 => Self::ServerContentLengthMismatch,
122 25 => Self::ServerCrossOriginRedirect,
123 26 => Self::UserCanceled,
124 27 => Self::UserShutdown,
125 28 => Self::UserPaused,
126 29 => Self::DownloadProcessCrashed,
127 _ => Self::Unknown,
128 }
129 }
130}
131
132#[derive(Clone)]
134pub struct DownloadOperation(pub(crate) ICoreWebView2DownloadOperation);
135
136impl DownloadOperation {
137 pub fn uri(&self) -> String {
139 unsafe { string::take_result(self.0.Uri()) }
140 }
141
142 pub fn content_disposition(&self) -> String {
145 unsafe { string::take_result(self.0.ContentDisposition()) }
146 }
147
148 pub fn mime_type(&self) -> String {
150 unsafe { string::take_result(self.0.MimeType()) }
151 }
152
153 pub fn total_bytes_to_receive(&self) -> i64 {
156 unsafe { self.0.TotalBytesToReceive() }.unwrap_or(0)
157 }
158
159 pub fn bytes_received(&self) -> i64 {
161 unsafe { self.0.BytesReceived() }.unwrap_or(0)
162 }
163
164 pub fn result_file_path(&self) -> String {
166 unsafe { string::take_result(self.0.ResultFilePath()) }
167 }
168
169 pub fn state(&self) -> DownloadState {
171 unsafe { self.0.State() }.map_or(DownloadState::InProgress, DownloadState::from_raw)
172 }
173
174 pub fn interrupt_reason(&self) -> DownloadInterruptReason {
177 unsafe { self.0.InterruptReason() }.map_or(
178 DownloadInterruptReason::None,
179 DownloadInterruptReason::from_raw,
180 )
181 }
182
183 pub fn can_resume(&self) -> bool {
186 unsafe { self.0.CanResume() }.is_ok_and(|value| value.as_bool())
187 }
188
189 pub fn cancel(&self) -> Result<()> {
191 unsafe { self.0.Cancel() }.ok()
192 }
193
194 pub fn pause(&self) -> Result<()> {
197 unsafe { self.0.Pause() }.ok()
198 }
199
200 pub fn resume(&self) -> Result<()> {
202 unsafe { self.0.Resume() }.ok()
203 }
204
205 subscription! {
206 on_bytes_received_changed(DownloadOperation) =>
210 BytesReceivedChanged, add_BytesReceivedChanged / remove_BytesReceivedChanged
211 }
212
213 subscription! {
214 on_state_changed(DownloadOperation) =>
218 DownloadStateChanged, add_StateChanged / remove_StateChanged
219 }
220}
221
222pub struct DownloadStartingArgs(pub(crate) ICoreWebView2DownloadStartingEventArgs);
224
225impl DownloadStartingArgs {
226 pub fn download_operation(&self) -> Result<DownloadOperation> {
228 unsafe { Ok(DownloadOperation(self.0.DownloadOperation()?)) }
229 }
230
231 pub fn is_cancelled(&self) -> bool {
233 unsafe { self.0.Cancel() }.is_ok_and(|value| value.as_bool())
234 }
235
236 pub fn set_cancel(&self, cancel: bool) -> Result<()> {
238 unsafe { self.0.SetCancel(cancel) }.ok()
239 }
240
241 pub fn result_file_path(&self) -> String {
243 unsafe { string::take_result(self.0.ResultFilePath()) }
244 }
245
246 pub fn set_result_file_path(&self, path: &str) -> Result<()> {
249 let path = HSTRING::from(path);
250 unsafe { self.0.SetResultFilePath(&path) }.ok()
251 }
252
253 pub fn is_handled(&self) -> bool {
256 unsafe { self.0.Handled() }.is_ok_and(|value| value.as_bool())
257 }
258
259 pub fn set_handled(&self, handled: bool) -> Result<()> {
262 unsafe { self.0.SetHandled(handled) }.ok()
263 }
264
265 pub fn defer(&self) -> Result<Deferral> {
268 Ok(Deferral::new(unsafe { self.0.GetDeferral()? }))
269 }
270}