Skip to content

Commit

Permalink
feat: add WebView::url() to access the current url (#732)
Browse files Browse the repository at this point in the history
* feat: add `.url()`to access the current url

* fmt

* add url import

* fix linux and windows

* add stub to android webview

* Update src/webview/webview2/mod.rs

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>

* Add android

* change file and doc

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
  • Loading branch information
JonasKruckenberg and amrbashir committed Oct 25, 2022
1 parent 9d5595c commit 38e49bd
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changes/url.md
@@ -0,0 +1,5 @@
---
"wry": minor
---

Add `WebView::url` to get the current url.
13 changes: 13 additions & 0 deletions src/webview/android/main_pipe.rs
Expand Up @@ -161,6 +161,18 @@ impl MainPipe<'_> {
Err(e) => tx.send(Err(e.into())).unwrap(),
}
}
WebViewMessage::GetUrl(tx) => {
if let Some(webview) = &self.webview {
let url = env
.call_method(webview.as_obj(), "getUrl", "()Ljava/lang/String", &[])
.and_then(|v| v.l())
.and_then(|s| env.get_string(s.into()))
.map(|u| u.to_string_lossy().into())
.unwrap_or_default();

tx.send(url).unwrap()
}
}
WebViewMessage::Jni(f) => {
if let Some(webview) = &self.webview {
f(env, activity, webview.as_obj());
Expand Down Expand Up @@ -198,6 +210,7 @@ pub enum WebViewMessage {
Eval(String),
SetBackgroundColor(RGBA),
GetWebViewVersion(Sender<Result<String, Error>>),
GetUrl(Sender<String>),
Jni(Box<dyn FnOnce(JNIEnv, JObject, JObject) + Send>),
}

Expand Down
8 changes: 8 additions & 0 deletions src/webview/android/mod.rs
Expand Up @@ -23,6 +23,7 @@ use tao::platform::android::ndk_glue::{
ndk::looper::{FdEvent, ForeignLooper},
PACKAGE,
};
use url::Url;

pub(crate) mod binding;
mod main_pipe;
Expand Down Expand Up @@ -228,6 +229,13 @@ impl InnerWebView {

pub fn print(&self) {}

pub fn url(&self) -> Url {
let (tx, rx) = bounded(1);
MainPipe::send(WebViewMessage::GetUrl(tx));
let uri = rx.recv().unwrap();
Url::parse(uri.as_str()).unwrap()
}

pub fn eval(&self, js: &str) -> Result<()> {
MainPipe::send(WebViewMessage::Eval(js.into()));
Ok(())
Expand Down
5 changes: 5 additions & 0 deletions src/webview/mod.rs
Expand Up @@ -636,6 +636,11 @@ impl WebView {
&self.window
}

/// Get the current url of the webview
pub fn url(&self) -> Url {
self.webview.url()
}

/// Evaluate and run javascript code. Must be called on the same thread who created the
/// [`WebView`]. Use [`EventLoopProxy`] and a custom event to send scripts from other threads.
///
Expand Down
16 changes: 11 additions & 5 deletions src/webview/webkitgtk/mod.rs
Expand Up @@ -2,6 +2,10 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

use gdk::{Cursor, EventMask, WindowEdge};
use gio::Cancellable;
use glib::signal::Inhibit;
use gtk::prelude::*;
#[cfg(any(debug_assertions, feature = "devtools"))]
use std::sync::{
atomic::{AtomicBool, Ordering},
Expand All @@ -12,11 +16,7 @@ use std::{
hash::{Hash, Hasher},
rc::Rc,
};

use gdk::{Cursor, EventMask, WindowEdge};
use gio::Cancellable;
use glib::signal::Inhibit;
use gtk::prelude::*;
use url::Url;
use webkit2gtk::{
traits::*, NavigationPolicyDecision, PolicyDecisionType, UserContentInjectedFrames, UserScript,
UserScriptInjectionTime, WebView, WebViewBuilder,
Expand Down Expand Up @@ -362,6 +362,12 @@ impl InnerWebView {
let _ = self.eval("window.print()");
}

pub fn url(&self) -> Url {
let uri = self.webview.uri().unwrap();

Url::parse(uri.as_str()).unwrap()
}

pub fn eval(&self, js: &str) -> Result<()> {
let cancellable: Option<&Cancellable> = None;
self.webview.run_javascript(js, cancellable, |_| ());
Expand Down
11 changes: 11 additions & 0 deletions src/webview/webview2/mod.rs
Expand Up @@ -10,6 +10,7 @@ use crate::{
};

use file_drop::FileDropController;
use url::Url;

use std::{
collections::HashSet, fmt::Write, iter::once, mem::MaybeUninit, os::windows::prelude::OsStrExt,
Expand Down Expand Up @@ -769,6 +770,16 @@ window.addEventListener('mousemove', (e) => window.chrome.webview.postMessage('_
let _ = self.eval("window.print()");
}

pub fn url(&self) -> Url {
let mut pwstr = PWSTR::null();

unsafe { self.webview.Source(&mut pwstr).unwrap() };

let uri = take_pwstr(pwstr);

Url::parse(&uri.to_string()).unwrap()
}

pub fn eval(&self, js: &str) -> Result<()> {
Self::execute_script(&self.webview, js.to_string())
.map_err(|err| Error::WebView2Error(webview2_com::Error::WindowsError(err)))
Expand Down
17 changes: 17 additions & 0 deletions src/webview/wkwebview/mod.rs
Expand Up @@ -7,6 +7,7 @@ mod download;
mod file_drop;
mod web_context;

use url::Url;
pub use web_context::WebContextImpl;

#[cfg(target_os = "macos")]
Expand Down Expand Up @@ -695,6 +696,22 @@ r#"Object.defineProperty(window, 'ipc', {
}
}

pub fn url(&self) -> Url {
let url_obj: *mut Object = unsafe { msg_send![self.webview, URL] };
let absolute_url: *mut Object = unsafe { msg_send![url_obj, absoluteString] };

let bytes = {
let bytes: *const c_char = unsafe { msg_send![absolute_url, UTF8String] };
bytes as *const u8
};

// 4 represents utf8 encoding
let len = unsafe { msg_send![absolute_url, lengthOfBytesUsingEncoding: 4] };
let bytes = unsafe { std::slice::from_raw_parts(bytes, len) };

Url::parse(std::str::from_utf8(bytes).unwrap()).unwrap()
}

pub fn eval(&self, js: &str) -> Result<()> {
// Safety: objc runtime calls are unsafe
unsafe {
Expand Down

0 comments on commit 38e49bd

Please sign in to comment.