Skip to content

Commit 8cc2a7f

Browse files
refactor!: add webview id to protocol handlers and improve API ergonomics (tauri-apps#1384)
* refactor!: add webview id to protocol handlers and improve API ergonomics * try to fix macos * fix macos impl * fix doctests * generated id instead of defaulting to None * update change file * fix macos * clone * ios * typos * fix replace --------- Co-authored-by: Lucas Nogueira <[email protected]>
1 parent b01eac3 commit 8cc2a7f

28 files changed

+874
-599
lines changed

.changes/custom-protocol-label.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
"wry": "minor"
3+
---
4+
5+
This release contains quite the breaking changes, because even though [email protected], ignored duplicate custom protocols, On Linux when using a shared web context, the custom protocol handler can only be registered once so we are bringing the duplicate custom protocols on Linux again, Windows and macOS are not affected. If using a shared web context, make sure to register a protocol only once on Linux (other platforms should be registed multiple times), use `WebContext::is_custom_protocol_registered` with `#[cfg(target_os = "linux")]`.
6+
7+
We also noticed that it is hard to know which webview made a request to the custom protocol so we added a method to attach an ID to a webview, and changed relevant custom protocol APIs to take a new argument that passes the specified id back to protocol handler.
8+
9+
We also made a few changes to the builder, specifically `WebViewBuilder::new` and `WebViewBuilder::build` methods to make them more ergonomic to work with.
10+
11+
- Added `Error::DuplicateCustomProtocol` enum variant.
12+
- Added `Error::ContextDuplicateCustomProtocol` enum variant.
13+
- On Linux, return an error in `WebViewBuilder::build` if registering a custom protocol multiple times.
14+
- Added `WebContext::is_custom_protocol_registered` to check if a protocol has been regsterd for this web context.
15+
- Added `WebViewId` alias type.
16+
- **Breaking** Changed `WebViewAttributes` to have a lifetime parameter.
17+
- Added `WebViewAttributes.id` field to specify an id for the webview.
18+
- Added `WebViewBuilder::with_id` method to specify an id for the webview.
19+
- Added `WebViewAttributes.context` field to specify a shared context for the webview.
20+
- **Breaking** Changed `WebViewAttributes.custom_protocols` field,`WebViewBuilder::with_custom_protocol` method and `WebViewBuilder::with_asynchronous_custom_protocol` method handler function to take `WebViewId` as the first argument to check which webview made the request to the protocol.
21+
- **Breaking** Changed `WebViewBuilder::with_web_context` to be a static method to create a builder with a webcontext, instead of it being a setter method. It is now an alternative to `WebviewBuilder::new`
22+
- Added `WebViewBuilder::with_attributes` to create a webview builder with provided attributes.
23+
- **Breaking** Changed `WebViewBuilder::new` to take no arguments.
24+
- **Breaking** Changed `WebViewBuilder::build` method to take a reference to a window to create the webview in it.
25+
- **Breaking** Removed `WebViewBuilder::new_as_child`.
26+
- Added `WebViewBuilder::build_as_child` method, which takes a reference to a window to create the webview in it.
27+
- **Breaking** Removed `WebViewBuilderExtUnix::new_gtk`.
28+
- Added `WebViewBuilderExtUnix::build_gtk`.

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ fn main() -> wry::Result<()> {
4040
.with_title("Hello World")
4141
.build(&event_loop)
4242
.unwrap();
43-
let _webview = WebViewBuilder::new(&window)
43+
44+
let webview = WebViewBuilder::new()
4445
.with_url("https://tauri.app")
45-
.build()?;
46+
.build(&window)?;
4647

4748
event_loop.run(move |event, _, control_flow| {
4849
*control_flow = ControlFlow::Wait;

examples/async_custom_protocol.rs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,42 +18,41 @@ fn main() -> wry::Result<()> {
1818
let event_loop = EventLoop::new();
1919
let window = WindowBuilder::new().build(&event_loop).unwrap();
2020

21+
let builder = WebViewBuilder::new()
22+
.with_asynchronous_custom_protocol("wry".into(), move |_webview_id, request, responder| {
23+
match get_wry_response(request) {
24+
Ok(http_response) => responder.respond(http_response),
25+
Err(e) => responder.respond(
26+
http::Response::builder()
27+
.header(CONTENT_TYPE, "text/plain")
28+
.status(500)
29+
.body(e.to_string().as_bytes().to_vec())
30+
.unwrap(),
31+
),
32+
}
33+
})
34+
// tell the webview to load the custom protocol
35+
.with_url("wry://localhost");
36+
2137
#[cfg(any(
2238
target_os = "windows",
2339
target_os = "macos",
2440
target_os = "ios",
2541
target_os = "android"
2642
))]
27-
let builder = WebViewBuilder::new(&window);
28-
43+
let _webview = builder.build(&window)?;
2944
#[cfg(not(any(
3045
target_os = "windows",
3146
target_os = "macos",
3247
target_os = "ios",
3348
target_os = "android"
3449
)))]
35-
let builder = {
50+
let _webview = {
3651
use tao::platform::unix::WindowExtUnix;
3752
use wry::WebViewBuilderExtUnix;
3853
let vbox = window.default_vbox().unwrap();
39-
WebViewBuilder::new_gtk(vbox)
54+
builder.build_gtk(vbox)?
4055
};
41-
let _webview = builder
42-
.with_asynchronous_custom_protocol("wry".into(), move |request, responder| {
43-
match get_wry_response(request) {
44-
Ok(http_response) => responder.respond(http_response),
45-
Err(e) => responder.respond(
46-
http::Response::builder()
47-
.header(CONTENT_TYPE, "text/plain")
48-
.status(500)
49-
.body(e.to_string().as_bytes().to_vec())
50-
.unwrap(),
51-
),
52-
}
53-
})
54-
// tell the webview to load the custom protocol
55-
.with_url("wry://localhost")
56-
.build()?;
5756

5857
event_loop.run(move |event, _, control_flow| {
5958
*control_flow = ControlFlow::Wait;

examples/custom_protocol.rs

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,42 +18,81 @@ fn main() -> wry::Result<()> {
1818
let event_loop = EventLoop::new();
1919
let window = WindowBuilder::new().build(&event_loop).unwrap();
2020

21+
let builder = WebViewBuilder::new()
22+
.with_id("id2")
23+
.with_custom_protocol(
24+
"wry".into(),
25+
move |_webview_id, request| match get_wry_response(request) {
26+
Ok(r) => r.map(Into::into),
27+
Err(e) => http::Response::builder()
28+
.header(CONTENT_TYPE, "text/plain")
29+
.status(500)
30+
.body(e.to_string().as_bytes().to_vec())
31+
.unwrap()
32+
.map(Into::into),
33+
},
34+
)
35+
// tell the webview to load the custom protocol
36+
.with_url("wry://localhost");
37+
2138
#[cfg(any(
2239
target_os = "windows",
2340
target_os = "macos",
2441
target_os = "ios",
2542
target_os = "android"
2643
))]
27-
let builder = WebViewBuilder::new(&window);
28-
44+
let _webview = builder.build(&window)?;
2945
#[cfg(not(any(
3046
target_os = "windows",
3147
target_os = "macos",
3248
target_os = "ios",
3349
target_os = "android"
3450
)))]
35-
let builder = {
51+
let _webview = {
3652
use tao::platform::unix::WindowExtUnix;
3753
use wry::WebViewBuilderExtUnix;
3854
let vbox = window.default_vbox().unwrap();
39-
WebViewBuilder::new_gtk(vbox)
55+
builder.build_gtk(vbox)?
4056
};
4157

42-
let _webview = builder
43-
.with_custom_protocol("wry".into(), move |request| {
44-
match get_wry_response(request) {
58+
let window = WindowBuilder::new().build(&event_loop).unwrap();
59+
60+
let builder = WebViewBuilder::new()
61+
.with_id("id1")
62+
.with_custom_protocol(
63+
"wry".into(),
64+
move |_webview_id, request| match get_wry_response(request) {
4565
Ok(r) => r.map(Into::into),
4666
Err(e) => http::Response::builder()
4767
.header(CONTENT_TYPE, "text/plain")
4868
.status(500)
4969
.body(e.to_string().as_bytes().to_vec())
5070
.unwrap()
5171
.map(Into::into),
52-
}
53-
})
72+
},
73+
)
5474
// tell the webview to load the custom protocol
55-
.with_url("wry://localhost")
56-
.build()?;
75+
.with_url("wry://localhost");
76+
77+
#[cfg(any(
78+
target_os = "windows",
79+
target_os = "macos",
80+
target_os = "ios",
81+
target_os = "android"
82+
))]
83+
let _webview = builder.build(&window)?;
84+
#[cfg(not(any(
85+
target_os = "windows",
86+
target_os = "macos",
87+
target_os = "ios",
88+
target_os = "android"
89+
)))]
90+
let _webview = {
91+
use tao::platform::unix::WindowExtUnix;
92+
use wry::WebViewBuilderExtUnix;
93+
let vbox = window.default_vbox().unwrap();
94+
builder.build_gtk(vbox)?
95+
};
5796

