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