servo/components/script/dom/url.rs
Simon Wülker 3d320fa96a
Update rustfmt to the 2024 style edition (#35764)
* Use 2024 style edition

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Reformat all code

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-03-03 11:26:53 +00:00

340 lines
12 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::default::Default;
use dom_struct::dom_struct;
use js::rust::HandleObject;
use net_traits::blob_url_store::{get_blob_origin, parse_blob_url};
use net_traits::filemanager_thread::FileManagerThreadMsg;
use net_traits::{CoreResourceMsg, IpcSend};
use profile_traits::ipc;
use servo_url::ServoUrl;
use uuid::Uuid;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::URLBinding::URLMethods;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::blob::Blob;
use crate::dom::globalscope::GlobalScope;
use crate::dom::urlhelper::UrlHelper;
use crate::dom::urlsearchparams::URLSearchParams;
use crate::script_runtime::CanGc;
/// <https://url.spec.whatwg.org/#url>
#[dom_struct]
#[allow(clippy::upper_case_acronyms)]
pub(crate) struct URL {
reflector_: Reflector,
/// <https://url.spec.whatwg.org/#concept-url-url>
#[no_trace]
url: DomRefCell<ServoUrl>,
/// <https://url.spec.whatwg.org/#dom-url-searchparams>
search_params: MutNullableDom<URLSearchParams>,
}
impl URL {
fn new_inherited(url: ServoUrl) -> URL {
URL {
reflector_: Reflector::new(),
url: DomRefCell::new(url),
search_params: Default::default(),
}
}
fn new(
global: &GlobalScope,
proto: Option<HandleObject>,
url: ServoUrl,
can_gc: CanGc,
) -> DomRoot<URL> {
reflect_dom_object_with_proto(Box::new(URL::new_inherited(url)), global, proto, can_gc)
}
pub(crate) fn query_pairs(&self) -> Vec<(String, String)> {
self.url
.borrow()
.as_url()
.query_pairs()
.into_owned()
.collect()
}
pub(crate) fn set_query_pairs(&self, pairs: &[(String, String)]) {
let mut url = self.url.borrow_mut();
if pairs.is_empty() {
url.as_mut_url().set_query(None);
} else {
url.as_mut_url()
.query_pairs_mut()
.clear()
.extend_pairs(pairs);
}
}
/// <https://w3c.github.io/FileAPI/#unicodeSerializationOfBlobURL>
fn unicode_serialization_blob_url(origin: &str, id: &Uuid) -> String {
// Step 1, 2
let mut result = "blob:".to_string();
// Step 3
result.push_str(origin);
// Step 4
result.push('/');
// Step 5
result.push_str(&id.to_string());
result
}
}
impl URLMethods<crate::DomTypeHolder> for URL {
/// <https://url.spec.whatwg.org/#constructors>
fn Constructor(
global: &GlobalScope,
proto: Option<HandleObject>,
can_gc: CanGc,
url: USVString,
base: Option<USVString>,
) -> Fallible<DomRoot<URL>> {
// Step 1. Parse url with base.
let parsed_base = match base {
None => None,
Some(base) => {
match ServoUrl::parse(&base.0) {
Ok(base) => Some(base),
Err(error) => {
// Step 2. Throw a TypeError if URL parsing fails.
return Err(Error::Type(format!("could not parse base: {}", error)));
},
}
},
};
let parsed_url = match ServoUrl::parse_with_base(parsed_base.as_ref(), &url.0) {
Ok(url) => url,
Err(error) => {
// Step 2. Throw a TypeError if URL parsing fails.
return Err(Error::Type(format!("could not parse URL: {}", error)));
},
};
// Skip the steps below.
// Instead of constructing a new `URLSearchParams` object here, construct it
// on-demand inside `URL::SearchParams`.
//
// Step 3. Let query be parsedURLs query.
// Step 5. Set thiss query object to a new URLSearchParams object.
// Step 6. Initialize thiss query object with query.
// Step 7. Set thiss query objects URL object to this.
// Step 4. Set thiss URL to parsedURL.
Ok(URL::new(global, proto, parsed_url, can_gc))
}
/// <https://url.spec.whatwg.org/#dom-url-canparse>
fn CanParse(_global: &GlobalScope, url: USVString, base: Option<USVString>) -> bool {
// Step 1.
let parsed_base = match base {
None => None,
Some(base) => match ServoUrl::parse(&base.0) {
Ok(base) => Some(base),
Err(_) => {
// Step 2.1
return false;
},
},
};
// Step 2.2, 3
ServoUrl::parse_with_base(parsed_base.as_ref(), &url.0).is_ok()
}
/// <https://url.spec.whatwg.org/#dom-url-parse>
fn Parse(
global: &GlobalScope,
url: USVString,
base: Option<USVString>,
can_gc: CanGc,
) -> Option<DomRoot<URL>> {
// Step 1: Let parsedURL be the result of running the API URL parser on url with base,
// if given.
let parsed_base = base.and_then(|base| ServoUrl::parse(base.0.as_str()).ok());
let parsed_url = ServoUrl::parse_with_base(parsed_base.as_ref(), &url.0);
// Step 2: If parsedURL is failure, then return null.
// Step 3: Let url be a new URL object.
// Step 4: Initialize url with parsedURL.
// Step 5: Return url.
// These steps are all handled while mapping the Result to an Option<ServoUrl>.
// Regarding initialization, the same condition should apply here as stated in the comments
// in Self::Constructor above - construct it on-demand inside `URL::SearchParams`.
Some(URL::new(global, None, parsed_url.ok()?, can_gc))
}
/// <https://w3c.github.io/FileAPI/#dfn-createObjectURL>
fn CreateObjectURL(global: &GlobalScope, blob: &Blob) -> DOMString {
// XXX: Second field is an unicode-serialized Origin, it is a temporary workaround
// and should not be trusted. See issue https://github.com/servo/servo/issues/11722
let origin = get_blob_origin(&global.get_url());
let id = blob.get_blob_url_id();
DOMString::from(URL::unicode_serialization_blob_url(&origin, &id))
}
/// <https://w3c.github.io/FileAPI/#dfn-revokeObjectURL>
fn RevokeObjectURL(global: &GlobalScope, url: DOMString) {
// If the value provided for the url argument is not a Blob URL OR
// if the value provided for the url argument does not have an entry in the Blob URL Store,
// this method call does nothing. User agents may display a message on the error console.
let origin = get_blob_origin(&global.get_url());
if let Ok(url) = ServoUrl::parse(&url) {
if url.fragment().is_none() && origin == get_blob_origin(&url) {
if let Ok((id, _)) = parse_blob_url(&url) {
let resource_threads = global.resource_threads();
let (tx, rx) = ipc::channel(global.time_profiler_chan().clone()).unwrap();
let msg = FileManagerThreadMsg::RevokeBlobURL(id, origin, tx);
let _ = resource_threads.send(CoreResourceMsg::ToFileManager(msg));
let _ = rx.recv().unwrap();
}
}
}
}
/// <https://url.spec.whatwg.org/#dom-url-hash>
fn Hash(&self) -> USVString {
UrlHelper::Hash(&self.url.borrow())
}
/// <https://url.spec.whatwg.org/#dom-url-hash>
fn SetHash(&self, value: USVString) {
UrlHelper::SetHash(&mut self.url.borrow_mut(), value);
}
/// <https://url.spec.whatwg.org/#dom-url-host>
fn Host(&self) -> USVString {
UrlHelper::Host(&self.url.borrow())
}
/// <https://url.spec.whatwg.org/#dom-url-host>
fn SetHost(&self, value: USVString) {
UrlHelper::SetHost(&mut self.url.borrow_mut(), value);
}
/// <https://url.spec.whatwg.org/#dom-url-hostname>
fn Hostname(&self) -> USVString {
UrlHelper::Hostname(&self.url.borrow())
}
/// <https://url.spec.whatwg.org/#dom-url-hostname>
fn SetHostname(&self, value: USVString) {
UrlHelper::SetHostname(&mut self.url.borrow_mut(), value);
}
/// <https://url.spec.whatwg.org/#dom-url-href>
fn Href(&self) -> USVString {
UrlHelper::Href(&self.url.borrow())
}
/// <https://url.spec.whatwg.org/#dom-url-href>
fn SetHref(&self, value: USVString) -> ErrorResult {
match ServoUrl::parse(&value.0) {
Ok(url) => {
*self.url.borrow_mut() = url;
self.search_params.set(None); // To be re-initialized in the SearchParams getter.
Ok(())
},
Err(error) => Err(Error::Type(format!("could not parse URL: {}", error))),
}
}
/// <https://url.spec.whatwg.org/#dom-url-password>
fn Password(&self) -> USVString {
UrlHelper::Password(&self.url.borrow())
}
/// <https://url.spec.whatwg.org/#dom-url-password>
fn SetPassword(&self, value: USVString) {
UrlHelper::SetPassword(&mut self.url.borrow_mut(), value);
}
/// <https://url.spec.whatwg.org/#dom-url-pathname>
fn Pathname(&self) -> USVString {
UrlHelper::Pathname(&self.url.borrow())
}
/// <https://url.spec.whatwg.org/#dom-url-pathname>
fn SetPathname(&self, value: USVString) {
UrlHelper::SetPathname(&mut self.url.borrow_mut(), value);
}
/// <https://url.spec.whatwg.org/#dom-url-port>
fn Port(&self) -> USVString {
UrlHelper::Port(&self.url.borrow())
}
/// <https://url.spec.whatwg.org/#dom-url-port>
fn SetPort(&self, value: USVString) {
UrlHelper::SetPort(&mut self.url.borrow_mut(), value);
}
/// <https://url.spec.whatwg.org/#dom-url-protocol>
fn Protocol(&self) -> USVString {
UrlHelper::Protocol(&self.url.borrow())
}
/// <https://url.spec.whatwg.org/#dom-url-protocol>
fn SetProtocol(&self, value: USVString) {
UrlHelper::SetProtocol(&mut self.url.borrow_mut(), value);
}
/// <https://url.spec.whatwg.org/#dom-url-origin>
fn Origin(&self) -> USVString {
UrlHelper::Origin(&self.url.borrow())
}
/// <https://url.spec.whatwg.org/#dom-url-search>
fn Search(&self) -> USVString {
UrlHelper::Search(&self.url.borrow())
}
/// <https://url.spec.whatwg.org/#dom-url-search>
fn SetSearch(&self, value: USVString) {
UrlHelper::SetSearch(&mut self.url.borrow_mut(), value);
if let Some(search_params) = self.search_params.get() {
search_params.set_list(self.query_pairs());
}
}
/// <https://url.spec.whatwg.org/#dom-url-searchparams>
fn SearchParams(&self, can_gc: CanGc) -> DomRoot<URLSearchParams> {
self.search_params
.or_init(|| URLSearchParams::new(&self.global(), Some(self), can_gc))
}
/// <https://url.spec.whatwg.org/#dom-url-username>
fn Username(&self) -> USVString {
UrlHelper::Username(&self.url.borrow())
}
/// <https://url.spec.whatwg.org/#dom-url-username>
fn SetUsername(&self, value: USVString) {
UrlHelper::SetUsername(&mut self.url.borrow_mut(), value);
}
/// <https://url.spec.whatwg.org/#dom-url-tojson>
fn ToJSON(&self) -> USVString {
self.Href()
}
}