5897
event_loop.run(move |event, _, control_flow| {
5998
*control_flow = ControlFlow::Wait;

examples/custom_titlebar.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -241,34 +241,32 @@ fn main() -> wry::Result<()> {
241241
}
242242
};
243243

244+
let builder = WebViewBuilder::new()
245+
.with_html(HTML)
246+
.with_ipc_handler(handler)
247+
.with_accept_first_mouse(true);
248+
244249
#[cfg(any(
245250
target_os = "windows",
246251
target_os = "macos",
247252
target_os = "ios",
248253
target_os = "android"
249254
))]
250-
let builder = WebViewBuilder::new(&window);
251-
255+
let webview = builder.build(&window)?;
252256
#[cfg(not(any(
253257
target_os = "windows",
254258
target_os = "macos",
255259
target_os = "ios",
256260
target_os = "android"
257261
)))]
258-
let builder = {
262+
let webview = {
259263
use tao::platform::unix::WindowExtUnix;
260264
use wry::WebViewBuilderExtUnix;
261265
let vbox = window.default_vbox().unwrap();
262-
WebViewBuilder::new_gtk(vbox)
266+
builder.build_gtk(vbox)?
263267
};
264268

265-
let mut webview = Some(
266-
builder
267-
.with_html(HTML)
268-
.with_ipc_handler(handler)
269-
.with_accept_first_mouse(true)
270-
.build()?,
271-
);
269+
let mut webview = Some(webview);
272270

273271
event_loop.run(move |event, _, control_flow| {
274272
*control_flow = ControlFlow::Wait;

examples/gtk_multiwebview.rs

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,74 +16,69 @@ fn main() -> wry::Result<()> {
1616
let event_loop = EventLoop::new();
1717
let window = WindowBuilder::new().build(&event_loop).unwrap();
1818

19-
#[cfg(not(any(
20-
target_os = "windows",
21-
target_os = "macos",
22-
target_os = "ios",
23-
target_os = "android"
24-
)))]
25-
let fixed = {
26-
use gtk::prelude::*;
27-
use tao::platform::unix::WindowExtUnix;
28-
29-
let fixed = gtk::Fixed::new();
30-
let vbox = window.default_vbox().unwrap();
31-
vbox.pack_start(&fixed, true, true, 0);
32-
fixed.show_all();
33-
fixed
34-
};
35-
36-
let create_webview_builder = || {
19+
let build_webview = |builder: WebViewBuilder<'_>| -> wry::Result<wry::WebView> {
3720
#[cfg(any(
3821
target_os = "windows",
3922
target_os = "macos",
4023
target_os = "ios",
4124
target_os = "android"
4225
))]
43-
return WebViewBuilder::new_as_child(&window);
26+
let webview = builder.build(&window)?;
4427

