#Listen to navigation in a webview window

6 messages · Page 1 of 1 (latest)

arctic hemlock
#

Hello !

For my app, I need a webview that logs into a service and my main webview receives data from that other webview.

To do this, I created a new webview using

let url = Url::parse("https://biome.unilim.fr").unwrap();
let external_url = WebviewUrl::External(url);
let new_window = WebviewWindowBuilder::new(&app, "biome", external_url)
  .build().unwrap();

Now, since I'm on macOS, I want to listen to navigation, so I tried the following...

#[derive(Default)]
struct Ivars {
    web_view: OnceCell<Retained<WKWebView>>,
    window: OnceCell<Retained<NSWindow>>,
}

declare_class!(
  struct Delegate;

  // SAFETY:
  // - The superclass NSObject does not have any subclassing requirements.
  // - Main thread only mutability is correct, since this is an application delegate.
  // - `Delegate` does not implement `Drop`.
  unsafe impl ClassType for Delegate {
      type Super = NSObject;
      type Mutability = mutability::MainThreadOnly;
      const NAME: &'static str = "Delegate";
  }

  impl DeclaredClass for Delegate {
    type Ivars = Ivars;
  }

  unsafe impl NSObjectProtocol for Delegate {}

  unsafe impl WKNavigationDelegate for Delegate {
      #[method(webView:didFinishNavigation:)]
      #[allow(non_snake_case)]
      unsafe fn webView_didFinishNavigation(
          &self,
          web_view: &WKWebView,
          _navigation: Option<&WKNavigation>,
      ) {
          println!("finished navigation");
          unsafe {
              if let Some(url) = web_view.URL().and_then(|url| url.absoluteString()) {
                  println!("Finished navigation to: {}", url);
              }
          }
      }
  }
);

impl Delegate {
  fn new(mtm: MainThreadMarker) -> Retained<Self> {
      let this = mtm.alloc();
      let this = this.set_ivars(Ivars::default());
      unsafe { msg_send_id![super(this), init] }
  }
}
#

Finally I used it like this :

let _ = new_window.with_webview(|webview| {
  #[cfg(target_os = "macos")]
  unsafe {
    let mtm = MainThreadMarker::new().unwrap();
    let delegate = Delegate::new(mtm);
    let view: &WKWebView = &*webview.inner().cast();
    
    let navigation_delegate_obj = ProtocolObject::from_ref(&*delegate);
    view.setNavigationDelegate(Some(navigation_delegate_obj));
    println!("set navigation delegate");
  }
});
#

and it just logs set navigation delegate but nothing else after...

#

is there anything i'm doing wrong ?
is there also any other easier way to listen to navigation events on a webview i create ?

rancid garnet
#

as far as i know delegates can't be changed later on.