Skip to content

Commit

Permalink
move api to WebView, make it blocking
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog committed Mar 7, 2025
1 parent 352fa40 commit 4214f70
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 68 deletions.
5 changes: 5 additions & 0 deletions .changes/WebViewExtDarwin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": patch
---

Added `WebViewExtDarwin` to expose WebView functions available to both macOS and iOS.
2 changes: 1 addition & 1 deletion .changes/fetch_all_and_remove_data_store.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
"wry": patch
---

feat: macOS: add `wry::fetch_all_data_store_identifiers` and `wry::remove_data_store`
feat: macOS: add `WebViewExtDarwin::fetch_data_store_identifiers` and `WebViewExtDarwin::remove_data_store`.
51 changes: 44 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1391,14 +1391,14 @@ impl<'a> WebViewBuilder<'a> {
}
}

#[cfg(any(target_os = "macos", target_os = "ios",))]
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[derive(Clone, Default)]
pub(crate) struct PlatformSpecificWebViewAttributes {
data_store_identifier: Option<[u8; 16]>,
traffic_light_inset: Option<dpi::Position>,
}

#[cfg(any(target_os = "macos", target_os = "ios",))]
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub trait WebViewBuilderExtDarwin {
/// Initialize the WebView with a custom data store identifier.
/// Can be used as a replacement for data_directory not being available in WKWebView.
Expand All @@ -1415,7 +1415,7 @@ pub trait WebViewBuilderExtDarwin {
fn with_traffic_light_inset<P: Into<dpi::Position>>(self, position: P) -> Self;
}

#[cfg(any(target_os = "macos", target_os = "ios",))]
#[cfg(any(target_os = "macos", target_os = "ios"))]
impl WebViewBuilderExtDarwin for WebViewBuilder<'_> {
fn with_data_store_identifier(self, identifier: [u8; 16]) -> Self {
self.and_then(|mut b| {
Expand All @@ -1432,9 +1432,6 @@ impl WebViewBuilderExtDarwin for WebViewBuilder<'_> {
}
}

#[cfg(any(target_os = "macos", target_os = "ios",))]
pub use wkwebview::data_store::{fetch_all_data_store_identifiers, remove_data_store};

#[cfg(windows)]
#[derive(Clone)]
pub(crate) struct PlatformSpecificWebViewAttributes {
Expand Down Expand Up @@ -2083,6 +2080,46 @@ impl WebViewExtUnix for WebView {
}
}

/// Additional methods on `WebView` that are specific to macOS or iOS.
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub trait WebViewExtDarwin {
/// Prints with extra options
fn print_with_options(&self, options: &PrintOptions) -> Result<()>;
/// Move the window controls to the specified position.
/// Normally this is handled by the Window but because `WebViewBuilder::build()` overwrites the window's NSView the controls will flicker on resizing.
/// Note: This method has no effects if the WebView is injected via `WebViewBuilder::build_as_child();` and there should be no flickers.
/// Warning: Do not use this if your chosen window library does not support traffic light insets.
/// Warning: Only use this in **decorated** windows with a **hidden titlebar**!
fn set_traffic_light_inset<P: Into<dpi::Position>>(&self, position: P) -> Result<()>;
/// Fetches all Data Store Identifiers of this application
///
/// Needs to run on main thread and needs an event loop to run.
fn fetch_data_store_identifiers() -> Result<Vec<[u8; 16]>>;
/// Deletes a Data Store by an identifier
///
/// Needs to run on main thread and needs an event loop to run.
fn remove_data_store(uuid: &[u8; 16]) -> Result<()>;
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
impl WebViewExtDarwin for WebView {
fn print_with_options(&self, options: &PrintOptions) -> Result<()> {
self.webview.print_with_options(options)
}

fn set_traffic_light_inset<P: Into<dpi::Position>>(&self, position: P) -> Result<()> {
self.webview.set_traffic_light_inset(position.into())
}

fn fetch_data_store_identifiers() -> Result<Vec<[u8; 16]>> {
wkwebview::InnerWebView::fetch_all_data_store_identifiers()
}

fn remove_data_store(uuid: &[u8; 16]) -> Result<()> {
wkwebview::InnerWebView::remove_data_store(uuid)
}
}

/// Additional methods on `WebView` that are specific to macOS.
#[cfg(target_os = "macos")]
pub trait WebViewExtMacOS {
Expand All @@ -2094,7 +2131,7 @@ pub trait WebViewExtMacOS {
fn ns_window(&self) -> Retained<NSWindow>;
/// Attaches this webview to the given NSWindow and removes it from the current one.
fn reparent(&self, window: *mut NSWindow) -> Result<()>;
// Prints with extra options
/// Prints with extra options
fn print_with_options(&self, options: &PrintOptions) -> Result<()>;
/// Move the window controls to the specified position.
/// Normally this is handled by the Window but because `WebViewBuilder::build()` overwrites the window's NSView the controls will flicker on resizing.
Expand Down
57 changes: 0 additions & 57 deletions src/wkwebview/data_store.rs

This file was deleted.

47 changes: 44 additions & 3 deletions src/wkwebview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

#[cfg(target_os = "macos")]
pub(crate) mod data_store;

mod download;
#[cfg(target_os = "macos")]
mod drag_drop;
Expand Down Expand Up @@ -998,6 +995,50 @@ r#"Object.defineProperty(window, 'ipc', {

Ok(())
}

/// Fetches all Data Store Identifiers of this application
///
/// Needs to run on main thread and needs an event loop to run.
pub fn fetch_all_data_store_identifiers() -> crate::Result<Vec<[u8; 16]>> {
let mtm = MainThreadMarker::new().ok_or(Error::NotMainThread)?;
let (tx, rx) = std::sync::mpsc::channel();

let block = block2::RcBlock::new(move |stores: NonNull<NSArray<NSUUID>>| {
let uuid_list = unsafe { stores.as_ref() }
.to_vec()
.iter()
.map(|uuid| uuid.as_bytes())
.collect::<Vec<_>>();
let _ = tx.send(uuid_list);
});
unsafe {
WKWebsiteDataStore::fetchAllDataStoreIdentifiers(&block, mtm);
wait_for_blocking_operation(rx)
}
}

/// Deletes a Data Store by an identifier
///
/// Needs to run on main thread and needs an event loop to run.
pub fn remove_data_store(uuid: &[u8; 16]) -> crate::Result<()> {
let (tx, rx) = std::sync::mpsc::channel();

let mtm = MainThreadMarker::new().ok_or(Error::NotMainThread)?;
let identifier = NSUUID::from_bytes(uuid.to_owned());

let block = block2::RcBlock::new(move |error: *mut NSError| {
if error.is_null() {
let _ = tx.send(Ok(()));
} else {
let _ = tx.send(Err(unsafe { error.read() }.into()));
}
});

unsafe {
WKWebsiteDataStore::removeDataStoreForIdentifier_completionHandler(&identifier, &block, mtm);
wait_for_blocking_operation(rx)?
}
}
}

pub fn url_from_webview(webview: &WKWebView) -> Result<String> {
Expand Down

0 comments on commit 4214f70

Please # to comment.