1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
// Copyright 2016 The rust-url developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[cfg(feature = "heapsize")] use heapsize::HeapSizeOf;
use host::Host;
use idna::domain_to_unicode;
use parser::default_port;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use Url;
pub fn url_origin(url: &Url) -> Origin {
let scheme = url.scheme();
match scheme {
"blob" => {
let result = Url::parse(url.path());
match result {
Ok(ref url) => url_origin(url),
Err(_) => Origin::new_opaque()
}
},
"ftp" | "gopher" | "http" | "https" | "ws" | "wss" => {
Origin::Tuple(scheme.to_owned(), url.host().unwrap().to_owned(),
url.port_or_known_default().unwrap())
},
// TODO: Figure out what to do if the scheme is a file
"file" => Origin::new_opaque(),
_ => Origin::new_opaque()
}
}
/// The origin of an URL
///
/// Two URLs with the same origin are considered
/// to originate from the same entity and can therefore trust
/// each other.
///
/// The origin is determined based on the scheme as follows:
///
/// - If the scheme is "blob" the origin is the origin of the
/// URL contained in the path component. If parsing fails,
/// it is an opaque origin.
/// - If the scheme is "ftp", "gopher", "http", "https", "ws", or "wss",
/// then the origin is a tuple of the scheme, host, and port.
/// - If the scheme is anything else, the origin is opaque, meaning
/// the URL does not have the same origin as any other URL.
///
/// For more information see <https://url.spec.whatwg.org/#origin>
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Origin {
/// A globally unique identifier
Opaque(OpaqueOrigin),
/// Consists of the URL's scheme, host and port
Tuple(String, Host<String>, u16)
}
#[cfg(feature = "heapsize")]
impl HeapSizeOf for Origin {
fn heap_size_of_children(&self) -> usize {
match *self {
Origin::Tuple(ref scheme, ref host, _) => {
scheme.heap_size_of_children() +
host.heap_size_of_children()
},
_ => 0,
}
}
}
impl Origin {
/// Creates a new opaque origin that is only equal to itself.
pub fn new_opaque() -> Origin {
static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
Origin::Opaque(OpaqueOrigin(COUNTER.fetch_add(1, Ordering::SeqCst)))
}
/// Return whether this origin is a (scheme, host, port) tuple
/// (as opposed to an opaque origin).
pub fn is_tuple(&self) -> bool {
matches!(*self, Origin::Tuple(..))
}
/// <https://html.spec.whatwg.org/multipage/#ascii-serialisation-of-an-origin>
pub fn ascii_serialization(&self) -> String {
match *self {
Origin::Opaque(_) => "null".to_owned(),
Origin::Tuple(ref scheme, ref host, port) => {
if default_port(scheme) == Some(port) {
format!("{}://{}", scheme, host)
} else {
format!("{}://{}:{}", scheme, host, port)
}
}
}
}
/// <https://html.spec.whatwg.org/multipage/#unicode-serialisation-of-an-origin>
pub fn unicode_serialization(&self) -> String {
match *self {
Origin::Opaque(_) => "null".to_owned(),
Origin::Tuple(ref scheme, ref host, port) => {
let host = match *host {
Host::Domain(ref domain) => {
let (domain, _errors) = domain_to_unicode(domain);
Host::Domain(domain)
}
_ => host.clone()
};
if default_port(scheme) == Some(port) {
format!("{}://{}", scheme, host)
} else {
format!("{}://{}:{}", scheme, host, port)
}
}
}
}
}
/// Opaque identifier for URLs that have file or other schemes
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
pub struct OpaqueOrigin(usize);
#[cfg(feature = "heapsize")]
known_heap_size!(0, OpaqueOrigin);