mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-01-31 00:35:19 +01:00
Add back WebDriver support (#2324)
This commit is contained in:
@@ -274,6 +274,11 @@
|
||||
"create-tauri-app": {
|
||||
"path": "./tooling/create-tauri-app",
|
||||
"manager": "javascript"
|
||||
},
|
||||
"tauri-driver": {
|
||||
"path": "./tooling/webdriver",
|
||||
"manager": "rust",
|
||||
"postversion": "node ../../.scripts/sync-prerelease.js ${ pkg.pkg } ${ release.type }"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
.changes/tauri-driver.md
Normal file
5
.changes/tauri-driver.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri-driver": minor
|
||||
---
|
||||
|
||||
Initial release including Linux and Windows support.
|
||||
5
.changes/webdriver.md
Normal file
5
.changes/webdriver.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri-runtime-wry": patch
|
||||
---
|
||||
|
||||
Add webdriver support to Tauri.
|
||||
@@ -64,9 +64,13 @@ pub use wry::application::window::{Window, WindowBuilder as WryWindowBuilder};
|
||||
use wry::webview::WebviewExtWindows;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
collections::{
|
||||
hash_map::Entry::{Occupied, Vacant},
|
||||
HashMap,
|
||||
},
|
||||
convert::TryFrom,
|
||||
fs::read,
|
||||
path::PathBuf,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
mpsc::{channel, Sender},
|
||||
@@ -83,6 +87,7 @@ use menu::*;
|
||||
mod mime_type;
|
||||
use mime_type::MimeType;
|
||||
|
||||
type WebContextStore = Mutex<HashMap<Option<PathBuf>, WebContext>>;
|
||||
type WindowEventHandler = Box<dyn Fn(&WindowEvent) + Send>;
|
||||
type WindowEventListenersMap = Arc<Mutex<HashMap<Uuid, WindowEventHandler>>>;
|
||||
type WindowEventListeners = Arc<Mutex<HashMap<WindowId, WindowEventListenersMap>>>;
|
||||
@@ -752,7 +757,9 @@ pub(crate) enum Message {
|
||||
#[cfg(feature = "system-tray")]
|
||||
Tray(TrayMessage),
|
||||
CreateWebview(
|
||||
Box<dyn FnOnce(&EventLoopWindowTarget<Message>) -> Result<WindowWrapper> + Send>,
|
||||
Box<
|
||||
dyn FnOnce(&EventLoopWindowTarget<Message>, &WebContextStore) -> Result<WindowWrapper> + Send,
|
||||
>,
|
||||
Sender<WindowId>,
|
||||
),
|
||||
CreateWindow(
|
||||
@@ -956,7 +963,9 @@ impl Dispatch for WryDispatcher {
|
||||
.context
|
||||
.proxy
|
||||
.send_event(Message::CreateWebview(
|
||||
Box::new(move |event_loop| create_webview(event_loop, context, pending)),
|
||||
Box::new(move |event_loop, web_context| {
|
||||
create_webview(event_loop, web_context, context, pending)
|
||||
}),
|
||||
tx,
|
||||
))
|
||||
.map_err(|_| Error::FailedToSendMessage)?;
|
||||
@@ -1243,6 +1252,7 @@ pub struct Wry {
|
||||
is_event_loop_running: Arc<AtomicBool>,
|
||||
event_loop: EventLoop<Message>,
|
||||
windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
|
||||
web_context: WebContextStore,
|
||||
window_event_listeners: WindowEventListeners,
|
||||
#[cfg(feature = "menu")]
|
||||
menu_event_listeners: MenuEventListeners,
|
||||
@@ -1288,7 +1298,9 @@ impl RuntimeHandle for WryHandle {
|
||||
.dispatcher_context
|
||||
.proxy
|
||||
.send_event(Message::CreateWebview(
|
||||
Box::new(move |event_loop| create_webview(event_loop, dispatcher_context, pending)),
|
||||
Box::new(move |event_loop, web_context| {
|
||||
create_webview(event_loop, web_context, dispatcher_context, pending)
|
||||
}),
|
||||
tx,
|
||||
))
|
||||
.map_err(|_| Error::FailedToSendMessage)?;
|
||||
@@ -1348,6 +1360,7 @@ impl Runtime for Wry {
|
||||
is_event_loop_running,
|
||||
event_loop,
|
||||
windows: Default::default(),
|
||||
web_context: Default::default(),
|
||||
window_event_listeners: Default::default(),
|
||||
#[cfg(feature = "menu")]
|
||||
menu_event_listeners: Default::default(),
|
||||
@@ -1382,6 +1395,7 @@ impl Runtime for Wry {
|
||||
let proxy = self.event_loop.create_proxy();
|
||||
let webview = create_webview(
|
||||
&self.event_loop,
|
||||
&self.web_context,
|
||||
DispatcherContext {
|
||||
main_thread_id: self.main_thread_id,
|
||||
is_event_loop_running: self.is_event_loop_running.clone(),
|
||||
@@ -1497,6 +1511,7 @@ impl Runtime for Wry {
|
||||
fn run_iteration<F: Fn(RunEvent) + 'static>(&mut self, callback: F) -> RunIteration {
|
||||
use wry::application::platform::run_return::EventLoopExtRunReturn;
|
||||
let windows = self.windows.clone();
|
||||
let web_context = &self.web_context;
|
||||
let window_event_listeners = self.window_event_listeners.clone();
|
||||
#[cfg(feature = "menu")]
|
||||
let menu_event_listeners = self.menu_event_listeners.clone();
|
||||
@@ -1531,6 +1546,7 @@ impl Runtime for Wry {
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_context: &tray_context,
|
||||
},
|
||||
web_context,
|
||||
);
|
||||
});
|
||||
self.is_event_loop_running.store(false, Ordering::Relaxed);
|
||||
@@ -1541,6 +1557,7 @@ impl Runtime for Wry {
|
||||
fn run<F: Fn(RunEvent) + 'static>(self, callback: F) {
|
||||
self.is_event_loop_running.store(true, Ordering::Relaxed);
|
||||
let windows = self.windows.clone();
|
||||
let web_context = self.web_context;
|
||||
let window_event_listeners = self.window_event_listeners.clone();
|
||||
#[cfg(feature = "menu")]
|
||||
let menu_event_listeners = self.menu_event_listeners.clone();
|
||||
@@ -1567,6 +1584,7 @@ impl Runtime for Wry {
|
||||
#[cfg(feature = "system-tray")]
|
||||
tray_context: &tray_context,
|
||||
},
|
||||
&web_context,
|
||||
);
|
||||
})
|
||||
}
|
||||
@@ -1590,6 +1608,7 @@ fn handle_event_loop(
|
||||
event_loop: &EventLoopWindowTarget<Message>,
|
||||
control_flow: &mut ControlFlow,
|
||||
context: EventLoopIterationContext<'_>,
|
||||
web_context: &WebContextStore,
|
||||
) -> RunIteration {
|
||||
let EventLoopIterationContext {
|
||||
callback,
|
||||
@@ -1892,7 +1911,7 @@ fn handle_event_loop(
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::CreateWebview(handler, sender) => match handler(event_loop) {
|
||||
Message::CreateWebview(handler, sender) => match handler(event_loop, web_context) {
|
||||
Ok(webview) => {
|
||||
let window_id = webview.inner.window().id();
|
||||
windows.insert(window_id, webview);
|
||||
@@ -1936,6 +1955,7 @@ fn handle_event_loop(
|
||||
sender.send(Err(Error::CreateWindow)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "system-tray")]
|
||||
Message::Tray(tray_message) => match tray_message {
|
||||
TrayMessage::UpdateItem(menu_id, update) => {
|
||||
@@ -2068,6 +2088,7 @@ fn center_window(window: &Window) -> Result<()> {
|
||||
|
||||
fn create_webview(
|
||||
event_loop: &EventLoopWindowTarget<Message>,
|
||||
web_context: &WebContextStore,
|
||||
context: DispatcherContext,
|
||||
pending: PendingWindow<Wry>,
|
||||
) -> Result<WindowWrapper> {
|
||||
@@ -2134,13 +2155,27 @@ fn create_webview(
|
||||
.map_err(|_| wry::Error::InitScriptError)
|
||||
});
|
||||
}
|
||||
let mut context = WebContext::new(webview_attributes.data_directory);
|
||||
webview_builder = webview_builder.with_web_context(&mut context);
|
||||
|
||||
for script in webview_attributes.initialization_scripts {
|
||||
webview_builder = webview_builder.with_initialization_script(&script);
|
||||
}
|
||||
|
||||
let mut web_context = web_context.lock().expect("poisoned WebContext store");
|
||||
let is_first_context = web_context.is_empty();
|
||||
let web_context = match web_context.entry(webview_attributes.data_directory) {
|
||||
Occupied(occupied) => occupied.into_mut(),
|
||||
Vacant(vacant) => {
|
||||
let mut web_context = WebContext::new(vacant.key().clone());
|
||||
web_context.set_allows_automation(match std::env::var("TAURI_AUTOMATION").as_deref() {
|
||||
Ok("true") => is_first_context,
|
||||
_ => false,
|
||||
});
|
||||
vacant.insert(web_context)
|
||||
}
|
||||
};
|
||||
|
||||
let webview = webview_builder
|
||||
.with_web_context(web_context)
|
||||
.build()
|
||||
.map_err(|e| Error::CreateWebview(Box::new(e)))?;
|
||||
|
||||
|
||||
4
tooling/webdriver/.gitignore
vendored
Normal file
4
tooling/webdriver/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/target
|
||||
.DS_Store
|
||||
*.rs.bk
|
||||
*~
|
||||
3
tooling/webdriver/.license_template
Normal file
3
tooling/webdriver/.license_template
Normal file
@@ -0,0 +1,3 @@
|
||||
// Copyright {20\d{2}(-20\d{2})?} Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
535
tooling/webdriver/Cargo.lock
generated
Normal file
535
tooling/webdriver/Cargo.lock
generated
Normal file
@@ -0,0 +1,535 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"proc-macro-hack",
|
||||
"proc-macro-nested",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3f71a7eea53a3f8257a7b4795373ff886397178cd634430ea94e12d7fe4fe34"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project",
|
||||
"socket2",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"miow",
|
||||
"ntapi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pico-args"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d7afeb98c5a10e0bffcc7fc16e105b04d06729fac5fd6384aebf7ff5cb5a67d"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-nested"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "470c5a6397076fae0094aaf06a08e6ba6f37acb77d3b1b91ea92b4d6c8650c39"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-tokio"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6c5d32165ff8b94e68e7b3bdecb1b082e958c22434b363482cfb89dcd6f3ff8"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"libc",
|
||||
"signal-hook",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-driver"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"futures",
|
||||
"hyper",
|
||||
"pico-args",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"signal-hook",
|
||||
"signal-hook-tokio",
|
||||
"tokio",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a38d31d7831c6ed7aad00aa4c12d9375fd225a6dd77da1d25b707346319a975"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libc",
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"tokio-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c49e3df43841dafb86046472506755d8501c5615673955f6aa17181125d13c37"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"pin-project-lite",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b55551e42cbdf2ce2bedd2203d0cc08dba002c27510f86dab6d0ce304cba3dfe"
|
||||
dependencies = [
|
||||
"either",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
28
tooling/webdriver/Cargo.toml
Normal file
28
tooling/webdriver/Cargo.toml
Normal file
@@ -0,0 +1,28 @@
|
||||
workspace = { }
|
||||
|
||||
[package]
|
||||
name = "tauri-driver"
|
||||
version = "0.0.0"
|
||||
authors = ["Tauri Programme within The Commons Conservancy"]
|
||||
categories = ["gui", "web-programming"]
|
||||
license = "Apache-2.0 OR MIT"
|
||||
homepage = "https://tauri.studio"
|
||||
repository = "https://github.com/tauri-apps/tauri"
|
||||
description = "Webdriver server for Tauri applications"
|
||||
readme = "README.md"
|
||||
exclude = [".license_template", "/target"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
hyper = { version = "0.14", features = [ "client", "http1", "runtime", "server", "stream", "tcp" ] }
|
||||
futures = "0.3"
|
||||
pico-args = "0.4"
|
||||
serde = { version = "1", features = [ "derive" ] }
|
||||
serde_json = "1"
|
||||
tokio = { version = "1", features = [ "macros" ] } # other required features enabled by hyper
|
||||
which = "4"
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
signal-hook = "0.3"
|
||||
signal-hook-tokio = { version = "0.3", features = [ "futures-v0_3" ] }
|
||||
1
tooling/webdriver/LICENSE.spdx
Symbolic link
1
tooling/webdriver/LICENSE.spdx
Symbolic link
@@ -0,0 +1 @@
|
||||
../../LICENSE.spdx
|
||||
1
tooling/webdriver/LICENSE_APACHE-2.0
Symbolic link
1
tooling/webdriver/LICENSE_APACHE-2.0
Symbolic link
@@ -0,0 +1 @@
|
||||
../../LICENSE_APACHE-2.0
|
||||
1
tooling/webdriver/LICENSE_MIT
Symbolic link
1
tooling/webdriver/LICENSE_MIT
Symbolic link
@@ -0,0 +1 @@
|
||||
../../LICENSE_MIT
|
||||
42
tooling/webdriver/README.md
Normal file
42
tooling/webdriver/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# `tauri-driver` _(pre-alpha)_
|
||||
|
||||
Cross-platform WebDriver server for Tauri applications.
|
||||
|
||||
This is a [WebDriver Intermediary Node] that wraps the native WebDriver server
|
||||
for platforms that [Tauri] supports. Your WebDriver client will connect to the
|
||||
running `tauri-driver` server, and `tauri-driver` will handle starting the
|
||||
native WebDriver server for you behind the scenes. It requires two separate
|
||||
ports to be used since two distinct [WebDriver Remote Ends] run.
|
||||
|
||||
You can configure the ports used with arguments when starting the binary:
|
||||
* `--port` (default: `4444`)
|
||||
* `--native-port` (default: `4445`)
|
||||
|
||||
Supported platforms:
|
||||
* **[In Progress]** Linux w/ `WebKitWebDriver`
|
||||
* **[In Progress]** Windows w/ [Microsoft Edge Driver]
|
||||
* **[Todo]** macOS w/ [Appium Mac2 Driver] (probably)
|
||||
|
||||
_note: the (probably) items haven't been proof-of-concept'd yet, and if it is
|
||||
not possible to use the listed native webdriver, then a custom implementation
|
||||
will be used that wraps around [wry]._
|
||||
|
||||
|
||||
## Trying it out
|
||||
|
||||
**Until this branch is merged into Tauri `dev`, this code works for pure [wry]
|
||||
applications only.**
|
||||
|
||||
Currently, this uses a branch on [wry] `feat/webdriver`. The support for
|
||||
automated actions goes all the way down to wry with no real layer for just
|
||||
Tauri yet. For Windows, the [wry] branch only supports the `win32` backend
|
||||
and not `winrt`, unless you are okay with the webview not being closable by
|
||||
the webdriver.
|
||||
|
||||
|
||||
[WebDriver Intermediary Node]: https://www.w3.org/TR/webdriver/#dfn-intermediary-nodes
|
||||
[WebDriver Remote Ends]: https://www.w3.org/TR/webdriver/#dfn-remote-ends
|
||||
[Microsoft Edge Driver]: https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
|
||||
[Appium Mac2 Driver]: https://github.com/appium/appium-mac2-driver
|
||||
[wry]: https://github.com/tauri-apps/wry
|
||||
[Tauri]: https://github.com/tauri-apps/tauri
|
||||
58
tooling/webdriver/src/cli.rs
Normal file
58
tooling/webdriver/src/cli.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
const HELP: &str = "\
|
||||
USAGE: tauri-driver [FLAGS] [OPTIONS]
|
||||
|
||||
FLAGS:
|
||||
-h, --help Prints help information
|
||||
|
||||
OPTIONS:
|
||||
--port NUMBER Sets the tauri-driver intermediary port
|
||||
--native-port NUMBER Sets the port of the underlying WebDriver
|
||||
--native-driver PATH Sets the path to the native WebDriver binary
|
||||
";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Args {
|
||||
pub port: u16,
|
||||
pub native_port: u16,
|
||||
pub native_driver: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl From<pico_args::Arguments> for Args {
|
||||
fn from(mut args: pico_args::Arguments) -> Self {
|
||||
// if the user wanted help, we don't care about parsing the rest of the args
|
||||
if args.contains(["-h", "--help"]) {
|
||||
println!("{}", HELP);
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
let native_driver = match args.opt_value_from_str("--native-driver") {
|
||||
Ok(native_driver) => native_driver,
|
||||
Err(e) => {
|
||||
eprintln!("Error while parsing option --native-driver: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let parsed = Args {
|
||||
port: args.value_from_str("--port").unwrap_or(4444),
|
||||
native_port: args.value_from_str("--native-port").unwrap_or(4445),
|
||||
native_driver,
|
||||
};
|
||||
|
||||
// be strict about accepting args, error for anything extraneous
|
||||
let rest = args.finish();
|
||||
if !rest.is_empty() {
|
||||
eprintln!("Error: unused arguments left: {:?}", rest);
|
||||
eprintln!("{}", HELP);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
parsed
|
||||
}
|
||||
}
|
||||
23
tooling/webdriver/src/main.rs
Normal file
23
tooling/webdriver/src/main.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
mod cli;
|
||||
mod server;
|
||||
mod webdriver;
|
||||
|
||||
fn main() {
|
||||
let args = pico_args::Arguments::from_env().into();
|
||||
|
||||
// start the native webdriver on the port specified in args
|
||||
let mut driver = webdriver::native(&args);
|
||||
let driver = driver
|
||||
.spawn()
|
||||
.expect("error while running native webdriver");
|
||||
|
||||
// start our webdriver intermediary node
|
||||
if let Err(e) = server::run(args, driver) {
|
||||
eprintln!("error while running server: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
196
tooling/webdriver/src/server.rs
Normal file
196
tooling/webdriver/src/server.rs
Normal file
@@ -0,0 +1,196 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::cli::Args;
|
||||
use anyhow::Error;
|
||||
use futures::TryFutureExt;
|
||||
use hyper::header::CONTENT_LENGTH;
|
||||
use hyper::http::uri::Authority;
|
||||
use hyper::service::{make_service_fn, service_fn};
|
||||
use hyper::{Body, Client, Method, Request, Response, Server};
|
||||
use serde::Deserialize;
|
||||
use serde_json::{json, Map, Value};
|
||||
use std::convert::Infallible;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Child;
|
||||
|
||||
type HttpClient = Client<hyper::client::HttpConnector>;
|
||||
|
||||
const TAURI_OPTIONS: &str = "tauri:options";
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct TauriOptions {
|
||||
application: PathBuf,
|
||||
}
|
||||
|
||||
impl TauriOptions {
|
||||
#[cfg(target_os = "linux")]
|
||||
fn into_native_object(self) -> Map<String, Value> {
|
||||
let mut map = Map::new();
|
||||
map.insert(
|
||||
"webkitgtk:browserOptions".into(),
|
||||
json!({"binary": self.application}),
|
||||
);
|
||||
map
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn into_native_object(self) -> Map<String, Value> {
|
||||
let mut map = Map::new();
|
||||
map.insert("ms:edgeChromium".into(), json!(true));
|
||||
map.insert("browserName".into(), json!("webview2"));
|
||||
map.insert("ms:edgeOptions".into(), json!({"binary": self.application}));
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle(
|
||||
client: HttpClient,
|
||||
mut req: Request<Body>,
|
||||
args: Args,
|
||||
) -> Result<Response<Body>, Error> {
|
||||
// manipulate a new session to convert options to the native driver format
|
||||
if let (&Method::POST, "/session") = (req.method(), req.uri().path()) {
|
||||
let (mut parts, body) = req.into_parts();
|
||||
|
||||
// get the body from the future stream and parse it as json
|
||||
let body = hyper::body::to_bytes(body).await?;
|
||||
let json: Value = serde_json::from_slice(&body)?;
|
||||
|
||||
// manipulate the json to convert from tauri option to native driver options
|
||||
let json = map_capabilities(json);
|
||||
|
||||
// serialize json and update the content-length header to be accurate
|
||||
let bytes = serde_json::to_vec(&json)?;
|
||||
parts.headers.insert(CONTENT_LENGTH, bytes.len().into());
|
||||
|
||||
req = Request::from_parts(parts, bytes.into());
|
||||
}
|
||||
|
||||
client
|
||||
.request(forward_to_native_driver(req, args)?)
|
||||
.err_into()
|
||||
.await
|
||||
}
|
||||
|
||||
/// Transform the request to a request for the native webdriver server.
|
||||
fn forward_to_native_driver(mut req: Request<Body>, args: Args) -> Result<Request<Body>, Error> {
|
||||
let host: Authority = {
|
||||
let headers = req.headers_mut();
|
||||
headers.remove("host").expect("hyper request has host")
|
||||
}
|
||||
.to_str()?
|
||||
.parse()?;
|
||||
|
||||
let path = req
|
||||
.uri()
|
||||
.path_and_query()
|
||||
.expect("hyper request has uri")
|
||||
.clone();
|
||||
|
||||
let uri = format!(
|
||||
"http://{}:{}{}",
|
||||
host.host(),
|
||||
args.native_port,
|
||||
path.as_str()
|
||||
);
|
||||
|
||||
let (mut parts, body) = req.into_parts();
|
||||
parts.uri = uri.parse()?;
|
||||
Ok(Request::from_parts(parts, body))
|
||||
}
|
||||
|
||||
/// only happy path for now, no errors
|
||||
fn map_capabilities(mut json: Value) -> Value {
|
||||
let mut native = None;
|
||||
if let Some(capabilities) = json.get_mut("capabilities") {
|
||||
if let Some(always_match) = capabilities.get_mut("alwaysMatch") {
|
||||
if let Some(always_match) = always_match.as_object_mut() {
|
||||
if let Some(tauri_options) = always_match.remove(TAURI_OPTIONS) {
|
||||
if let Ok(options) = serde_json::from_value::<TauriOptions>(tauri_options) {
|
||||
native = Some(options.into_native_object());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(native) = native.clone() {
|
||||
always_match.extend(native);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(native) = native {
|
||||
if let Some(desired) = json.get_mut("desiredCapabilities") {
|
||||
if let Some(desired) = desired.as_object_mut() {
|
||||
desired.remove(TAURI_OPTIONS);
|
||||
desired.extend(native);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
json
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
pub async fn run(args: Args, mut _driver: Child) -> Result<(), Error> {
|
||||
#[cfg(unix)]
|
||||
let (signals_handle, signals_task) = {
|
||||
use futures::StreamExt;
|
||||
use signal_hook::consts::signal::*;
|
||||
|
||||
let signals = signal_hook_tokio::Signals::new(&[SIGTERM, SIGINT, SIGQUIT])?;
|
||||
let signals_handle = signals.handle();
|
||||
let signals_task = tokio::spawn(async move {
|
||||
let mut signals = signals.fuse();
|
||||
while let Some(signal) = signals.next().await {
|
||||
match signal {
|
||||
SIGTERM | SIGINT | SIGQUIT => {
|
||||
_driver
|
||||
.kill()
|
||||
.expect("unable to kill native webdriver server");
|
||||
std::process::exit(0);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
});
|
||||
(signals_handle, signals_task)
|
||||
};
|
||||
|
||||
let address = std::net::SocketAddr::from(([127, 0, 0, 1], args.port));
|
||||
|
||||
// the client we use to proxy requests to the native webdriver
|
||||
let client = Client::builder()
|
||||
.http1_preserve_header_case(true)
|
||||
.http1_title_case_headers(true)
|
||||
.retry_canceled_requests(false)
|
||||
.build_http();
|
||||
|
||||
// pass a copy of the client to the http request handler
|
||||
let service = make_service_fn(move |_| {
|
||||
let client = client.clone();
|
||||
let args = args.clone();
|
||||
async move {
|
||||
Ok::<_, Infallible>(service_fn(move |request| {
|
||||
handle(client.clone(), request, args.clone())
|
||||
}))
|
||||
}
|
||||
});
|
||||
|
||||
// set up a http1 server that uses the service we just created
|
||||
Server::bind(&address)
|
||||
.http1_title_case_headers(true)
|
||||
.http1_preserve_header_case(true)
|
||||
.http1_only(true)
|
||||
.serve(service)
|
||||
.await?;
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
signals_handle.close();
|
||||
signals_task.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
51
tooling/webdriver/src/webdriver.rs
Normal file
51
tooling/webdriver/src/webdriver.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::cli::Args;
|
||||
use std::{env::current_dir, process::Command};
|
||||
|
||||
// the name of the binary to find in $PATH
|
||||
#[cfg(target_os = "linux")]
|
||||
const DRIVER_BINARY: &str = "WebKitWebDriver";
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
const DRIVER_BINARY: &str = "msedgedriver.exe";
|
||||
|
||||
/// Find the native driver binary in the PATH, or exits the process with an error.
|
||||
pub fn native(args: &Args) -> Command {
|
||||
let native_binary = match args.native_driver.as_deref() {
|
||||
Some(custom) => {
|
||||
if custom.exists() {
|
||||
custom.to_owned()
|
||||
} else {
|
||||
eprintln!(
|
||||
"can not find the supplied binary path {}. This is currently required.",
|
||||
custom.display()
|
||||
);
|
||||
match current_dir() {
|
||||
Ok(cwd) => eprintln!("current working directory: {}", cwd.display()),
|
||||
Err(error) => eprintln!("can not find current working directory: {}", error),
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
None => match which::which(DRIVER_BINARY) {
|
||||
Ok(binary) => binary,
|
||||
Err(error) => {
|
||||
eprintln!(
|
||||
"can not find binary {} in the PATH. This is currently required.\
|
||||
You can also pass a custom path with --native-driver",
|
||||
DRIVER_BINARY
|
||||
);
|
||||
eprintln!("{:?}", error);
|
||||
std::process::exit(1);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let mut cmd = Command::new(native_binary);
|
||||
cmd.env("TAURI_AUTOMATION", "true");
|
||||
cmd.arg(format!("--port={}", args.native_port));
|
||||
cmd
|
||||
}
|
||||
Reference in New Issue
Block a user