Skip to content

Commit

Permalink
feat: Add a way to launch WebViews as incognito `WebView::as_incognit…
Browse files Browse the repository at this point in the history
…o`, closes #908 (#916)

* impl Incognito for WebKitGTK and WebView2

* Fix broken commit

* i hate objc

* Mark Android as unsupported

* fix broken webview2 module

* better example

* example currently broken

* forgot change file

* update

* Fix WebKitGTK

* Share same code when creating context

* Cargo fmt

* Clean gitignore

* Simply more code

* Small patches to WKWebView, thank you pewsheen!

* Fix example on Windows

* Fix an oversight on WKWebView

* Fix webkit2gtk implementation

* Rename to with_incognito

* Fix WKWebView type annotations

* Fix warnings on wkwebview

* Remove examples

We can test with existing sites instead.

* Update docs

* Cargo fmt

---------

Co-authored-by: Wu Yu Wei <[email protected]>
Co-authored-by: Wu Wayne <[email protected]>
  • Loading branch information
3 people authored Apr 6, 2023
1 parent 1daccc9 commit 8698836
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changes/as_incognito.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": patch
---

Adds a way to launch a WebView as incognito through a new API at WebViewBuilder named as `with_incognito`.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ Cargo.lock
gh-pages
.DS_Store
examples/test_video.mp4
.vscode/
.vscode/
3 changes: 2 additions & 1 deletion examples/hello_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ fn main() -> wry::Result<()> {
.with_title("Hello World")
.build(&event_loop)?;
let _webview = WebViewBuilder::new(window)?
.with_url("https://html5test.com")?
.with_url("https://www.netflix.com/browse")?
// .with_incognito(true)
.build()?;

event_loop.run(move |event, _, control_flow| {
Expand Down
20 changes: 20 additions & 0 deletions src/webview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,14 @@ pub struct WebViewAttributes {
/// Set a handler closure to process the change of the webview's document title.
pub document_title_changed_handler: Option<Box<dyn Fn(&Window, String)>>,

/// Run the WebView with incognito mode. Note that WebContext will be ingored if incognito is
/// enabled.
///
/// ## Platform-specific:
///
/// - **Android:** Unsupported yet.
pub incognito: bool,

/// Whether all media can be played without user interaction.
pub autoplay: bool,
}
Expand Down Expand Up @@ -259,6 +267,7 @@ impl Default for WebViewAttributes {
accept_first_mouse: false,
back_forward_navigation_gestures: false,
document_title_changed_handler: None,
incognito: false,
autoplay: true,
}
}
Expand Down Expand Up @@ -625,6 +634,17 @@ impl<'a> WebViewBuilder<'a> {
self
}

/// Run the WebView with incognito mode. Note that WebContext will be ingored if incognito is
/// enabled.
///
/// ## Platform-specific:
///
/// - **Android:** Unsupported yet.
pub fn with_incognito(mut self, incognito: bool) -> Self {
self.webview.incognito = incognito;
self
}

/// Consume the builder and create the [`WebView`].
///
/// Platform-specific behavior:
Expand Down
13 changes: 13 additions & 0 deletions src/webview/web_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ impl WebContext {
Self { data, os }
}

#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
pub(crate) fn new_ephemeral() -> Self {
let data = WebContextData::default();
let os = WebContextImpl::new_ephemeral();
Self { data, os }
}

/// A reference to the data directory the context was created with.
pub fn data_directory(&self) -> Option<&Path> {
self.data.data_directory()
Expand Down
22 changes: 13 additions & 9 deletions src/webview/webkitgtk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use std::{
};
use url::Url;
use webkit2gtk::{
traits::*, AutoplayPolicy, LoadEvent, NavigationPolicyDecision, PolicyDecisionType, URIRequest,
UserContentInjectedFrames, UserScript, UserScriptInjectionTime, WebView, WebViewBuilder,
WebsitePoliciesBuilder,
traits::*, AutoplayPolicy, LoadEvent, NavigationPolicyDecision, PolicyDecisionType, SettingsExt,
URIRequest, UserContentInjectedFrames, UserScript, UserScriptInjectionTime, WebView,
WebViewBuilder, WebsitePoliciesBuilder,
};
use webkit2gtk_sys::{
webkit_get_major_version, webkit_get_micro_version, webkit_get_minor_version,
Expand Down Expand Up @@ -58,11 +58,16 @@ impl InnerWebView {

// default_context allows us to create a scoped context on-demand
let mut default_context;
let web_context = match web_context {
Some(w) => w,
None => {
default_context = Default::default();
&mut default_context
let web_context = if attributes.incognito {
default_context = WebContext::new_ephemeral();
&mut default_context
} else {
match web_context {
Some(w) => w,
None => {
default_context = Default::default();
&mut default_context
}
}
};

Expand All @@ -88,7 +93,6 @@ impl InnerWebView {
let w = window_rc.clone();
let ipc_handler = attributes.ipc_handler.take();
let manager = web_context.manager();

// Use the window hash as the script handler name to prevent from conflict when sharing same
// web context.
let window_hash = {
Expand Down
14 changes: 11 additions & 3 deletions src/webview/webkitgtk/web_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ pub struct WebContextImpl {

impl WebContextImpl {
pub fn new(data: &WebContextData) -> Self {
use webkit2gtk::traits::*;

let mut context_builder = WebContextBuilder::new();
if let Some(data_directory) = data.data_directory() {
let data_manager = WebsiteDataManagerBuilder::new()
Expand All @@ -58,9 +56,19 @@ impl WebContextImpl {
}
context_builder = context_builder.website_data_manager(&data_manager);
}

let context = context_builder.build();

Self::create_context(context)
}

pub fn new_ephemeral() -> Self {
let context = WebContext::new_ephemeral();

Self::create_context(context)
}

pub fn create_context(context: WebContext) -> Self {
use webkit2gtk::traits::*;
let automation = false;
context.set_automation_allowed(automation);

Expand Down
10 changes: 7 additions & 3 deletions src/webview/webview2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl InnerWebView {
let file_drop_window = window.clone();

let env = Self::create_environment(&web_context, pl_attrs.clone(), attributes.autoplay)?;
let controller = Self::create_controller(hwnd, &env)?;
let controller = Self::create_controller(hwnd, &env, attributes.incognito)?;
let webview = Self::init_webview(window, hwnd, attributes, &env, &controller, pl_attrs)?;

if let Some(file_drop_handler) = file_drop_handler {
Expand Down Expand Up @@ -173,14 +173,18 @@ impl InnerWebView {
fn create_controller(
hwnd: HWND,
env: &ICoreWebView2Environment,
incognito: bool,
) -> webview2_com::Result<ICoreWebView2Controller> {
let (tx, rx) = mpsc::channel();
let env = env.clone();
let env = env.clone().cast::<ICoreWebView2Environment10>()?;
let controller_opts = unsafe { env.CreateCoreWebView2ControllerOptions()? };

unsafe { controller_opts.SetIsInPrivateModeEnabled(incognito)? }

CreateCoreWebView2ControllerCompletedHandler::wait_for_async_operation(
Box::new(move |handler| unsafe {
env
.CreateCoreWebView2Controller(hwnd, &handler)
.CreateCoreWebView2ControllerWithOptions(hwnd, &controller_opts, &handler)
.map_err(webview2_com::Error::WindowsError)
}),
Box::new(move |error_code, controller| {
Expand Down
9 changes: 9 additions & 0 deletions src/webview/wkwebview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,14 @@ impl InnerWebView {
// Config and custom protocol
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]
};

for (name, function) in attributes.custom_protocols {
let scheme_name = format!("{}URLSchemeHandler", name);
let cls = ClassDecl::new(&scheme_name, class!(NSObject));
Expand Down Expand Up @@ -299,6 +307,7 @@ impl InnerWebView {
_ => class!(WryWebView),
};
let webview: id = msg_send![cls, alloc];
let () = msg_send![config, setWebsiteDataStore: data_store];
let _preference: id = msg_send![config, preferences];
let _yes: id = msg_send![class!(NSNumber), numberWithBool:1];

Expand Down

0 comments on commit 8698836

Please sign in to comment.