Implement origin concept.

This commit is contained in:
Josh Matthews 2015-09-11 12:24:25 -04:00 committed by Ms2ger
parent e8e354d5d3
commit a8233a135e
8 changed files with 215 additions and 9 deletions

View file

@ -89,6 +89,7 @@ use style::properties::PropertyDeclarationBlock;
use style::restyle_hints::ElementSnapshot; use style::restyle_hints::ElementSnapshot;
use style::selector_impl::PseudoElement; use style::selector_impl::PseudoElement;
use style::values::specified::Length; use style::values::specified::Length;
use url::Origin as UrlOrigin;
use url::Url; use url::Url;
use util::str::{DOMString, LengthOrPercentageOrAuto}; use util::str::{DOMString, LengthOrPercentageOrAuto};
use uuid::Uuid; use uuid::Uuid;
@ -276,7 +277,7 @@ impl<A: JSTraceable, B: JSTraceable, C: JSTraceable> JSTraceable for (A, B, C) {
} }
} }
no_jsmanaged_fields!(bool, f32, f64, String, Url, AtomicBool, AtomicUsize, Uuid); no_jsmanaged_fields!(bool, f32, f64, String, Url, AtomicBool, AtomicUsize, UrlOrigin, Uuid);
no_jsmanaged_fields!(usize, u8, u16, u32, u64); no_jsmanaged_fields!(usize, u8, u16, u32, u64);
no_jsmanaged_fields!(isize, i8, i16, i32, i64); no_jsmanaged_fields!(isize, i8, i16, i32, i64);
no_jsmanaged_fields!(Sender<T>); no_jsmanaged_fields!(Sender<T>);

View file

