From ae5399e68e74fa9034fb11404a5f3a3924172cc2 Mon Sep 17 00:00:00 2001 From: yggverse Date: Tue, 10 Dec 2024 00:04:09 +0200 Subject: [PATCH] keep all redirects chain, add referrer holder --- src/app/browser/window/tab/item/page.rs | 43 +++++++--------- src/app/browser/window/tab/item/page/meta.rs | 49 ++++++------------- .../window/tab/item/page/meta/redirect.rs | 19 +++---- .../browser/window/tab/item/page/request.rs | 21 +++++++- 4 files changed, 58 insertions(+), 74 deletions(-) diff --git a/src/app/browser/window/tab/item/page.rs b/src/app/browser/window/tab/item/page.rs index 2e6e26f2..9dc97035 100644 --- a/src/app/browser/window/tab/item/page.rs +++ b/src/app/browser/window/tab/item/page.rs @@ -155,7 +155,7 @@ impl Page { pub fn load(&self, is_history: bool) { /// Global limit to prevent infinitive redirects (ALL protocols) /// * every protocol implementation has own value checker, according to specification - const DEFAULT_MAX_REDIRECT_COUNT: i8 = 10; + const DEFAULT_MAX_REDIRECT_COUNT: usize = 10; // Reset widgets self.input.unset(); @@ -163,40 +163,29 @@ impl Page { // Create shared variant value let id = self.id.clone(); - // Try **take** request value from Redirect holder first - let request = if let Some(redirect) = self.meta.take_redirect() { - // Update redirect counter - self.meta - .set_redirect_count(match self.meta.redirect_count() { - Some(value) => { - // Prevent infinitive redirection - if value > DEFAULT_MAX_REDIRECT_COUNT { - todo!() - } - // Increase - Some(value + 1) - } - // Set initial value - None => Some(1), - }); + // Prevent infinitive redirection + if self.meta.total_redirects() > DEFAULT_MAX_REDIRECT_COUNT { + todo!() + } - // Update navigation on redirect `is_foreground` - if redirect.is_foreground() { + // Try redirect request + let request = if let Some(redirect) = self.meta.last_redirect() { + if redirect.is_foreground { self.navigation .request .widget .entry - .set_text(redirect.request().as_str()); + .set_text(&redirect.request); } // Return value from redirection holder - Request::from(&redirect.request()) + Request::from(&redirect.request, redirect.referrer.as_ref()) } else { // Reset redirect counter as request value taken from user input - self.meta.unset_redirect_count(); + self.meta.redirect.borrow_mut().clear(); // Return value from navigation entry - Request::from(&self.navigation.request.widget.entry.text()) + Request::from(&self.navigation.request.widget.entry.text(), None) }; // Update @@ -773,7 +762,7 @@ impl Page { ) ); // Client MUST limit the number of redirects they follow to 5 (by protocol specification) - } else if meta.redirect_count() > Some(5) { + } else if meta.total_redirects() > 5 { // Update meta meta.set_status(Status::Failure) .set_title("Oops"); @@ -790,12 +779,14 @@ impl Page { // then call page reload action to apply it by the parental controller } else { meta.set_redirect( - // Skip query and fragment by protocol requirements + // skip query and fragment by protocol requirements // @TODO review fragment specification resolved_uri.to_string_partial( UriHideFlags::FRAGMENT | UriHideFlags::QUERY ), - // Set follow policy based on status code + // referrer + Some(navigation.request.widget.entry.text()), + // set follow policy based on status code matches!(response.meta.status, gemini::client::connection::response::meta::Status::PermanentRedirect), ) .set_status(Status::Redirect) // @TODO is this status really wanted? diff --git a/src/app/browser/window/tab/item/page/meta.rs b/src/app/browser/window/tab/item/page/meta.rs index 67863baf..f79c6980 100644 --- a/src/app/browser/window/tab/item/page/meta.rs +++ b/src/app/browser/window/tab/item/page/meta.rs @@ -29,10 +29,9 @@ pub enum Status { } pub struct Meta { - status: RefCell, - title: RefCell, - redirect: RefCell>, - redirect_count: RefCell>, + pub status: RefCell, + pub title: RefCell, + pub redirect: RefCell>, } impl Meta { @@ -42,8 +41,7 @@ impl Meta { Self { status: RefCell::new(status), title: RefCell::new(title), - redirect: RefCell::new(None), - redirect_count: RefCell::new(None), + redirect: RefCell::new(Vec::new()), } } @@ -59,30 +57,18 @@ impl Meta { self } - pub fn set_redirect(&self, request: GString, is_foreground: bool) -> &Self { + pub fn set_redirect( + &self, + request: GString, + referrer: Option, + is_foreground: bool, + ) -> &Self { self.redirect - .replace(Some(Redirect::new(request, is_foreground))); + .borrow_mut() + .push(Redirect::new(request, referrer, is_foreground)); self } - pub fn set_redirect_count(&self, redirect_count: Option) -> &Self { - self.redirect_count.replace(redirect_count); - self - } - - pub fn unset_redirect_count(&self) -> &Self { - if self.redirect_count.borrow().is_some() { - self.set_redirect_count(None); - } - self - } - - /* @TODO not in use - pub fn unset_redirect(&self) -> &Self { - self.redirect.replace(None); - self - } */ - // Getters pub fn status(&self) -> Status { @@ -93,15 +79,12 @@ impl Meta { self.title.borrow().clone() } - pub fn redirect_count(&self) -> Option { - *self.redirect_count.borrow() + pub fn total_redirects(&self) -> usize { + self.redirect.borrow().len() + 1 } - /// WARNING! - /// - /// This function **take** the `Redirect` without clone semantics - pub fn take_redirect(&self) -> Option { - self.redirect.take() + pub fn last_redirect(&self) -> Option { + self.redirect.borrow().last().cloned() } // Actions diff --git a/src/app/browser/window/tab/item/page/meta/redirect.rs b/src/app/browser/window/tab/item/page/meta/redirect.rs index 6f7e091b..62c547c9 100644 --- a/src/app/browser/window/tab/item/page/meta/redirect.rs +++ b/src/app/browser/window/tab/item/page/meta/redirect.rs @@ -12,28 +12,21 @@ use gtk::glib::GString; /// * `request` - destination /// * currently, it's raw `GString` not [Uri](https://docs.gtk.org/glib/struct.Uri.html) /// because of compatibility with request field as it could contain any other, not parsable values +#[derive(Clone, Debug)] pub struct Redirect { - is_foreground: bool, - request: GString, + pub is_foreground: bool, + pub referrer: Option, + pub request: GString, } impl Redirect { // Constructors - pub fn new(request: GString, is_foreground: bool) -> Self { + pub fn new(request: GString, referrer: Option, is_foreground: bool) -> Self { Self { is_foreground, + referrer, request, } } - - // Getters - - pub fn request(&self) -> GString { - self.request.clone() - } - - pub fn is_foreground(&self) -> bool { - self.is_foreground - } } diff --git a/src/app/browser/window/tab/item/page/request.rs b/src/app/browser/window/tab/item/page/request.rs index 87adf20e..2517f26b 100644 --- a/src/app/browser/window/tab/item/page/request.rs +++ b/src/app/browser/window/tab/item/page/request.rs @@ -1,4 +1,4 @@ -use gtk::glib::{Uri, UriFlags}; +use gtk::glib::{GString, Uri, UriFlags}; /// Request type for `Page` with optional value parsed pub enum Request { @@ -12,7 +12,9 @@ impl Request { // Constructors /// Create new `Self` from `request` string - pub fn from(request: &str) -> Self { + /// * if some `referrer` given, make additional check in previous request + pub fn from(request: &str, referrer: Option<&GString>) -> Self { + // check in request if let Some(postfix) = request.strip_prefix("source:") { if let Ok(uri) = Uri::parse(postfix, UriFlags::NONE) { return Self::Source(uri); @@ -25,10 +27,25 @@ impl Request { } } + // check in referrer @TODO tmp + if referrer.is_some_and(|this| this.starts_with("source:")) { + if let Ok(uri) = Uri::parse(request, UriFlags::NONE) { + return Self::Source(uri); + } + } + + if referrer.is_some_and(|this| this.starts_with("download:")) { + if let Ok(uri) = Uri::parse(request, UriFlags::NONE) { + return Self::Download(uri); + } + } + + // is default if let Ok(uri) = Uri::parse(request, UriFlags::NONE) { return Self::Default(uri); } + // is search Self::Search(request.to_string()) } }