Skip to content

Commit

Permalink
feat(macos): add option to set a DataStoreIdentifier for WKWebView (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
santikid authored Apr 30, 2024
1 parent 8bbc2bf commit 21dc850
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 8 deletions.
34 changes: 32 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,38 @@ impl<'a> WebViewBuilder<'a> {
}
}

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

#[cfg(any(target_os = "macos", target_os = "ios",))]
impl Default for PlatformSpecificWebViewAttributes {
fn default() -> Self {
Self {
data_store_identifier: None,
}
}
}

#[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.
///
/// - **macOS / iOS**: Available on macOS >= 14 and iOS >= 17
fn with_data_store_identifier(self, identifier: [u8; 16]) -> Self;
}

#[cfg(any(target_os = "macos", target_os = "ios",))]
impl WebViewBuilderExtDarwin for WebViewBuilder<'_> {
fn with_data_store_identifier(mut self, identifier: [u8; 16]) -> Self {
self.platform_specific.data_store_identifier = Some(identifier);
self
}
}

#[cfg(windows)]
#[derive(Clone)]
pub(crate) struct PlatformSpecificWebViewAttributes {
Expand Down Expand Up @@ -1653,8 +1685,6 @@ pub enum PageLoadEvent {
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "ios",
target_os = "macos",
))]
#[derive(Default)]
pub(crate) struct PlatformSpecificWebViewAttributes;
Expand Down
44 changes: 38 additions & 6 deletions src/wkwebview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ impl InnerWebView {
fn new_ns_view(
ns_view: id,
attributes: WebViewAttributes,
_pl_attrs: super::PlatformSpecificWebViewAttributes,
pl_attrs: super::PlatformSpecificWebViewAttributes,
_web_context: Option<&mut WebContext>,
is_child: bool,
) -> Result<Self> {
Expand Down Expand Up @@ -332,11 +332,28 @@ impl InnerWebView {
let config: id = msg_send![class!(WKWebViewConfiguration), new];
let mut protocol_ptrs = Vec::new();

// Incognito mode
let data_store: id = if attributes.incognito {
msg_send![class!(WKWebsiteDataStore), nonPersistentDataStore]
} else {
msg_send![class!(WKWebsiteDataStore), defaultDataStore]
let os_version = util::operating_system_version();

#[cfg(target_os = "macos")]
let custom_data_store_available = os_version.0 >= 14;

#[cfg(target_os = "ios")]
let custom_data_store_available = os_version.0 >= 17;

let data_store: id = match (
attributes.incognito,
custom_data_store_available,
pl_attrs.data_store_identifier,
) {
// incognito has priority
(true, _, _) => msg_send![class!(WKWebsiteDataStore), nonPersistentDataStore],
// if data_store_identifier is given and custom data stores are available, use custom store
(false, true, Some(data_store)) => {
let ns_uuid = NSUUID::new(&data_store);
msg_send![class!(WKWebsiteDataStore), dataStoreForIdentifier:ns_uuid.0]
}
// default data store
_ => msg_send![class!(WKWebsiteDataStore), defaultDataStore],
};

for (name, function) in attributes.custom_protocols {
Expand Down Expand Up @@ -1321,6 +1338,21 @@ impl Drop for InnerWebView {

const UTF8_ENCODING: usize = 4;

struct NSUUID(id);

impl NSUUID {
fn new(data: &[u8; 16]) -> Self {
NSUUID(unsafe {
let ns_uuid: id = msg_send![class!(NSUUID), alloc];
let ns_uuid: id = msg_send![ns_uuid, initWithUUIDBytes:data.as_ptr()];

let _: () = msg_send![ns_uuid, autorelease];

ns_uuid
})
}
}

struct NSString(id);

impl NSString {
Expand Down
13 changes: 13 additions & 0 deletions src/wkwebview/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

use cocoa::{base::id, foundation::NSOperatingSystemVersion};
use std::sync::atomic::{AtomicU32, Ordering};

pub struct Counter(AtomicU32);
Expand All @@ -16,3 +17,15 @@ impl Counter {
self.0.fetch_add(1, Ordering::Relaxed)
}
}

pub fn operating_system_version() -> (u64, u64, u64) {
unsafe {
let process_info: id = msg_send![class!(NSProcessInfo), processInfo];
let version: NSOperatingSystemVersion = msg_send![process_info, operatingSystemVersion];
(
version.majorVersion,
version.minorVersion,
version.patchVersion,
)
}
}

0 comments on commit 21dc850

Please sign in to comment.