diff options
author | Connor Brewster <connor.brewster@eagles.oc.edu> | 2017-01-20 13:21:23 -0600 |
---|---|---|
committer | Alan Jeffrey <ajeffrey@mozilla.com> | 2017-02-22 11:11:59 -0600 |
commit | bfd7b950ad1d2e9264563fc40d5684a96bbab23f (patch) | |
tree | 775afc20fbfb832b7242ea5c6145c97f6a63bcc6 | |
parent | 4f7e422054237c8ba0a8e521a615a6012b90eab4 (diff) | |
download | servo-bfd7b950ad1d2e9264563fc40d5684a96bbab23f.tar.gz servo-bfd7b950ad1d2e9264563fc40d5684a96bbab23f.zip |
Add ImmutableOrigin to allow for serializing origins
-rw-r--r-- | Cargo.lock | 3 | ||||
-rw-r--r-- | components/net/http_loader.rs | 7 | ||||
-rw-r--r-- | components/net_traits/request.rs | 7 | ||||
-rw-r--r-- | components/script/dom/bindings/trace.rs | 6 | ||||
-rw-r--r-- | components/script/dom/document.rs | 33 | ||||
-rw-r--r-- | components/script/dom/domimplementation.rs | 4 | ||||
-rw-r--r-- | components/script/dom/domparser.rs | 4 | ||||
-rw-r--r-- | components/script/dom/htmliframeelement.rs | 2 | ||||
-rw-r--r-- | components/script/dom/node.rs | 2 | ||||
-rw-r--r-- | components/script/dom/servoparser/mod.rs | 2 | ||||
-rw-r--r-- | components/script/dom/window.rs | 11 | ||||
-rw-r--r-- | components/script/dom/xmldocument.rs | 7 | ||||
-rw-r--r-- | components/script/dom/xmlhttprequest.rs | 2 | ||||
-rw-r--r-- | components/script/lib.rs | 1 | ||||
-rw-r--r-- | components/script/origin.rs | 61 | ||||
-rw-r--r-- | components/script/script_thread.rs | 16 | ||||
-rw-r--r-- | components/url/Cargo.toml | 7 | ||||
-rw-r--r-- | components/url/lib.rs | 15 | ||||
-rw-r--r-- | components/url/origin.rs | 172 | ||||
-rw-r--r-- | tests/unit/net/fetch.rs | 15 | ||||
-rw-r--r-- | tests/unit/script/origin.rs | 45 |
21 files changed, 270 insertions, 152 deletions
diff --git a/Cargo.lock b/Cargo.lock index 7f2a649894e..e6354423afb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2596,8 +2596,11 @@ dependencies = [ "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", + "servo_rand 0.0.1", "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 63fa745707b..56750d60f05 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -37,7 +37,7 @@ use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType}; use openssl; use openssl::ssl::error::{OpensslError, SslError}; use resource_thread::AuthCache; -use servo_url::ServoUrl; +use servo_url::{ImmutableOrigin, ServoUrl}; use std::collections::HashSet; use std::error::Error; use std::io::{self, Read, Write}; @@ -51,7 +51,6 @@ use std::thread; use time; use time::Tm; use unicase::UniCase; -use url::Origin as UrlOrigin; use uuid; fn read_block<R: Read>(reader: &mut R) -> Result<Data, ()> { @@ -389,7 +388,7 @@ fn send_response_to_devtools(devtools_chan: &Sender<DevtoolsControlMsg>, let _ = devtools_chan.send(DevtoolsControlMsg::FromChrome(msg)); } -fn auth_from_cache(auth_cache: &Arc<RwLock<AuthCache>>, origin: &UrlOrigin) -> Option<Basic> { +fn auth_from_cache(auth_cache: &Arc<RwLock<AuthCache>>, origin: &ImmutableOrigin) -> Option<Basic> { if let Some(ref auth_entry) = auth_cache.read().unwrap().entries.get(&origin.ascii_serialization()) { let user_name = auth_entry.user_name.clone(); let password = Some(auth_entry.password.clone()); @@ -767,7 +766,7 @@ fn http_redirect_fetch(request: Rc<Request>, // Step 9 if cors_flag && !same_origin { - *request.origin.borrow_mut() = Origin::Origin(UrlOrigin::new_opaque()); + *request.origin.borrow_mut() = Origin::Origin(ImmutableOrigin::new_opaque()); } // Step 10 diff --git a/components/net_traits/request.rs b/components/net_traits/request.rs index dcdd87ac4b0..7178ec8ca99 100644 --- a/components/net_traits/request.rs +++ b/components/net_traits/request.rs @@ -6,10 +6,9 @@ use ReferrerPolicy; use hyper::header::Headers; use hyper::method::Method; use msg::constellation_msg::PipelineId; -use servo_url::ServoUrl; +use servo_url::{ImmutableOrigin, ServoUrl}; use std::cell::{Cell, RefCell}; use std::default::Default; -use url::Origin as UrlOrigin; /// An [initiator](https://fetch.spec.whatwg.org/#concept-request-initiator) #[derive(Copy, Clone, PartialEq, HeapSizeOf)] @@ -55,10 +54,10 @@ pub enum Destination { } /// A request [origin](https://fetch.spec.whatwg.org/#concept-request-origin) -#[derive(Clone, PartialEq, Debug, HeapSizeOf)] +#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, HeapSizeOf)] pub enum Origin { Client, - Origin(UrlOrigin), + Origin(ImmutableOrigin), } /// A [referer](https://fetch.spec.whatwg.org/#concept-request-referrer) diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index aeddcdabe4b..0e605780a20 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -79,7 +79,7 @@ use script_traits::{UntrustedNodeAddress, WindowSizeData, WindowSizeType}; use selectors::matching::ElementSelectorFlags; use serde::{Deserialize, Serialize}; use servo_atoms::Atom; -use servo_url::ServoUrl; +use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use smallvec::SmallVec; use std::cell::{Cell, RefCell, UnsafeCell}; use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; @@ -104,7 +104,6 @@ use style::stylesheets::SupportsRule; use style::values::specified::Length; use style::viewport::ViewportRule; use time::Duration; -use url::Origin as UrlOrigin; use uuid::Uuid; use webrender_traits::{WebGLBufferId, WebGLError, WebGLFramebufferId, WebGLProgramId}; use webrender_traits::{WebGLRenderbufferId, WebGLShaderId, WebGLTextureId}; @@ -317,9 +316,10 @@ unsafe impl<A: JSTraceable, B: JSTraceable, C: JSTraceable> JSTraceable for (A, } } -unsafe_no_jsmanaged_fields!(bool, f32, f64, String, ServoUrl, AtomicBool, AtomicUsize, UrlOrigin, Uuid, char); +unsafe_no_jsmanaged_fields!(bool, f32, f64, String, AtomicBool, AtomicUsize, Uuid, char); unsafe_no_jsmanaged_fields!(usize, u8, u16, u32, u64); unsafe_no_jsmanaged_fields!(isize, i8, i16, i32, i64); +unsafe_no_jsmanaged_fields!(ServoUrl, ImmutableOrigin, MutableOrigin); unsafe_no_jsmanaged_fields!(Image, ImageMetadata, ImageCacheChan, ImageCacheThread); unsafe_no_jsmanaged_fields!(Metadata); unsafe_no_jsmanaged_fields!(NetworkError); diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 56053555f7c..c836a46f1da 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -105,7 +105,6 @@ use net_traits::CoreResourceMsg::{GetCookiesForUrl, SetCookiesForUrl}; use net_traits::request::RequestInit; use net_traits::response::HttpsState; use num_traits::ToPrimitive; -use origin::Origin; use script_layout_interface::message::{Msg, ReflowQueryType}; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; use script_thread::{MainThreadScriptMsg, Runnable}; @@ -116,7 +115,7 @@ use script_traits::{TouchEventType, TouchId}; use script_traits::UntrustedNodeAddress; use servo_atoms::Atom; use servo_config::prefs::PREFS; -use servo_url::ServoUrl; +use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::{Cell, Ref, RefMut}; @@ -136,6 +135,7 @@ use style::str::{HTML_SPACE_CHARACTERS, split_html_space_chars, str_join}; use style::stylesheets::Stylesheet; use task_source::TaskSource; use time; +use url::Host; use url::percent_encoding::percent_decode; pub enum TouchEventResult { @@ -277,7 +277,7 @@ pub struct Document { https_state: Cell<HttpsState>, touchpad_pressure_phase: Cell<TouchpadPressurePhase>, /// The document's origin. - origin: Origin, + origin: MutableOrigin, /// https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-states referrer_policy: Cell<Option<ReferrerPolicy>>, /// https://html.spec.whatwg.org/multipage/#dom-document-referrer @@ -424,7 +424,7 @@ impl Document { } } - pub fn origin(&self) -> &Origin { + pub fn origin(&self) -> &MutableOrigin { &self.origin } @@ -1949,7 +1949,7 @@ impl Document { pub fn new_inherited(window: &Window, has_browsing_context: HasBrowsingContext, url: Option<ServoUrl>, - origin: Origin, + origin: MutableOrigin, is_html_document: IsHTMLDocument, content_type: Option<DOMString>, last_modified: Option<String>, @@ -2053,7 +2053,7 @@ impl Document { Ok(Document::new(window, HasBrowsingContext::No, None, - doc.origin().alias(), + doc.origin().clone(), IsHTMLDocument::NonHTMLDocument, None, None, @@ -2067,7 +2067,7 @@ impl Document { pub fn new(window: &Window, has_browsing_context: HasBrowsingContext, url: Option<ServoUrl>, - origin: Origin, + origin: MutableOrigin, doctype: IsHTMLDocument, content_type: Option<DOMString>, last_modified: Option<String>, @@ -2154,7 +2154,7 @@ impl Document { HasBrowsingContext::No, None, // https://github.com/whatwg/html/issues/2109 - Origin::opaque_identifier(), + MutableOrigin::new(ImmutableOrigin::new_opaque()), doctype, None, None, @@ -2411,16 +2411,17 @@ impl DocumentMethods for Document { // https://html.spec.whatwg.org/multipage/#relaxing-the-same-origin-restriction fn Domain(&self) -> DOMString { // Step 1. - if self.browsing_context().is_none() { + if !self.has_browsing_context { return DOMString::new(); } - if let Some(host) = self.origin.host() { - // Step 4. - DOMString::from(host.to_string()) - } else { + // Step 2. + match self.origin.effective_domain() { // Step 3. - DOMString::new() + None => DOMString::new(), + // Step 4. + Some(Host::Domain(domain)) => DOMString::from(domain), + Some(host) => DOMString::from(host.to_string()), } } @@ -3077,7 +3078,7 @@ impl DocumentMethods for Document { return Ok(DOMString::new()); } - if !self.origin.is_scheme_host_port_tuple() { + if !self.origin.is_tuple() { return Err(Error::Security); } @@ -3097,7 +3098,7 @@ impl DocumentMethods for Document { return Ok(()); } - if !self.origin.is_scheme_host_port_tuple() { + if !self.origin.is_tuple() { return Err(Error::Security); } diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs index 4ec27cc5b36..1de0a24863b 100644 --- a/components/script/dom/domimplementation.rs +++ b/components/script/dom/domimplementation.rs @@ -80,7 +80,7 @@ impl DOMImplementationMethods for DOMImplementation { let doc = XMLDocument::new(win, HasBrowsingContext::No, None, - self.document.origin().alias(), + self.document.origin().clone(), IsHTMLDocument::NonHTMLDocument, Some(DOMString::from(content_type)), None, @@ -127,7 +127,7 @@ impl DOMImplementationMethods for DOMImplementation { let doc = Document::new(win, HasBrowsingContext::No, None, - self.document.origin().alias(), + self.document.origin().clone(), IsHTMLDocument::HTMLDocument, None, None, diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs index d89ec3c1595..67d16934c66 100644 --- a/components/script/dom/domparser.rs +++ b/components/script/dom/domparser.rs @@ -61,7 +61,7 @@ impl DOMParserMethods for DOMParser { let document = Document::new(&self.window, HasBrowsingContext::No, Some(url.clone()), - doc.origin().alias(), + doc.origin().clone(), IsHTMLDocument::HTMLDocument, Some(content_type), None, @@ -79,7 +79,7 @@ impl DOMParserMethods for DOMParser { let document = Document::new(&self.window, HasBrowsingContext::No, Some(url.clone()), - doc.origin().alias(), + doc.origin().clone(), IsHTMLDocument::NonHTMLDocument, Some(content_type), None, diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 3a1c9daf1c9..4ab82735384 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -167,7 +167,7 @@ impl HTMLIFrameElement { layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize, }; - ScriptThread::process_attach_layout(new_layout_info, document.origin().alias()); + ScriptThread::process_attach_layout(new_layout_info, document.origin().clone()); } else { let load_info = IFrameLoadInfoWithData { info: load_info, diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index df335be75a6..96d3fceaff5 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -1729,7 +1729,7 @@ impl Node { let document = Document::new(window, HasBrowsingContext::No, Some(document.url()), // https://github.com/whatwg/dom/issues/378 - document.origin().alias(), + document.origin().clone(), is_html_doc, None, None, DocumentActivity::Inactive, DocumentSource::NotFromParser, loader, diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index 39077930200..149957576a2 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -110,7 +110,7 @@ impl ServoParser { let document = Document::new(window, HasBrowsingContext::No, Some(url.clone()), - context_document.origin().alias(), + context_document.origin().clone(), IsHTMLDocument::HTMLDocument, None, None, diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 1fbe57ba165..b6392fbdd19 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -62,7 +62,6 @@ use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread}; use net_traits::storage_thread::StorageType; use num_traits::ToPrimitive; use open; -use origin::Origin; use profile_traits::mem::ProfilerChan as MemProfilerChan; use profile_traits::time::ProfilerChan as TimeProfilerChan; use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64}; @@ -83,7 +82,7 @@ use servo_atoms::Atom; use servo_config::opts; use servo_config::prefs::PREFS; use servo_geometry::{f32_rect_to_au_rect, max_rect}; -use servo_url::ServoUrl; +use servo_url::{ImmutableOrigin, ServoUrl}; use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::Cell; @@ -660,10 +659,10 @@ impl WindowMethods for Window { "/" => { // TODO(#12715): Should be the origin of the incumbent settings // object, not self's. - Some(self.Document().origin().copy()) + Some(self.Document().origin().immutable().clone()) }, url => match ServoUrl::parse(&url) { - Ok(url) => Some(Origin::new(&url)), + Ok(url) => Some(url.origin().clone()), Err(_) => return Err(Error::Syntax), } }; @@ -1793,13 +1792,13 @@ fn debug_reflow_events(id: PipelineId, goal: &ReflowGoal, query_type: &ReflowQue struct PostMessageHandler { destination: Trusted<Window>, - origin: Option<Origin>, + origin: Option<ImmutableOrigin>, message: StructuredCloneData, } impl PostMessageHandler { fn new(window: &Window, - origin: Option<Origin>, + origin: Option<ImmutableOrigin>, message: StructuredCloneData) -> PostMessageHandler { PostMessageHandler { destination: Trusted::new(window), diff --git a/components/script/dom/xmldocument.rs b/components/script/dom/xmldocument.rs index eaf90fbfe01..c832e018360 100644 --- a/components/script/dom/xmldocument.rs +++ b/components/script/dom/xmldocument.rs @@ -15,9 +15,8 @@ use dom::location::Location; use dom::node::Node; use dom::window::Window; use js::jsapi::{JSContext, JSObject}; -use origin::Origin; use script_traits::DocumentActivity; -use servo_url::ServoUrl; +use servo_url::{MutableOrigin, ServoUrl}; // https://dom.spec.whatwg.org/#xmldocument #[dom_struct] @@ -29,7 +28,7 @@ impl XMLDocument { fn new_inherited(window: &Window, has_browsing_context: HasBrowsingContext, url: Option<ServoUrl>, - origin: Origin, + origin: MutableOrigin, is_html_document: IsHTMLDocument, content_type: Option<DOMString>, last_modified: Option<String>, @@ -55,7 +54,7 @@ impl XMLDocument { pub fn new(window: &Window, has_browsing_context: HasBrowsingContext, url: Option<ServoUrl>, - origin: Origin, + origin: MutableOrigin, doctype: IsHTMLDocument, content_type: Option<DOMString>, last_modified: Option<String>, diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 6fe89476994..c5c3c635129 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -1225,7 +1225,7 @@ impl XMLHttpRequest { Document::new(win, HasBrowsingContext::No, parsed_url, - doc.origin().alias(), + doc.origin().clone(), is_html_document, content_type, None, diff --git a/components/script/lib.rs b/components/script/lib.rs index 8a2829059c0..e5c93357bd2 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -114,7 +114,6 @@ pub mod layout_wrapper; mod mem; mod microtask; mod network_listener; -pub mod origin; pub mod script_runtime; #[allow(unsafe_code)] pub mod script_thread; diff --git a/components/script/origin.rs b/components/script/origin.rs deleted file mode 100644 index 067eb77dcda..00000000000 --- a/components/script/origin.rs +++ /dev/null @@ -1,61 +0,0 @@ -/* 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 http://mozilla.org/MPL/2.0/. */ - -use servo_url::ServoUrl; -use std::sync::Arc; -use url::Host; -use url::Origin as UrlOrigin; - -/// A representation of an [origin](https://html.spec.whatwg.org/multipage/#origin-2). -#[derive(HeapSizeOf, JSTraceable)] -pub struct Origin { - #[ignore_heap_size_of = "Arc<T> has unclear ownership semantics"] - inner: Arc<UrlOrigin>, -} - -impl Origin { - /// Create a new origin comprising a unique, opaque identifier. - pub fn opaque_identifier() -> Origin { - Origin { - inner: Arc::new(UrlOrigin::new_opaque()), - } - } - - /// Create a new origin for the given URL. - pub fn new(url: &ServoUrl) -> Origin { - Origin { - inner: Arc::new(url.origin()), - } - } - - /// Does this origin represent a host/scheme/port tuple? - pub fn is_scheme_host_port_tuple(&self) -> bool { - self.inner.is_tuple() - } - - /// Return the host associated with this origin. - pub fn host(&self) -> Option<&Host<String>> { - match *self.inner { - UrlOrigin::Tuple(_, ref host, _) => Some(host), - UrlOrigin::Opaque(..) => None, - } - } - - /// https://html.spec.whatwg.org/multipage/#same-origin - pub fn same_origin(&self, other: &Origin) -> bool { - self.inner == other.inner - } - - pub fn copy(&self) -> Origin { - Origin { - inner: Arc::new((*self.inner).clone()), - } - } - - pub fn alias(&self) -> Origin { - Origin { - inner: self.inner.clone(), - } - } -} diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index ac093a7a5df..2ab421c707b 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -77,7 +77,6 @@ use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCach use net_traits::request::{CredentialsMode, Destination, RequestInit}; use net_traits::storage_thread::StorageType; use network_listener::NetworkListener; -use origin::Origin; use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan}; use profile_traits::time::{self, ProfilerCategory, profile}; use script_layout_interface::message::{self, NewLayoutThreadInfo, ReflowQueryType}; @@ -95,7 +94,7 @@ use script_traits::WebVREventMsg; use script_traits::webdriver_msg::WebDriverScriptCommand; use serviceworkerjob::{Job, JobQueue, AsyncJobHandler}; use servo_config::opts; -use servo_url::ServoUrl; +use servo_url::{MutableOrigin, ServoUrl}; use std::cell::Cell; use std::collections::{hash_map, HashMap, HashSet}; use std::default::Default; @@ -155,7 +154,8 @@ struct InProgressLoad { is_visible: bool, /// The requested URL of the load. url: ServoUrl, - origin: Origin, + /// The origin for the document + origin: MutableOrigin, } impl InProgressLoad { @@ -166,7 +166,7 @@ impl InProgressLoad { layout_chan: Sender<message::Msg>, window_size: Option<WindowSizeData>, url: ServoUrl, - origin: Origin) -> InProgressLoad { + origin: MutableOrigin) -> InProgressLoad { InProgressLoad { pipeline_id: id, frame_id: frame_id, @@ -545,7 +545,7 @@ impl ScriptThreadFactory for ScriptThread { let mut failsafe = ScriptMemoryFailsafe::new(&script_thread); - let origin = Origin::new(&load_data.url); + let origin = MutableOrigin::new(load_data.url.origin()); let new_load = InProgressLoad::new(id, frame_id, parent_info, layout_chan, window_size, load_data.url.clone(), origin); script_thread.start_page_load(new_load, load_data); @@ -611,7 +611,7 @@ impl ScriptThread { }); } - pub fn process_attach_layout(new_layout_info: NewLayoutInfo, origin: Origin) { + pub fn process_attach_layout(new_layout_info: NewLayoutInfo, origin: MutableOrigin) { SCRIPT_THREAD_ROOT.with(|root| { if let Some(script_thread) = root.get() { let script_thread = unsafe { &*script_thread }; @@ -791,7 +791,7 @@ impl ScriptThread { FromConstellation(ConstellationControlMsg::AttachLayout( new_layout_info)) => { self.profile_event(ScriptThreadEventCategory::AttachLayout, || { - let origin = Origin::new(&new_layout_info.load_data.url); + let origin = MutableOrigin::new(new_layout_info.load_data.url.origin()); self.handle_new_layout(new_layout_info, origin); }) } @@ -1208,7 +1208,7 @@ impl ScriptThread { window.set_scroll_offsets(scroll_offsets) } - fn handle_new_layout(&self, new_layout_info: NewLayoutInfo, origin: Origin) { + fn handle_new_layout(&self, new_layout_info: NewLayoutInfo, origin: MutableOrigin) { let NewLayoutInfo { parent_info, new_pipeline_id, diff --git a/components/url/Cargo.toml b/components/url/Cargo.toml index e6acfe07649..4cefa0611c6 100644 --- a/components/url/Cargo.toml +++ b/components/url/Cargo.toml @@ -10,11 +10,14 @@ name = "servo_url" path = "lib.rs" [features] -servo = ["heapsize", "heapsize_derive", "serde", "url/heap_size", "url_serde"] +servo = ["heapsize", "heapsize_derive", "serde", "serde_derive", "uuid/serde", "url/heap_size", "url_serde"] [dependencies] heapsize = {version = "0.3.0", optional = true} heapsize_derive = {version = "0.1", optional = true} serde = {version = "0.9", optional = true} +serde_derive = {version = "0.9", optional = true} +servo_rand = {path = "../rand"} url = "1.2" -url_serde = {version = "0.1", optional = true} +url_serde = {version = "0.1.3", optional = true} +uuid = {version = "0.4.0", features = ["v4"]} diff --git a/components/url/lib.rs b/components/url/lib.rs index 85933a509c7..e8d8d363fbf 100644 --- a/components/url/lib.rs +++ b/components/url/lib.rs @@ -7,19 +7,26 @@ #![crate_name = "servo_url"] #![crate_type = "rlib"] -#[cfg(feature = "servo")] extern crate heapsize; +#[cfg(feature = "servo")] #[macro_use] extern crate heapsize; #[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive; #[cfg(feature = "servo")] extern crate serde; +#[cfg(feature = "servo")] #[macro_use] extern crate serde_derive; #[cfg(feature = "servo")] extern crate url_serde; +extern crate servo_rand; extern crate url; +extern crate uuid; + +pub mod origin; + +pub use origin::{OpaqueOrigin, ImmutableOrigin, MutableOrigin}; use std::fmt; use std::net::IpAddr; use std::ops::{Range, RangeFrom, RangeTo, RangeFull, Index}; use std::path::Path; use std::sync::Arc; -use url::{Url, Origin, Position}; +use url::{Url, Position}; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] @@ -68,8 +75,8 @@ impl ServoUrl { self.0.path() } - pub fn origin(&self) -> Origin { - self.0.origin() + pub fn origin(&self) -> ImmutableOrigin { + ImmutableOrigin::new(self.0.origin()) } pub fn scheme(&self) -> &str { diff --git a/components/url/origin.rs b/components/url/origin.rs new file mode 100644 index 00000000000..3795b73fb61 --- /dev/null +++ b/components/url/origin.rs @@ -0,0 +1,172 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +use servo_rand; +use servo_rand::Rng; +use std::cell::RefCell; +use std::rc::Rc; +use url::{Host, Origin}; +#[cfg(feature = "servo")] use url_serde; +use uuid::Uuid; + +/// The origin of an URL +#[derive(PartialEq, Eq, Clone, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] +pub enum ImmutableOrigin { + /// A globally unique identifier + Opaque(OpaqueOrigin), + + /// Consists of the URL's scheme, host and port + Tuple( + String, + #[cfg_attr(feature = "servo", + serde(deserialize_with = "url_serde::deserialize", serialize_with = "url_serde::serialize"))] + Host, + u16, + ) +} + +impl ImmutableOrigin { + pub fn new(origin: Origin) -> ImmutableOrigin { + match origin { + Origin::Opaque(_) => ImmutableOrigin::new_opaque(), + Origin::Tuple(scheme, host, port) => ImmutableOrigin::Tuple(scheme, host, port), + } + } + + pub fn same_origin(&self, other: &MutableOrigin) -> bool { + self == other.immutable() + } + + pub fn same_origin_domain(&self, other: &MutableOrigin) -> bool { + !other.has_domain() && self == other.immutable() + } + + /// Creates a new opaque origin that is only equal to itself. + pub fn new_opaque() -> ImmutableOrigin { + ImmutableOrigin::Opaque(OpaqueOrigin(servo_rand::thread_rng().gen())) + } + + pub fn scheme(&self) -> Option<&str> { + match *self { + ImmutableOrigin::Opaque(_) => None, + ImmutableOrigin::Tuple(ref scheme, _, _) => Some(&**scheme), + } + } + + pub fn host(&self) -> Option<&Host> { + match *self { + ImmutableOrigin::Opaque(_) => None, + ImmutableOrigin::Tuple(_, ref host, _) => Some(host), + } + } + + pub fn port(&self) -> Option<u16> { + match *self { + ImmutableOrigin::Opaque(_) => None, + ImmutableOrigin::Tuple(_, _, port) => Some(port), + } + } + + pub fn into_url_origin(self) -> Origin { + match self { + ImmutableOrigin::Opaque(_) => Origin::new_opaque(), + ImmutableOrigin::Tuple(scheme, host, port) => Origin::Tuple(scheme, host, port), + } + } + + /// Return whether this origin is a (scheme, host, port) tuple + /// (as opposed to an opaque origin). + pub fn is_tuple(&self) -> bool { + match *self { + ImmutableOrigin::Opaque(..) => false, + ImmutableOrigin::Tuple(..) => true, + } + } + + /// https://html.spec.whatwg.org/multipage/#ascii-serialisation-of-an-origin + pub fn ascii_serialization(&self) -> String { + self.clone().into_url_origin().ascii_serialization() + } + + /// https://html.spec.whatwg.org/multipage/#unicode-serialisation-of-an-origin + pub fn unicode_serialization(&self) -> String { + self.clone().into_url_origin().unicode_serialization() + } +} + +/// Opaque identifier for URLs that have file or other schemes +#[derive(Eq, PartialEq, Clone, Debug)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +pub struct OpaqueOrigin(Uuid); + +#[cfg(feature = "servo")] +known_heap_size!(0, OpaqueOrigin); + +/// A representation of an [origin](https://html.spec.whatwg.org/multipage/#origin-2). +#[derive(Clone, Debug)] +pub struct MutableOrigin(Rc<(ImmutableOrigin, RefCell<Option<Host>>)>); + +#[cfg(feature = "servo")] +known_heap_size!(0, MutableOrigin); + +impl MutableOrigin { + pub fn new(origin: ImmutableOrigin) -> MutableOrigin { + MutableOrigin(Rc::new((origin, RefCell::new(None)))) + } + + pub fn immutable(&self) -> &ImmutableOrigin { + &(self.0).0 + } + + pub fn is_tuple(&self) -> bool { + self.immutable().is_tuple() + } + + pub fn scheme(&self) -> Option<&str> { + self.immutable().scheme() + } + + pub fn host(&self) -> Option<&Host> { + self.immutable().host() + } + + pub fn port(&self) -> Option<u16> { + self.immutable().port() + } + + pub fn same_origin(&self, other: &MutableOrigin) -> bool { + self.immutable() == other.immutable() + } + + pub fn same_origin_domain(&self, other: &MutableOrigin) -> bool { + if let Some(ref self_domain) = *(self.0).1.borrow() { + if let Some(ref other_domain) = *(other.0).1.borrow() { + self_domain == other_domain && + self.immutable().scheme() == other.immutable().scheme() + } else { + false + } + } else { + self.immutable().same_origin_domain(other) + } + } + + pub fn domain(&self) -> Option<Host> { + (self.0).1.borrow().clone() + } + + pub fn set_domain(&self, domain: Host) { + *(self.0).1.borrow_mut() = Some(domain); + } + + pub fn has_domain(&self) -> bool { + (self.0).1.borrow().is_some() + } + + pub fn effective_domain(&self) -> Option<Host> { + self.immutable().host() + .map(|host| self.domain().unwrap_or_else(|| host.clone())) + } +} diff --git a/tests/unit/net/fetch.rs b/tests/unit/net/fetch.rs index 4329e44884d..43940f28a9f 100644 --- a/tests/unit/net/fetch.rs +++ b/tests/unit/net/fetch.rs @@ -34,7 +34,7 @@ use net_traits::ReferrerPolicy; use net_traits::request::{Origin, RedirectMode, Referrer, Request, RequestMode}; use net_traits::response::{CacheState, Response, ResponseBody, ResponseType}; use servo_config::resource_files::resources_dir_path; -use servo_url::ServoUrl; +use servo_url::{ImmutableOrigin, ServoUrl}; use std::fs::File; use std::io::Read; use std::rc::Rc; @@ -43,7 +43,6 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::{Sender, channel}; use time::{self, Duration}; use unicase::UniCase; -use url::Origin as UrlOrigin; // TODO write a struct that impls Handler for storing test values @@ -223,7 +222,7 @@ fn test_cors_preflight_fetch() { let target_url = url.clone().join("a.html").unwrap(); - let origin = Origin::Origin(UrlOrigin::new_opaque()); + let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let mut request = Request::new(url.clone(), Some(origin), false, None); *request.referrer.borrow_mut() = Referrer::ReferrerUrl(target_url); *request.referrer_policy.get_mut() = Some(ReferrerPolicy::Origin); @@ -260,7 +259,7 @@ fn test_cors_preflight_cache_fetch() { }; let (mut server, url) = make_server(handler); - let origin = Origin::Origin(UrlOrigin::new_opaque()); + let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let mut request = Request::new(url.clone(), Some(origin.clone()), false, None); *request.referrer.borrow_mut() = Referrer::NoReferrer; request.use_cors_preflight = true; @@ -309,7 +308,7 @@ fn test_cors_preflight_fetch_network_error() { }; let (mut server, url) = make_server(handler); - let origin = Origin::Origin(UrlOrigin::new_opaque()); + let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let mut request = Request::new(url, Some(origin), false, None); *request.method.borrow_mut() = Method::Extension("CHICKEN".to_owned()); *request.referrer.borrow_mut() = Referrer::NoReferrer; @@ -378,7 +377,7 @@ fn test_fetch_response_is_cors_filtered() { let (mut server, url) = make_server(handler); // an origin mis-match will stop it from defaulting to a basic filtered response - let origin = Origin::Origin(UrlOrigin::new_opaque()); + let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let mut request = Request::new(url, Some(origin), false, None); *request.referrer.borrow_mut() = Referrer::NoReferrer; request.mode = RequestMode::CorsMode; @@ -410,7 +409,7 @@ fn test_fetch_response_is_opaque_filtered() { let (mut server, url) = make_server(handler); // an origin mis-match will fall through to an Opaque filtered response - let origin = Origin::Origin(UrlOrigin::new_opaque()); + let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let request = Request::new(url, Some(origin), false, None); *request.referrer.borrow_mut() = Referrer::NoReferrer; let fetch_response = fetch(request, None); @@ -800,7 +799,7 @@ fn test_opaque_filtered_fetch_async_returns_complete_response() { let (mut server, url) = make_server(handler); // an origin mis-match will fall through to an Opaque filtered response - let origin = Origin::Origin(UrlOrigin::new_opaque()); + let origin = Origin::Origin(ImmutableOrigin::new_opaque()); let request = Request::new(url, Some(origin), false, None); *request.referrer.borrow_mut() = Referrer::NoReferrer; diff --git a/tests/unit/script/origin.rs b/tests/unit/script/origin.rs index 6357587da89..526b12bf0f9 100644 --- a/tests/unit/script/origin.rs +++ b/tests/unit/script/origin.rs @@ -2,46 +2,45 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use script::origin::Origin; -use servo_url::ServoUrl; +use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; #[test] fn same_origin() { - let a = Origin::new(&ServoUrl::parse("http://example.com/a.html").unwrap()); - let b = Origin::new(&ServoUrl::parse("http://example.com/b.html").unwrap()); + let a = MutableOrigin::new(ServoUrl::parse("http://example.com/a.html").unwrap().origin()); + let b = MutableOrigin::new(ServoUrl::parse("http://example.com/b.html").unwrap().origin()); assert!(a.same_origin(&b)); - assert_eq!(a.is_scheme_host_port_tuple(), true); + assert_eq!(a.is_tuple(), true); } #[test] fn identical_origin() { - let a = Origin::new(&ServoUrl::parse("http://example.com/a.html").unwrap()); + let a = MutableOrigin::new(ServoUrl::parse("http://example.com/a.html").unwrap().origin()); assert!(a.same_origin(&a)); } #[test] fn cross_origin() { - let a = Origin::new(&ServoUrl::parse("http://example.com/a.html").unwrap()); - let b = Origin::new(&ServoUrl::parse("http://example.org/b.html").unwrap()); + let a = MutableOrigin::new(ServoUrl::parse("http://example.com/a.html").unwrap().origin()); + let b = MutableOrigin::new(ServoUrl::parse("http://example.org/b.html").unwrap().origin()); assert!(!a.same_origin(&b)); } #[test] -fn alias_same_origin() { - let a = Origin::new(&ServoUrl::parse("http://example.com/a.html").unwrap()); - let b = Origin::new(&ServoUrl::parse("http://example.com/b.html").unwrap()); - let c = b.alias(); +fn clone_same_origin() { + let a = MutableOrigin::new(ServoUrl::parse("http://example.com/a.html").unwrap().origin()); + let b = MutableOrigin::new(ServoUrl::parse("http://example.com/b.html").unwrap().origin()); + let c = b.clone(); assert!(a.same_origin(&c)); assert!(b.same_origin(&b)); assert!(c.same_origin(&b)); - assert_eq!(c.is_scheme_host_port_tuple(), true); + assert_eq!(c.is_tuple(), true); } #[test] -fn alias_cross_origin() { - let a = Origin::new(&ServoUrl::parse("http://example.com/a.html").unwrap()); - let b = Origin::new(&ServoUrl::parse("http://example.org/b.html").unwrap()); - let c = b.alias(); +fn clone_cross_origin() { + let a = MutableOrigin::new(ServoUrl::parse("http://example.com/a.html").unwrap().origin()); + let b = MutableOrigin::new(ServoUrl::parse("http://example.org/b.html").unwrap().origin()); + let c = b.clone(); assert!(!a.same_origin(&c)); assert!(b.same_origin(&c)); assert!(c.same_origin(&c)); @@ -49,16 +48,16 @@ fn alias_cross_origin() { #[test] fn opaque() { - let a = Origin::opaque_identifier(); - let b = Origin::opaque_identifier(); + let a = MutableOrigin::new(ImmutableOrigin::new_opaque()); + let b = MutableOrigin::new(ImmutableOrigin::new_opaque()); assert!(!a.same_origin(&b)); - assert_eq!(a.is_scheme_host_port_tuple(), false); + assert_eq!(a.is_tuple(), false); } #[test] fn opaque_clone() { - let a = Origin::opaque_identifier(); - let b = a.alias(); + let a = MutableOrigin::new(ImmutableOrigin::new_opaque()); + let b = a.clone(); assert!(a.same_origin(&b)); - assert_eq!(a.is_scheme_host_port_tuple(), false); + assert_eq!(a.is_tuple(), false); } |