aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/dom/bindings/trace.rs3
-rw-r--r--components/script/dom/document.rs29
-rw-r--r--components/script/lib.rs1
-rw-r--r--components/script/origin.rs73
-rw-r--r--components/servo/Cargo.lock2
-rw-r--r--tests/unit/script/Cargo.toml6
-rw-r--r--tests/unit/script/lib.rs5
-rw-r--r--tests/unit/script/origin.rs105
8 files changed, 215 insertions, 9 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 16138b33641..50c3fbf682f 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -89,6 +89,7 @@ use style::properties::PropertyDeclarationBlock;
use style::restyle_hints::ElementSnapshot;
use style::selector_impl::PseudoElement;
use style::values::specified::Length;
+use url::Origin as UrlOrigin;
use url::Url;
use util::str::{DOMString, LengthOrPercentageOrAuto};
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!(isize, i8, i16, i32, i64);
no_jsmanaged_fields!(Sender<T>);
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index e38ab86bf29..9bb9a656719 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -94,6 +94,7 @@ use net_traits::CookieSource::NonHTTP;
use net_traits::response::HttpsState;
use net_traits::{AsyncResponseTarget, PendingAsyncLoad};
use num::ToPrimitive;
+use origin::Origin;
use script_runtime::ScriptChan;
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable};
use script_traits::UntrustedNodeAddress;
@@ -223,6 +224,8 @@ pub struct Document {
/// https://html.spec.whatwg.org/multipage/#concept-document-https-state
https_state: Cell<HttpsState>,
touchpad_pressure_phase: Cell<TouchpadPressurePhase>,
+ /// The document's origin.
+ origin: Origin,
}
#[derive(JSTraceable, HeapSizeOf)]
@@ -1544,14 +1547,6 @@ impl Document {
/// https://html.spec.whatwg.org/multipage/#cookie-averse-document-object
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)
}
@@ -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 {
pub fn new_inherited(window: &Window,
browsing_context: Option<&BrowsingContext>,
@@ -1608,6 +1611,15 @@ impl Document {
(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 {
node: Node::new_document_node(),
window: JS::from_ref(window),
@@ -1673,6 +1685,7 @@ impl Document {
css_errors_store: DOMRefCell::new(vec![]),
https_state: Cell::new(HttpsState::None),
touchpad_pressure_phase: Cell::new(TouchpadPressurePhase::BeforeClick),
+ origin: origin,
}
}
diff --git a/components/script/lib.rs b/components/script/lib.rs
index d3913865070..e525a62b70d 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -90,6 +90,7 @@ pub mod dom;
pub mod layout_interface;
mod mem;
mod network_listener;
+pub mod origin;
pub mod page;
pub mod parse;
pub mod reporter;
diff --git a/components/script/origin.rs b/components/script/origin.rs
new file mode 100644
index 00000000000..096ffbbd6fb
--- /dev/null
+++ b/components/script/origin.rs
@@ -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(),
+ }
+ }
+}
diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock
index 07c6aa3a0cb..8cb85eb5550 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -1752,7 +1752,9 @@ name = "script_tests"
version = "0.0.1"
dependencies = [
"msg 0.0.1",
+ "plugins 0.0.1",
"script 0.0.1",
+ "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
]
diff --git a/tests/unit/script/Cargo.toml b/tests/unit/script/Cargo.toml
index 8aa177e966b..b34cfb238f6 100644
--- a/tests/unit/script/Cargo.toml
+++ b/tests/unit/script/Cargo.toml
@@ -11,8 +11,14 @@ doctest = false
[dependencies.msg]
path = "../../../components/msg"
+[dependencies.plugins]
+path = "../../../components/plugins"
+
[dependencies.script]
path = "../../../components/script"
[dependencies.util]
path = "../../../components/util"
+
+[dependencies]
+url = {version = "0.5.8", features = ["heap_size"]}
diff --git a/tests/unit/script/lib.rs b/tests/unit/script/lib.rs
index 8270d8542d7..2dbbd16ea7a 100644
--- a/tests/unit/script/lib.rs
+++ b/tests/unit/script/lib.rs
@@ -2,10 +2,15 @@
* 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/. */
+#![feature(plugin)]
+#![plugin(plugins)]
+
extern crate msg;
extern crate script;
+extern crate url;
extern crate util;
+#[cfg(test)] mod origin;
#[cfg(all(test, target_pointer_width = "64"))] mod size_of;
#[cfg(test)] mod textinput;
#[cfg(test)] mod dom {
diff --git a/tests/unit/script/origin.rs b/tests/unit/script/origin.rs
new file mode 100644
index 00000000000..81e5d538686
--- /dev/null
+++ b/tests/unit/script/origin.rs
@@ -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);
+}