@ -94,6 +94,7 @@ use net_traits::CookieSource::NonHTTP;
use net_traits::response::HttpsState; use net_traits::response::HttpsState;
use net_traits::{AsyncResponseTarget, PendingAsyncLoad}; use net_traits::{AsyncResponseTarget, PendingAsyncLoad};
use num::ToPrimitive; use num::ToPrimitive;
use origin::Origin;
use script_runtime::ScriptChan; use script_runtime::ScriptChan;
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable}; use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable};
use script_traits::UntrustedNodeAddress; use script_traits::UntrustedNodeAddress;
@ -223,6 +224,8 @@ pub struct Document {
/// https://html.spec.whatwg.org/multipage/#concept-document-https-state /// https://html.spec.whatwg.org/multipage/#concept-document-https-state
https_state: Cell<HttpsState>, https_state: Cell<HttpsState>,
touchpad_pressure_phase: Cell<TouchpadPressurePhase>, touchpad_pressure_phase: Cell<TouchpadPressurePhase>,
/// The document's origin.
origin: Origin,
} }
#[derive(JSTraceable, HeapSizeOf)] #[derive(JSTraceable, HeapSizeOf)]
@ -1544,14 +1547,6 @@ impl Document {
/// https://html.spec.whatwg.org/multipage/#cookie-averse-document-object /// https://html.spec.whatwg.org/multipage/#cookie-averse-document-object
fn is_cookie_averse(&self) -> bool { fn is_cookie_averse(&self) -> bool {
/// https://url.spec.whatwg.org/#network-scheme
fn url_has_network_scheme(url: &Url) -> bool {
match &*url.scheme {
"ftp" | "http" | "https" => true,
_ => false,
}
}
self.browsing_context.is_none() || !url_has_network_scheme(&self.url) self.browsing_context.is_none() || !url_has_network_scheme(&self.url)
} }
@ -1590,6 +1585,14 @@ impl LayoutDocumentHelpers for LayoutJS<Document> {
} }
} }
/// https://url.spec.whatwg.org/#network-scheme
fn url_has_network_scheme(url: &Url) -> bool {
match &*url.scheme {
"ftp" | "http" | "https" => true,
_ => false,
}
}
impl Document { impl Document {
pub fn new_inherited(window: &Window, pub fn new_inherited(window: &Window,
browsing_context: Option<&BrowsingContext>, browsing_context: Option<&BrowsingContext>,
@ -1608,6 +1611,15 @@ impl Document {
(DocumentReadyState::Complete, true) (DocumentReadyState::Complete, true)
}; };
// Incomplete implementation of Document origin specification at
// https://html.spec.whatwg.org/multipage/#origin:document
let origin = if url_has_network_scheme(&url) {
Origin::new(&url)
} else {
// Default to DOM standard behaviour
Origin::opaque_identifier()
};
Document { Document {
node: Node::new_document_node(), node: Node::new_document_node(),
window: JS::from_ref(window), window: JS::from_ref(window),
@ -1673,6 +1685,7 @@ impl Document {
css_errors_store: DOMRefCell::new(vec![]), css_errors_store: DOMRefCell::new(vec![]),
https_state: Cell::new(HttpsState::None), https_state: Cell::new(HttpsState::None),
touchpad_pressure_phase: Cell::new(TouchpadPressurePhase::BeforeClick), touchpad_pressure_phase: Cell::new(TouchpadPressurePhase::BeforeClick),
origin: origin,
} }
} }

View file

@ -90,6 +90,7 @@ pub mod dom;
pub mod layout_interface; pub mod layout_interface;
mod mem; mod mem;
mod network_listener; mod network_listener;
pub mod origin;
pub mod page; pub mod page;
pub mod parse; pub mod parse;
pub mod reporter; pub mod reporter;

View file

@ -0,0 +1,73 @@
/* 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 std::cell::RefCell;
use std::rc::Rc;
use url::{OpaqueOrigin, Origin as UrlOrigin};
use url::{Url, Host};
/// A representation of an [origin](https://html.spec.whatwg.org/multipage/#origin-2).
#[derive(HeapSizeOf)]
pub struct Origin {
#[ignore_heap_size_of = "Rc<T> has unclear ownership semantics"]
inner: Rc<RefCell<UrlOrigin>>,
}
// We can't use RefCell inside JSTraceable, but Origin doesn't contain JS values and
// DOMRefCell makes it much harder to write unit tests (due to setting up required TLS).
no_jsmanaged_fields!(Origin);
impl Origin {
/// Create a new origin comprising a unique, opaque identifier.
pub fn opaque_identifier() -> Origin {
let opaque = UrlOrigin::UID(OpaqueOrigin::new());
Origin {
inner: Rc::new(RefCell::new(opaque)),
}
}
/// Create a new origin for the given URL.
pub fn new(url: &Url) -> Origin {
Origin {
inner: Rc::new(RefCell::new(url.origin())),
}
}
pub fn set(&self, origin: UrlOrigin) {
*self.inner.borrow_mut() = origin;
}
/// Does this origin represent a host/scheme/port tuple?
pub fn is_scheme_host_port_tuple(&self) -> bool {
match *self.inner.borrow() {
UrlOrigin::Tuple(..) => true,
UrlOrigin::UID(..) => false,
}
}
/// Return the host associated with this origin.
pub fn host(&self) -> Option<Host> {
match *self.inner.borrow() {
UrlOrigin::Tuple(_, ref host, _) => Some(host.clone()),
UrlOrigin::UID(..) => None,
}
}
/// https://html.spec.whatwg.org/multipage/#same-origin
pub fn same_origin(&self, other: &Origin) -> bool {
*self.inner.borrow() == *other.inner.borrow()
}
pub fn copy(&self) -> Origin {
Origin {
inner: Rc::new(RefCell::new(self.inner.borrow().clone())),
}
}
pub fn alias(&self) -> Origin {
Origin {
inner: self.inner.clone(),
}
}
}

View file

@ -1752,7 +1752,9 @@ name = "script_tests"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"msg 0.0.1", "msg 0.0.1",
"plugins 0.0.1",
"script 0.0.1", "script 0.0.1",
"url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1", "util 0.0.1",
] ]

View file

@ -11,8 +11,14 @@ doctest = false
[dependencies.msg] [dependencies.msg]
path = "../../../components/msg" path = "../../../components/msg"
[dependencies.plugins]
path = "../../../components/plugins"
[dependencies.script] [dependencies.script]
path = "../../../components/script" path = "../../../components/script"
[dependencies.util] [dependencies.util]
path = "../../../components/util" path = "../../../components/util"
[dependencies]
url = {version = "0.5.8", features = ["heap_size"]}

View file

@ -2,10 +2,15 @@
* 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/. */
#![feature(plugin)]
#![plugin(plugins)]
extern crate msg; extern crate msg;
extern crate script; extern crate script;
extern crate url;
extern crate util; extern crate util;
#[cfg(test)] mod origin;
#[cfg(all(test, target_pointer_width = "64"))] mod size_of; #[cfg(all(test, target_pointer_width = "64"))] mod size_of;
#[cfg(test)] mod textinput; #[cfg(test)] mod textinput;
#[cfg(test)] mod dom { #[cfg(test)] mod dom {

105
tests/unit/script/origin.rs Normal file
View file

@ -0,0 +1,105 @@
/* 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 script::origin::Origin;
#[test]
fn same_origin() {
let a = Origin::new(&url!("http://example.com/a.html"));
let b = Origin::new(&url!("http://example.com/b.html"));
assert!(a.same_origin(&b));
assert_eq!(a.is_scheme_host_port_tuple(), true);
}
#[test]
fn identical_origin() {
let a = Origin::new(&url!("http://example.com/a.html"));
assert!(a.same_origin(&a));
}
#[test]
fn cross_origin() {
let a = Origin::new(&url!("http://example.com/a.html"));
let b = Origin::new(&url!("http://example.org/b.html"));
assert!(!a.same_origin(&b));
}
#[test]
fn alias_same_origin() {
let a = Origin::new(&url!("http://example.com/a.html"));
let b = Origin::new(&url!("http://example.com/b.html"));
let c = b.alias();
assert!(a.same_origin(&c));
assert!(b.same_origin(&b));
assert!(c.same_origin(&b));
assert_eq!(c.is_scheme_host_port_tuple(), true);
}
#[test]
fn alias_cross_origin() {
let a = Origin::new(&url!("http://example.com/a.html"));
let b = Origin::new(&url!("http://example.org/b.html"));
let c = b.alias();
assert!(!a.same_origin(&c));
assert!(b.same_origin(&c));
assert!(c.same_origin(&c));
}
#[test]
fn alias_update_same_origin() {
let a = Origin::new(&url!("http://example.com/a.html"));
let b = Origin::new(&url!("http://example.org/b.html"));
let c = b.alias();
b.set(url!("http://example.com/c.html").origin());
assert!(a.same_origin(&c));
assert!(b.same_origin(&c));
assert!(c.same_origin(&c));
}
#[test]
fn alias_update_cross_origin() {
let a = Origin::new(&url!("http://example.com/a.html"));
let b = Origin::new(&url!("http://example.com/b.html"));
let c = b.alias();
b.set(url!("http://example.org/c.html").origin());
assert!(!a.same_origin(&c));
assert!(b.same_origin(&c));
assert!(c.same_origin(&c));
}
#[test]
fn alias_chain() {
let a = Origin::new(&url!("http://example.com/a.html"));
let b = Origin::new(&url!("http://example.com/b.html"));
let c = b.copy();
let d = c.alias();
let e = d.alias();
assert!(a.same_origin(&e));
assert!(b.same_origin(&e));
assert!(c.same_origin(&e));
assert!(d.same_origin(&e));
assert!(e.same_origin(&e));
c.set(url!("http://example.org/c.html").origin());
assert!(a.same_origin(&b));
assert!(!b.same_origin(&c));
assert!(c.same_origin(&d));
assert!(d.same_origin(&e));
assert!(!e.same_origin(&a));
}
#[test]
fn opaque() {
let a = Origin::opaque_identifier();
let b = Origin::opaque_identifier();
assert!(!a.same_origin(&b));
assert_eq!(a.is_scheme_host_port_tuple(), false);
}
#[test]
fn opaque_clone() {
let a = Origin::opaque_identifier();
let b = a.alias();
assert!(a.same_origin(&b));
assert_eq!(a.is_scheme_host_port_tuple(), false);
}