diff --git a/.changes/macos-protocol-body-nocopy.md b/.changes/macos-protocol-body-nocopy.md new file mode 100644 index 000000000..8774ab1c7 --- /dev/null +++ b/.changes/macos-protocol-body-nocopy.md @@ -0,0 +1,5 @@ +--- +"wry": patch +--- + +On macOS, avoid an extra copy for owned custom protocol response bodies by transferring the body buffer into `NSData`. diff --git a/Cargo.lock b/Cargo.lock index 7ca4fc451..5071efdc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1944,6 +1944,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998" dependencies = [ "bitflags 2.8.0", + "block2 0.6.2", "objc2 0.6.4", "objc2-core-foundation", ] diff --git a/Cargo.toml b/Cargo.toml index 30996c574..f99618f47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -138,6 +138,7 @@ objc2-core-foundation = { version = "0.3.0", default-features = false, features ] } objc2-foundation = { version = "0.3.0", default-features = false, features = [ "std", + "block2", "objc2-core-foundation", "NSURLRequest", "NSURL", diff --git a/src/wkwebview/class/url_scheme_handler.rs b/src/wkwebview/class/url_scheme_handler.rs index 254bbb65f..c280b84c1 100644 --- a/src/wkwebview/class/url_scheme_handler.rs +++ b/src/wkwebview/class/url_scheme_handler.rs @@ -4,7 +4,7 @@ use std::{ borrow::Cow, - ffi::{c_char, c_void, CStr}, + ffi::{c_char, CStr}, panic::AssertUnwindSafe, ptr::NonNull, }; @@ -214,7 +214,7 @@ extern "C" fn start_task( check_webview_id_valid(webview_id)?; check_task_is_valid(&webview, task_key, task_uuid.clone())?; - let content = sent_response.body(); + let content_len = sent_response.body().len(); // default: application/octet-stream, but should be provided by the client let wanted_mime = sent_response.headers().get(CONTENT_TYPE); // default to 200 @@ -231,7 +231,7 @@ extern "C" fn start_task( } headers.insert( &*NSString::from_str(CONTENT_LENGTH.as_str()), - &*NSString::from_str(&content.len().to_string()), + &*NSString::from_str(&content_len.to_string()), ); // add headers @@ -264,15 +264,10 @@ extern "C" fn start_task( })) .map_err(|_e| crate::Error::CustomProtocolTaskInvalid)?; - // Send data - let data = NSData::alloc(); - // MIGRATE NOTE: we copied the content to the NSData because content will be freed - // when out of scope but NSData will also free the content when it's done and cause doube free. - let data = NSData::initWithBytes_length( - data, - content.as_ptr() as *mut c_void, - content.len(), - ); + let data = match sent_response.into_body() { + Cow::Owned(content) => NSData::from_vec(content), + Cow::Borrowed(content) => NSData::with_bytes(content), + }; // Check validity again check_webview_id_valid(webview_id)?;