Skip to content

Commit

Permalink
feat: add load_url_with_headers, close #816
Browse files Browse the repository at this point in the history
  • Loading branch information
amrbashir committed Dec 27, 2022
1 parent fca42a0 commit 4bbec1d
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changes/load_url_with_headers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": "patch"
---

Add `WebViewBuilder::with_headers` and `WebView::load_url_with_headers` to navigate to urls with headers.
17 changes: 15 additions & 2 deletions src/webview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ pub struct WebViewAttributes {
pub background_color: Option<RGBA>,
/// Whether load the provided URL to [`WebView`].
pub url: Option<Url>,
/// Headers used when loading the requested `url`.
pub headers: Option<http::HeaderMap>,
/// Whether page zooming by hotkeys is enabled
///
/// ## Platform-specific
Expand Down Expand Up @@ -234,6 +236,7 @@ impl Default for WebViewAttributes {
transparent: false,
background_color: None,
url: None,
headers: None,
html: None,
initialization_scripts: vec![],
custom_protocols: vec![],
Expand Down Expand Up @@ -433,15 +436,21 @@ impl<'a> WebViewBuilder<'a> {
self
}

/// Specify headers used when loading the requested `url`.
pub fn with_headers(mut self, headers: http::HeaderMap) -> Self {
self.webview.headers = Some(headers);
self
}

/// Load the provided URL when the builder calling [`WebViewBuilder::build`] to create the
/// [`WebView`]. The provided URL must be valid.
/// [`WebView`]. The provided URL must be valid. This will be ignored if `url` or `request` is already provided.
pub fn with_url(mut self, url: &str) -> Result<Self> {
self.webview.url = Some(Url::parse(url)?);
Ok(self)
}

/// Load the provided HTML string when the builder calling [`WebViewBuilder::build`] to create the
/// [`WebView`]. This will be ignored if `url` is already provided.
/// [`WebView`]. This will be ignored if `url` or `request` is already provided.
///
/// # Warning
/// The Page loaded from html string will have different Origin on different platforms. And
Expand Down Expand Up @@ -785,6 +794,10 @@ impl WebView {
pub fn load_url(&self, url: &str) {
self.webview.load_url(url)
}

pub fn load_url_with_headers(&self, url: &str, headers: http::HeaderMap) {
self.webview.load_url_with_headers(url, headers)
}
}

/// An event enumeration sent to [`FileDropHandler`].
Expand Down
21 changes: 18 additions & 3 deletions src/webview/webkitgtk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use std::{
};
use url::Url;
use webkit2gtk::{
traits::*, LoadEvent, NavigationPolicyDecision, PolicyDecisionType, UserContentInjectedFrames,
UserScript, UserScriptInjectionTime, WebView, WebViewBuilder,
traits::*, LoadEvent, NavigationPolicyDecision, PolicyDecisionType, URIRequest,
UserContentInjectedFrames, UserScript, UserScriptInjectionTime, WebView, WebViewBuilder,
};
use webkit2gtk_sys::{
webkit_get_major_version, webkit_get_micro_version, webkit_get_minor_version,
Expand Down Expand Up @@ -350,7 +350,7 @@ impl InnerWebView {

// Navigation
if let Some(url) = attributes.url {
web_context.queue_load_uri(Rc::clone(&w.webview), url);
web_context.queue_load_uri(Rc::clone(&w.webview), url, attributes.headers);
web_context.flush_queue_loader();
} else if let Some(html) = attributes.html {
w.webview.load_html(&html, Some("http://localhost"));
Expand Down Expand Up @@ -450,6 +450,21 @@ impl InnerWebView {
pub fn load_url(&self, url: &str) {
self.webview.load_uri(url)
}

pub fn load_url_with_headers(&self, url: &str, headers: http::HeaderMap) {
let req = URIRequest::builder().uri(url).build();

if let Some(ref mut req_headers) = req.http_headers() {
for (header, value) in headers.iter() {
req_headers.append(
header.to_string().as_str(),
value.to_str().unwrap_or_default(),
);
}
}

self.webview.load_request(&req);
}
}

pub fn platform_webview_version() -> Result<String> {
Expand Down
37 changes: 26 additions & 11 deletions src/webview/webkitgtk/web_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use std::{
};
use url::Url;
use webkit2gtk::{
traits::*, ApplicationInfo, CookiePersistentStorage, LoadEvent, UserContentManager, WebContext,
WebContextBuilder, WebView, WebsiteDataManagerBuilder,
traits::*, ApplicationInfo, CookiePersistentStorage, LoadEvent, URIRequest, UserContentManager,
WebContext, WebContextBuilder, WebView, WebsiteDataManagerBuilder,
};

#[derive(Debug)]
Expand Down Expand Up @@ -124,7 +124,7 @@ pub trait WebContextExt {
/// Add a [`WebView`] to the queue waiting to be opened.
///
/// See the `WebviewUriLoader` for more information.
fn queue_load_uri(&self, webview: Rc<WebView>, url: Url);
fn queue_load_uri(&self, webview: Rc<WebView>, url: Url, headers: Option<http::HeaderMap>);

/// Flush all queued [`WebView`]s waiting to load a uri.
///
Expand Down Expand Up @@ -177,8 +177,8 @@ impl WebContextExt for super::WebContext {
}
}

fn queue_load_uri(&self, webview: Rc<WebView>, url: Url) {
self.os.webview_uri_loader.push(webview, url)
fn queue_load_uri(&self, webview: Rc<WebView>, url: Url, headers: Option<http::HeaderMap>) {
self.os.webview_uri_loader.push(webview, url, headers)
}

fn flush_queue_loader(&self) {
Expand Down Expand Up @@ -402,7 +402,7 @@ where
#[derive(Debug, Default)]
struct WebviewUriLoader {
lock: AtomicBool,
queue: Mutex<VecDeque<(Rc<WebView>, Url)>>,
queue: Mutex<VecDeque<(Rc<WebView>, Url, Option<http::HeaderMap>)>>,
}

impl WebviewUriLoader {
Expand All @@ -417,21 +417,21 @@ impl WebviewUriLoader {
}

/// Add a [`WebView`] to the queue.
fn push(&self, webview: Rc<WebView>, url: Url) {
fn push(&self, webview: Rc<WebView>, url: Url, headers: Option<http::HeaderMap>) {
let mut queue = self.queue.lock().expect("poisoned load queue");
queue.push_back((webview, url))
queue.push_back((webview, url, headers))
}

/// Remove a [`WebView`] from the queue and return it.
fn pop(&self) -> Option<(Rc<WebView>, Url)> {
fn pop(&self) -> Option<(Rc<WebView>, Url, Option<http::HeaderMap>)> {
let mut queue = self.queue.lock().expect("poisoned load queue");
queue.pop_front()
}

/// Load the next uri to load if the lock is not engaged.
fn flush(self: Rc<Self>) {
if !self.is_locked() {
if let Some((webview, url)) = self.pop() {
if let Some((webview, url, headers)) = self.pop() {
// we do not need to listen to failed events because those will finish the change event anyways
webview.connect_load_changed(move |_, event| {
if let LoadEvent::Finished = event {
Expand All @@ -440,7 +440,22 @@ impl WebviewUriLoader {
};
});

webview.load_uri(url.as_str());
if let Some(headers) = headers {
let req = URIRequest::builder().uri(url.as_str()).build();

if let Some(ref mut req_headers) = req.http_headers() {
for (header, value) in headers.iter() {
req_headers.append(
header.to_string().as_str(),
value.to_str().unwrap_or_default(),
);
}
}

webview.load_request(&req);
} else {
webview.load_uri(url.as_str());
}
} else {
self.unlock();
}
Expand Down

0 comments on commit 4bbec1d

Please sign in to comment.