Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement origin concept and browsing contextless documents. #8658

Merged
merged 3 commits into from Apr 13, 2016
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

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

@@ -1868,9 +1881,18 @@ impl DocumentMethods for Document {

// https://html.spec.whatwg.org/multipage/#relaxing-the-same-origin-restriction
fn Domain(&self) -> DOMString {
// TODO: This should use the effective script origin when it exists
let origin = self.window.get_url();
DOMString::from(origin.serialize_host().unwrap_or_else(|| "".to_owned()))
// Step 1.
if self.browsing_context().is_none() {
return DOMString::new();
}

if let Some(host) = self.origin.host() {
// Step 4.
DOMString::from(host.serialize())
} else {
// Step 3.
DOMString::new()
}
}

// https://dom.spec.whatwg.org/#dom-document-documenturi
@@ -2497,10 +2519,11 @@ impl DocumentMethods for Document {
return Ok(DOMString::new());
}

let url = self.url();
if !is_scheme_host_port_tuple(&url) {
if !self.origin.is_scheme_host_port_tuple() {
return Err(Error::Security);
}

let url = self.url();
let (tx, rx) = ipc::channel().unwrap();
let _ = self.window.resource_thread().send(GetCookiesForUrl((*url).clone(), tx, NonHTTP));
let cookies = rx.recv().unwrap();
@@ -2513,10 +2536,11 @@ impl DocumentMethods for Document {
return Ok(());
}

let url = self.url();
if !is_scheme_host_port_tuple(url) {
if !self.origin.is_scheme_host_port_tuple() {
return Err(Error::Security);
}

let url = self.url();
let _ = self.window
.resource_thread()
.send(SetCookiesForUrl((*url).clone(), String::from(cookie), NonHTTP));
@@ -2720,10 +2744,6 @@ impl DocumentMethods for Document {
}
}

fn is_scheme_host_port_tuple(url: &Url) -> bool {
url.host().is_some() && url.port_or_default().is_some()
}

fn update_with_current_time_ms(marker: &Cell<u64>) {
if marker.get() == Default::default() {
let time = time::get_time();
@@ -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;
@@ -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(),
}
}
}

Some generated files are not rendered by default. Learn more.

@@ -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"]}
@@ -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 {
@@ -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);
}

This file was deleted.

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.