Add ImmutableOrigin to allow for serializing origins

This commit is contained in:
Connor Brewster 2017-01-20 13:21:23 -06:00 committed by Alan Jeffrey
parent 4f7e422054
commit bfd7b950ad
21 changed files with 270 additions and 152 deletions

3
Cargo.lock generated
View file

@ -2596,8 +2596,11 @@ dependencies = [
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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 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 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)", "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]] [[package]]

View file

@ -37,7 +37,7 @@ use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType};
use openssl; use openssl;
use openssl::ssl::error::{OpensslError, SslError}; use openssl::ssl::error::{OpensslError, SslError};
use resource_thread::AuthCache; use resource_thread::AuthCache;
use servo_url::ServoUrl; use servo_url::{ImmutableOrigin, ServoUrl};
use std::collections::HashSet; use std::collections::HashSet;
use std::error::Error; use std::error::Error;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
@ -51,7 +51,6 @@ use std::thread;
use time; use time;
use time::Tm; use time::Tm;
use unicase::UniCase; use unicase::UniCase;
use url::Origin as UrlOrigin;
use uuid; use uuid;
fn read_block<R: Read>(reader: &mut R) -> Result<Data, ()> { 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)); 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()) { if let Some(ref auth_entry) = auth_cache.read().unwrap().entries.get(&origin.ascii_serialization()) {
let user_name = auth_entry.user_name.clone(); let user_name = auth_entry.user_name.clone();
let password = Some(auth_entry.password.clone()); let password = Some(auth_entry.password.clone());
@ -767,7 +766,7 @@ fn http_redirect_fetch(request: Rc<Request>,
// Step 9 // Step 9
if cors_flag && !same_origin { 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 // Step 10

View file

@ -6,10 +6,9 @@ use ReferrerPolicy;
use hyper::header::Headers; use hyper::header::Headers;
use hyper::method::Method; use hyper::method::Method;
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use servo_url::ServoUrl; use servo_url::{ImmutableOrigin, ServoUrl};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::default::Default; use std::default::Default;
use url::Origin as UrlOrigin;
/// An [initiator](https://fetch.spec.whatwg.org/#concept-request-initiator) /// An [initiator](https://fetch.spec.whatwg.org/#concept-request-initiator)
#[derive(Copy, Clone, PartialEq, HeapSizeOf)] #[derive(Copy, Clone, PartialEq, HeapSizeOf)]
@ -55,10 +54,10 @@ pub enum Destination {
} }
/// A request [origin](https://fetch.spec.whatwg.org/#concept-request-origin) /// 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 { pub enum Origin {
Client, Client,
Origin(UrlOrigin), Origin(ImmutableOrigin),
} }
/// A [referer](https://fetch.spec.whatwg.org/#concept-request-referrer) /// A [referer](https://fetch.spec.whatwg.org/#concept-request-referrer)

View file

@ -79,7 +79,7 @@ use script_traits::{UntrustedNodeAddress, WindowSizeData, WindowSizeType};
use selectors::matching::ElementSelectorFlags; use selectors::matching::ElementSelectorFlags;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use servo_atoms::Atom; use servo_atoms::Atom;
use servo_url::ServoUrl; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::cell::{Cell, RefCell, UnsafeCell}; use std::cell::{Cell, RefCell, UnsafeCell};
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
@ -104,7 +104,6 @@ use style::stylesheets::SupportsRule;
use style::values::specified::Length; use style::values::specified::Length;
use style::viewport::ViewportRule; use style::viewport::ViewportRule;
use time::Duration; use time::Duration;
use url::Origin as UrlOrigin;
use uuid::Uuid; use uuid::Uuid;
use webrender_traits::{WebGLBufferId, WebGLError, WebGLFramebufferId, WebGLProgramId}; use webrender_traits::{WebGLBufferId, WebGLError, WebGLFramebufferId, WebGLProgramId};
use webrender_traits::{WebGLRenderbufferId, WebGLShaderId, WebGLTextureId}; 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!(usize, u8, u16, u32, u64);
unsafe_no_jsmanaged_fields!(isize, i8, i16, i32, i64); 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!(Image, ImageMetadata, ImageCacheChan, ImageCacheThread);
unsafe_no_jsmanaged_fields!(Metadata); unsafe_no_jsmanaged_fields!(Metadata);
unsafe_no_jsmanaged_fields!(NetworkError); unsafe_no_jsmanaged_fields!(NetworkError);

View file

@ -105,7 +105,6 @@ use net_traits::CoreResourceMsg::{GetCookiesForUrl, SetCookiesForUrl};
use net_traits::request::RequestInit; use net_traits::request::RequestInit;
use net_traits::response::HttpsState; use net_traits::response::HttpsState;
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use origin::Origin;
use script_layout_interface::message::{Msg, ReflowQueryType}; use script_layout_interface::message::{Msg, ReflowQueryType};
use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory};
use script_thread::{MainThreadScriptMsg, Runnable}; use script_thread::{MainThreadScriptMsg, Runnable};
@ -116,7 +115,7 @@ use script_traits::{TouchEventType, TouchId};
use script_traits::UntrustedNodeAddress; use script_traits::UntrustedNodeAddress;
use servo_atoms::Atom; use servo_atoms::Atom;
use servo_config::prefs::PREFS; use servo_config::prefs::PREFS;
use servo_url::ServoUrl; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::{Cell, Ref, RefMut}; 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 style::stylesheets::Stylesheet;
use task_source::TaskSource; use task_source::TaskSource;
use time; use time;
use url::Host;
use url::percent_encoding::percent_decode; use url::percent_encoding::percent_decode;
pub enum TouchEventResult { pub enum TouchEventResult {
@ -277,7 +277,7 @@ pub struct Document {
https_state: Cell<HttpsState>, https_state: Cell<HttpsState>,
touchpad_pressure_phase: Cell<TouchpadPressurePhase>, touchpad_pressure_phase: Cell<TouchpadPressurePhase>,
/// The document's origin. /// The document's origin.
origin: Origin, origin: MutableOrigin,
/// https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-states /// https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-states
referrer_policy: Cell<Option<ReferrerPolicy>>, referrer_policy: Cell<Option<ReferrerPolicy>>,
/// https://html.spec.whatwg.org/multipage/#dom-document-referrer /// 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 &self.origin
} }
@ -1949,7 +1949,7 @@ impl Document {
pub fn new_inherited(window: &Window, pub fn new_inherited(window: &Window,
has_browsing_context: HasBrowsingContext, has_browsing_context: HasBrowsingContext,
url: Option<ServoUrl>, url: Option<ServoUrl>,
origin: Origin, origin: MutableOrigin,
is_html_document: IsHTMLDocument, is_html_document: IsHTMLDocument,
content_type: Option<DOMString>, content_type: Option<DOMString>,
last_modified: Option<String>, last_modified: Option<String>,
@ -2053,7 +2053,7 @@ impl Document {
Ok(Document::new(window, Ok(Document::new(window,
HasBrowsingContext::No, HasBrowsingContext::No,
None, None,
doc.origin().alias(), doc.origin().clone(),
IsHTMLDocument::NonHTMLDocument, IsHTMLDocument::NonHTMLDocument,
None, None,
None, None,
@ -2067,7 +2067,7 @@ impl Document {
pub fn new(window: &Window, pub fn new(window: &Window,
has_browsing_context: HasBrowsingContext, has_browsing_context: HasBrowsingContext,
url: Option<ServoUrl>, url: Option<ServoUrl>,
origin: Origin, origin: MutableOrigin,
doctype: IsHTMLDocument, doctype: IsHTMLDocument,
content_type: Option<DOMString>, content_type: Option<DOMString>,
last_modified: Option<String>, last_modified: Option<String>,
@ -2154,7 +2154,7 @@ impl Document {
HasBrowsingContext::No, HasBrowsingContext::No,
None, None,
// https://github.com/whatwg/html/issues/2109 // https://github.com/whatwg/html/issues/2109
Origin::opaque_identifier(), MutableOrigin::new(ImmutableOrigin::new_opaque()),
doctype, doctype,
None, None,
None, None,
@ -2411,16 +2411,17 @@ impl DocumentMethods for Document {
// https://html.spec.whatwg.org/multipage/#relaxing-the-same-origin-restriction // https://html.spec.whatwg.org/multipage/#relaxing-the-same-origin-restriction
fn Domain(&self) -> DOMString { fn Domain(&self) -> DOMString {
// Step 1. // Step 1.
if self.browsing_context().is_none() { if !self.has_browsing_context {
return DOMString::new(); return DOMString::new();
} }
if let Some(host) = self.origin.host() { // Step 2.
// Step 4. match self.origin.effective_domain() {
DOMString::from(host.to_string())
} else {
// Step 3. // 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()); return Ok(DOMString::new());
} }
if !self.origin.is_scheme_host_port_tuple() { if !self.origin.is_tuple() {
return Err(Error::Security); return Err(Error::Security);
} }
@ -3097,7 +3098,7 @@ impl DocumentMethods for Document {
return Ok(()); return Ok(());
} }
if !self.origin.is_scheme_host_port_tuple() { if !self.origin.is_tuple() {
return Err(Error::Security); return Err(Error::Security);
} }

View file

@ -80,7 +80,7 @@ impl DOMImplementationMethods for DOMImplementation {
let doc = XMLDocument::new(win, let doc = XMLDocument::new(win,
HasBrowsingContext::No, HasBrowsingContext::No,
None, None,
self.document.origin().alias(), self.document.origin().clone(),
IsHTMLDocument::NonHTMLDocument, IsHTMLDocument::NonHTMLDocument,
Some(DOMString::from(content_type)), Some(DOMString::from(content_type)),
None, None,
@ -127,7 +127,7 @@ impl DOMImplementationMethods for DOMImplementation {
let doc = Document::new(win, let doc = Document::new(win,
HasBrowsingContext::No, HasBrowsingContext::No,
None, None,
self.document.origin().alias(), self.document.origin().clone(),
IsHTMLDocument::HTMLDocument, IsHTMLDocument::HTMLDocument,
None, None,
None, None,

View file

@ -61,7 +61,7 @@ impl DOMParserMethods for DOMParser {
let document = Document::new(&self.window, let document = Document::new(&self.window,
HasBrowsingContext::No, HasBrowsingContext::No,
Some(url.clone()), Some(url.clone()),
doc.origin().alias(), doc.origin().clone(),
IsHTMLDocument::HTMLDocument, IsHTMLDocument::HTMLDocument,
Some(content_type), Some(content_type),
None, None,
@ -79,7 +79,7 @@ impl DOMParserMethods for DOMParser {
let document = Document::new(&self.window, let document = Document::new(&self.window,
HasBrowsingContext::No, HasBrowsingContext::No,
Some(url.clone()), Some(url.clone()),
doc.origin().alias(), doc.origin().clone(),
IsHTMLDocument::NonHTMLDocument, IsHTMLDocument::NonHTMLDocument,
Some(content_type), Some(content_type),
None, None,

View file

@ -167,7 +167,7 @@ impl HTMLIFrameElement {
layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize, 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 { } else {
let load_info = IFrameLoadInfoWithData { let load_info = IFrameLoadInfoWithData {
info: load_info, info: load_info,

View file

@ -1729,7 +1729,7 @@ impl Node {
let document = Document::new(window, HasBrowsingContext::No, let document = Document::new(window, HasBrowsingContext::No,
Some(document.url()), Some(document.url()),
// https://github.com/whatwg/dom/issues/378 // https://github.com/whatwg/dom/issues/378
document.origin().alias(), document.origin().clone(),
is_html_doc, None, is_html_doc, None,
None, DocumentActivity::Inactive, None, DocumentActivity::Inactive,
DocumentSource::NotFromParser, loader, DocumentSource::NotFromParser, loader,

View file

@ -110,7 +110,7 @@ impl ServoParser {
let document = Document::new(window, let document = Document::new(window,
HasBrowsingContext::No, HasBrowsingContext::No,
Some(url.clone()), Some(url.clone()),
context_document.origin().alias(), context_document.origin().clone(),
IsHTMLDocument::HTMLDocument, IsHTMLDocument::HTMLDocument,
None, None,
None, None,

View file

@ -62,7 +62,6 @@ use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
use net_traits::storage_thread::StorageType; use net_traits::storage_thread::StorageType;
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use open; use open;
use origin::Origin;
use profile_traits::mem::ProfilerChan as MemProfilerChan; use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::time::ProfilerChan as TimeProfilerChan; use profile_traits::time::ProfilerChan as TimeProfilerChan;
use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64}; use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64};
@ -83,7 +82,7 @@ use servo_atoms::Atom;
use servo_config::opts; use servo_config::opts;
use servo_config::prefs::PREFS; use servo_config::prefs::PREFS;
use servo_geometry::{f32_rect_to_au_rect, max_rect}; 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::ascii::AsciiExt;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::Cell; use std::cell::Cell;
@ -660,10 +659,10 @@ impl WindowMethods for Window {
"/" => { "/" => {
// TODO(#12715): Should be the origin of the incumbent settings // TODO(#12715): Should be the origin of the incumbent settings
// object, not self's. // object, not self's.
Some(self.Document().origin().copy()) Some(self.Document().origin().immutable().clone())
}, },
url => match ServoUrl::parse(&url) { url => match ServoUrl::parse(&url) {
Ok(url) => Some(Origin::new(&url)), Ok(url) => Some(url.origin().clone()),
Err(_) => return Err(Error::Syntax), Err(_) => return Err(Error::Syntax),
} }
}; };
@ -1793,13 +1792,13 @@ fn debug_reflow_events(id: PipelineId, goal: &ReflowGoal, query_type: &ReflowQue
struct PostMessageHandler { struct PostMessageHandler {
destination: Trusted<Window>, destination: Trusted<Window>,
origin: Option<Origin>, origin: Option<ImmutableOrigin>,
message: StructuredCloneData, message: StructuredCloneData,
} }
impl PostMessageHandler { impl PostMessageHandler {
fn new(window: &Window, fn new(window: &Window,
origin: Option<Origin>, origin: Option<ImmutableOrigin>,
message: StructuredCloneData) -> PostMessageHandler { message: StructuredCloneData) -> PostMessageHandler {
PostMessageHandler { PostMessageHandler {
destination: Trusted::new(window), destination: Trusted::new(window),

View file

@ -15,9 +15,8 @@ use dom::location::Location;
use dom::node::Node; use dom::node::Node;
use dom::window::Window; use dom::window::Window;
use js::jsapi::{JSContext, JSObject}; use js::jsapi::{JSContext, JSObject};
use origin::Origin;
use script_traits::DocumentActivity; use script_traits::DocumentActivity;
use servo_url::ServoUrl; use servo_url::{MutableOrigin, ServoUrl};
// https://dom.spec.whatwg.org/#xmldocument // https://dom.spec.whatwg.org/#xmldocument
#[dom_struct] #[dom_struct]
@ -29,7 +28,7 @@ impl XMLDocument {
fn new_inherited(window: &Window, fn new_inherited(window: &Window,
has_browsing_context: HasBrowsingContext, has_browsing_context: HasBrowsingContext,
url: Option<ServoUrl>, url: Option<ServoUrl>,
origin: Origin, origin: MutableOrigin,
is_html_document: IsHTMLDocument, is_html_document: IsHTMLDocument,
content_type: Option<DOMString>, content_type: Option<DOMString>,
last_modified: Option<String>, last_modified: Option<String>,
@ -55,7 +54,7 @@ impl XMLDocument {
pub fn new(window: &Window, pub fn new(window: &Window,
has_browsing_context: HasBrowsingContext, has_browsing_context: HasBrowsingContext,
url: Option<ServoUrl>, url: Option<ServoUrl>,
origin: Origin, origin: MutableOrigin,
doctype: IsHTMLDocument, doctype: IsHTMLDocument,
content_type: Option<DOMString>, content_type: Option<DOMString>,
last_modified: Option<String>, last_modified: Option<String>,

View file

@ -1225,7 +1225,7 @@ impl XMLHttpRequest {
Document::new(win, Document::new(win,
HasBrowsingContext::No, HasBrowsingContext::No,
parsed_url, parsed_url,
doc.origin().alias(), doc.origin().clone(),
is_html_document, is_html_document,
content_type, content_type,
None, None,

View file

@ -114,7 +114,6 @@ pub mod layout_wrapper;
mod mem; mod mem;
mod microtask; mod microtask;
mod network_listener; mod network_listener;
pub mod origin;
pub mod script_runtime; pub mod script_runtime;
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub mod script_thread; pub mod script_thread;

View file

@ -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(),
}
}
}

View file

@ -77,7 +77,6 @@ use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCach
use net_traits::request::{CredentialsMode, Destination, RequestInit}; use net_traits::request::{CredentialsMode, Destination, RequestInit};
use net_traits::storage_thread::StorageType; use net_traits::storage_thread::StorageType;
use network_listener::NetworkListener; use network_listener::NetworkListener;
use origin::Origin;
use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan}; use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan};
use profile_traits::time::{self, ProfilerCategory, profile}; use profile_traits::time::{self, ProfilerCategory, profile};
use script_layout_interface::message::{self, NewLayoutThreadInfo, ReflowQueryType}; use script_layout_interface::message::{self, NewLayoutThreadInfo, ReflowQueryType};
@ -95,7 +94,7 @@ use script_traits::WebVREventMsg;
use script_traits::webdriver_msg::WebDriverScriptCommand; use script_traits::webdriver_msg::WebDriverScriptCommand;
use serviceworkerjob::{Job, JobQueue, AsyncJobHandler}; use serviceworkerjob::{Job, JobQueue, AsyncJobHandler};
use servo_config::opts; use servo_config::opts;
use servo_url::ServoUrl; use servo_url::{MutableOrigin, ServoUrl};
use std::cell::Cell; use std::cell::Cell;
use std::collections::{hash_map, HashMap, HashSet}; use std::collections::{hash_map, HashMap, HashSet};
use std::default::Default; use std::default::Default;
@ -155,7 +154,8 @@ struct InProgressLoad {
is_visible: bool, is_visible: bool,
/// The requested URL of the load. /// The requested URL of the load.
url: ServoUrl, url: ServoUrl,
origin: Origin, /// The origin for the document
origin: MutableOrigin,
} }
impl InProgressLoad { impl InProgressLoad {
@ -166,7 +166,7 @@ impl InProgressLoad {
layout_chan: Sender<message::Msg>, layout_chan: Sender<message::Msg>,
window_size: Option<WindowSizeData>, window_size: Option<WindowSizeData>,
url: ServoUrl, url: ServoUrl,
origin: Origin) -> InProgressLoad { origin: MutableOrigin) -> InProgressLoad {
InProgressLoad { InProgressLoad {
pipeline_id: id, pipeline_id: id,
frame_id: frame_id, frame_id: frame_id,
@ -545,7 +545,7 @@ impl ScriptThreadFactory for ScriptThread {
let mut failsafe = ScriptMemoryFailsafe::new(&script_thread); 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, let new_load = InProgressLoad::new(id, frame_id, parent_info, layout_chan, window_size,
load_data.url.clone(), origin); load_data.url.clone(), origin);
script_thread.start_page_load(new_load, load_data); 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| { SCRIPT_THREAD_ROOT.with(|root| {
if let Some(script_thread) = root.get() { if let Some(script_thread) = root.get() {
let script_thread = unsafe { &*script_thread }; let script_thread = unsafe { &*script_thread };
@ -791,7 +791,7 @@ impl ScriptThread {
FromConstellation(ConstellationControlMsg::AttachLayout( FromConstellation(ConstellationControlMsg::AttachLayout(
new_layout_info)) => { new_layout_info)) => {
self.profile_event(ScriptThreadEventCategory::AttachLayout, || { 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); self.handle_new_layout(new_layout_info, origin);
}) })
} }
@ -1208,7 +1208,7 @@ impl ScriptThread {
window.set_scroll_offsets(scroll_offsets) 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 { let NewLayoutInfo {
parent_info, parent_info,
new_pipeline_id, new_pipeline_id,

View file

@ -10,11 +10,14 @@ name = "servo_url"
path = "lib.rs" path = "lib.rs"
[features] [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] [dependencies]
heapsize = {version = "0.3.0", optional = true} heapsize = {version = "0.3.0", optional = true}
heapsize_derive = {version = "0.1", optional = true} heapsize_derive = {version = "0.1", optional = true}
serde = {version = "0.9", optional = true} serde = {version = "0.9", optional = true}
serde_derive = {version = "0.9", optional = true}
servo_rand = {path = "../rand"}
url = "1.2" 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"]}

View file

@ -7,19 +7,26 @@
#![crate_name = "servo_url"] #![crate_name = "servo_url"]
#![crate_type = "rlib"] #![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")] #[macro_use] extern crate heapsize_derive;
#[cfg(feature = "servo")] extern crate serde; #[cfg(feature = "servo")] extern crate serde;
#[cfg(feature = "servo")] #[macro_use] extern crate serde_derive;
#[cfg(feature = "servo")] extern crate url_serde; #[cfg(feature = "servo")] extern crate url_serde;
extern crate servo_rand;
extern crate url; extern crate url;
extern crate uuid;
pub mod origin;
pub use origin::{OpaqueOrigin, ImmutableOrigin, MutableOrigin};
use std::fmt; use std::fmt;
use std::net::IpAddr; use std::net::IpAddr;
use std::ops::{Range, RangeFrom, RangeTo, RangeFull, Index}; use std::ops::{Range, RangeFrom, RangeTo, RangeFull, Index};
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use url::{Url, Origin, Position}; use url::{Url, Position};
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -68,8 +75,8 @@ impl ServoUrl {
self.0.path() self.0.path()
} }
pub fn origin(&self) -> Origin { pub fn origin(&self) -> ImmutableOrigin {
self.0.origin() ImmutableOrigin::new(self.0.origin())
} }
pub fn scheme(&self) -> &str { pub fn scheme(&self) -> &str {

172
components/url/origin.rs Normal file
View file

@ -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()))
}
}

View file

@ -34,7 +34,7 @@ use net_traits::ReferrerPolicy;
use net_traits::request::{Origin, RedirectMode, Referrer, Request, RequestMode}; use net_traits::request::{Origin, RedirectMode, Referrer, Request, RequestMode};
use net_traits::response::{CacheState, Response, ResponseBody, ResponseType}; use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
use servo_config::resource_files::resources_dir_path; use servo_config::resource_files::resources_dir_path;
use servo_url::ServoUrl; use servo_url::{ImmutableOrigin, ServoUrl};
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
use std::rc::Rc; use std::rc::Rc;
@ -43,7 +43,6 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{Sender, channel}; use std::sync::mpsc::{Sender, channel};
use time::{self, Duration}; use time::{self, Duration};
use unicase::UniCase; use unicase::UniCase;
use url::Origin as UrlOrigin;
// TODO write a struct that impls Handler for storing test values // 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 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); let mut request = Request::new(url.clone(), Some(origin), false, None);
*request.referrer.borrow_mut() = Referrer::ReferrerUrl(target_url); *request.referrer.borrow_mut() = Referrer::ReferrerUrl(target_url);
*request.referrer_policy.get_mut() = Some(ReferrerPolicy::Origin); *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 (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); let mut request = Request::new(url.clone(), Some(origin.clone()), false, None);
*request.referrer.borrow_mut() = Referrer::NoReferrer; *request.referrer.borrow_mut() = Referrer::NoReferrer;
request.use_cors_preflight = true; request.use_cors_preflight = true;
@ -309,7 +308,7 @@ fn test_cors_preflight_fetch_network_error() {
}; };
let (mut server, url) = make_server(handler); 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); let mut request = Request::new(url, Some(origin), false, None);
*request.method.borrow_mut() = Method::Extension("CHICKEN".to_owned()); *request.method.borrow_mut() = Method::Extension("CHICKEN".to_owned());
*request.referrer.borrow_mut() = Referrer::NoReferrer; *request.referrer.borrow_mut() = Referrer::NoReferrer;
@ -378,7 +377,7 @@ fn test_fetch_response_is_cors_filtered() {
let (mut server, url) = make_server(handler); let (mut server, url) = make_server(handler);
// an origin mis-match will stop it from defaulting to a basic filtered response // 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); let mut request = Request::new(url, Some(origin), false, None);
*request.referrer.borrow_mut() = Referrer::NoReferrer; *request.referrer.borrow_mut() = Referrer::NoReferrer;
request.mode = RequestMode::CorsMode; request.mode = RequestMode::CorsMode;
@ -410,7 +409,7 @@ fn test_fetch_response_is_opaque_filtered() {
let (mut server, url) = make_server(handler); let (mut server, url) = make_server(handler);
// an origin mis-match will fall through to an Opaque filtered response // 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); let request = Request::new(url, Some(origin), false, None);
*request.referrer.borrow_mut() = Referrer::NoReferrer; *request.referrer.borrow_mut() = Referrer::NoReferrer;
let fetch_response = fetch(request, None); 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); let (mut server, url) = make_server(handler);
// an origin mis-match will fall through to an Opaque filtered response // 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); let request = Request::new(url, Some(origin), false, None);
*request.referrer.borrow_mut() = Referrer::NoReferrer; *request.referrer.borrow_mut() = Referrer::NoReferrer;

View file

@ -2,46 +2,45 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use script::origin::Origin; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use servo_url::ServoUrl;
#[test] #[test]
fn same_origin() { fn same_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());
let b = Origin::new(&ServoUrl::parse("http://example.com/b.html").unwrap()); let b = MutableOrigin::new(ServoUrl::parse("http://example.com/b.html").unwrap().origin());
assert!(a.same_origin(&b)); assert!(a.same_origin(&b));
assert_eq!(a.is_scheme_host_port_tuple(), true); assert_eq!(a.is_tuple(), true);
} }
#[test] #[test]
fn identical_origin() { 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)); assert!(a.same_origin(&a));
} }
#[test] #[test]
fn cross_origin() { fn cross_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());
let b = Origin::new(&ServoUrl::parse("http://example.org/b.html").unwrap()); let b = MutableOrigin::new(ServoUrl::parse("http://example.org/b.html").unwrap().origin());
assert!(!a.same_origin(&b)); assert!(!a.same_origin(&b));
} }
#[test] #[test]
fn alias_same_origin() { fn clone_same_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());
let b = Origin::new(&ServoUrl::parse("http://example.com/b.html").unwrap()); let b = MutableOrigin::new(ServoUrl::parse("http://example.com/b.html").unwrap().origin());
let c = b.alias(); let c = b.clone();
assert!(a.same_origin(&c)); assert!(a.same_origin(&c));
assert!(b.same_origin(&b)); assert!(b.same_origin(&b));
assert!(c.same_origin(&b)); assert!(c.same_origin(&b));
assert_eq!(c.is_scheme_host_port_tuple(), true); assert_eq!(c.is_tuple(), true);
} }
#[test] #[test]
fn alias_cross_origin() { fn clone_cross_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());
let b = Origin::new(&ServoUrl::parse("http://example.org/b.html").unwrap()); let b = MutableOrigin::new(ServoUrl::parse("http://example.org/b.html").unwrap().origin());
let c = b.alias(); let c = b.clone();
assert!(!a.same_origin(&c)); assert!(!a.same_origin(&c));
assert!(b.same_origin(&c)); assert!(b.same_origin(&c));
assert!(c.same_origin(&c)); assert!(c.same_origin(&c));
@ -49,16 +48,16 @@ fn alias_cross_origin() {
#[test] #[test]
fn opaque() { fn opaque() {
let a = Origin::opaque_identifier(); let a = MutableOrigin::new(ImmutableOrigin::new_opaque());
let b = Origin::opaque_identifier(); let b = MutableOrigin::new(ImmutableOrigin::new_opaque());
assert!(!a.same_origin(&b)); assert!(!a.same_origin(&b));
assert_eq!(a.is_scheme_host_port_tuple(), false); assert_eq!(a.is_tuple(), false);
} }
#[test] #[test]
fn opaque_clone() { fn opaque_clone() {
let a = Origin::opaque_identifier(); let a = MutableOrigin::new(ImmutableOrigin::new_opaque());
let b = a.alias(); let b = a.clone();
assert!(a.same_origin(&b)); assert!(a.same_origin(&b));
assert_eq!(a.is_scheme_host_port_tuple(), false); assert_eq!(a.is_tuple(), false);
} }