4528
#[cfg(not(any(
4629
target_os = "windows",
4730
target_os = "macos",
4831
target_os = "ios",
4932
target_os = "android"
5033
)))]
51-
{
34+
let webview = {
35+
use gtk::prelude::*;
36+
use tao::platform::unix::WindowExtUnix;
5237
use wry::WebViewBuilderExtUnix;
53-
WebViewBuilder::new_gtk(&fixed)
54-
}
38+
39+
let fixed = gtk::Fixed::new();
40+
let vbox = window.default_vbox().unwrap();
41+
vbox.pack_start(&fixed, true, true, 0);
42+
fixed.show_all();
43+
builder.build_gtk(&fixed)?
44+
};
45+
46+
Ok(webview)
5547
};
5648

5749
let size = window.inner_size().to_logical::<u32>(window.scale_factor());
5850

59-
let webview = create_webview_builder()
51+
let builder = WebViewBuilder::new()
6052
.with_bounds(Rect {
6153
position: LogicalPosition::new(0, 0).into(),
6254
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
6355
})
64-
.with_url("https://tauri.app")
65-
.build()?;
66-
let webview2 = create_webview_builder()
56+
.with_url("https://tauri.app");
57+
let webview = build_webview(builder)?;
58+
59+
let builder2 = WebViewBuilder::new()
6760
.with_bounds(Rect {
6861
position: LogicalPosition::new(size.width / 2, 0).into(),
6962
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
7063
})
71-
.with_url("https://github.com/tauri-apps/wry")
72-
.build()?;
73-
let webview3 = create_webview_builder()
64+
.with_url("https://github.com/tauri-apps/wry");
65+
let webview2 = build_webview(builder2)?;
66+
67+
let builder3 = WebViewBuilder::new()
7468
.with_bounds(Rect {
7569
position: LogicalPosition::new(0, size.height / 2).into(),
7670
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
7771
})
78-
.with_url("https://twitter.com/TauriApps")
79-
.build()?;
80-
let webview4 = create_webview_builder()
72+
.with_url("https://twitter.com/TauriApps");
73+
let webview3 = build_webview(builder3)?;
74+
75+
let builder4 = WebViewBuilder::new()
8176
.with_bounds(Rect {
8277
position: LogicalPosition::new(size.width / 2, size.height / 2).into(),
8378
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
8479
})
85-
.with_url("https://google.com")
86-
.build()?;
80+
.with_url("https://google.com");
81+
let webview4 = build_webview(builder4)?;
8782

8883
event_loop.run(move |event, _, control_flow| {
8984
*control_flow = ControlFlow::Wait;

examples/multiwebview.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,34 +44,34 @@ fn main() -> wry::Result<()> {
4444

4545
let size = window.inner_size().to_logical::<u32>(window.scale_factor());
4646

47-
let webview = WebViewBuilder::new_as_child(&window)
47+
let webview = WebViewBuilder::new()
4848
.with_bounds(Rect {
4949
position: LogicalPosition::new(0, 0).into(),
5050
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
5151
})
5252
.with_url("https://tauri.app")
53-
.build()?;
54-
let webview2 = WebViewBuilder::new_as_child(&window)
53+
.build(&window)?;
54+
let webview2 = WebViewBuilder::new()
5555
.with_bounds(Rect {
5656
position: LogicalPosition::new(size.width / 2, 0).into(),
5757
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
5858
})
5959
.with_url("https://github.com/tauri-apps/wry")
60-
.build()?;
61-
let webview3 = WebViewBuilder::new_as_child(&window)
60+
.build(&window)?;
61+
let webview3 = WebViewBuilder::new()
6262
.with_bounds(Rect {
6363
position: LogicalPosition::new(0, size.height / 2).into(),
6464
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
6565
})
6666
.with_url("https://twitter.com/TauriApps")
67-
.build()?;
68-
let webview4 = WebViewBuilder::new_as_child(&window)
67+
.build(&window)?;
68+
let webview4 = WebViewBuilder::new()
6969
.with_bounds(Rect {
7070
position: LogicalPosition::new(size.width / 2, size.height / 2).into(),
7171
size: LogicalSize::new(size.width / 2, size.height / 2).into(),
7272
})
7373
.with_url("https://google.com")
74-
.build()?;
74+
.build(&window)?;
7575

7676
event_loop
7777
.run(move |event, evl| {

0 commit comments

Comments
 (0)