Auto merge of #27806 - jonathanKingston:secure-contexts-with-creation-url, r=jdm

Add creation url and Secure Contexts

A more complete version of https://github.com/servo/servo/pull/27793

I've added in creation/creator URLs to match the HTML spec for the "global settings object" which doesn't exist in Servo but lots of its concepts exist within the Global Scope.

This fixes the previously mentioned blob url test fails but has the previously mentioned issues in https://github.com/servo/servo/pull/27793

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [ ] `./mach build -d` does not report any errors
- [ ] `./mach test-tidy` does not report any errors
- [ ] These changes fix #___ (GitHub issue number if applicable)

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because ___

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
bors-servo 2020-11-25 18:32:58 -05:00 committed by GitHub
commit cf68cd16bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
296 changed files with 495 additions and 318 deletions

View file

@ -24,6 +24,9 @@ pub struct NewBrowsingContextInfo {
/// Whether this browsing context is in private browsing mode. /// Whether this browsing context is in private browsing mode.
pub is_private: bool, pub is_private: bool,
/// Whether this browsing context inherits a secure context.
pub inherited_secure_context: Option<bool>,
/// Whether this browsing context should be treated as visible for the /// Whether this browsing context should be treated as visible for the
/// purposes of scheduling and resource management. /// purposes of scheduling and resource management.
pub is_visible: bool, pub is_visible: bool,
@ -51,6 +54,9 @@ pub struct BrowsingContext {
/// Whether this browsing context is in private browsing mode. /// Whether this browsing context is in private browsing mode.
pub is_private: bool, pub is_private: bool,
/// Whether this browsing context inherits a secure context.
pub inherited_secure_context: Option<bool>,
/// Whether this browsing context should be treated as visible for the /// Whether this browsing context should be treated as visible for the
/// purposes of scheduling and resource management. /// purposes of scheduling and resource management.
pub is_visible: bool, pub is_visible: bool,
@ -78,6 +84,7 @@ impl BrowsingContext {
parent_pipeline_id: Option<PipelineId>, parent_pipeline_id: Option<PipelineId>,
size: Size2D<f32, CSSPixel>, size: Size2D<f32, CSSPixel>,
is_private: bool, is_private: bool,
inherited_secure_context: Option<bool>,
is_visible: bool, is_visible: bool,
) -> BrowsingContext { ) -> BrowsingContext {
let mut pipelines = HashSet::new(); let mut pipelines = HashSet::new();
@ -88,6 +95,7 @@ impl BrowsingContext {
top_level_id, top_level_id,
size, size,
is_private, is_private,
inherited_secure_context,
is_visible, is_visible,
pipeline_id, pipeline_id,
parent_pipeline_id, parent_pipeline_id,

View file

@ -1249,6 +1249,7 @@ where
parent_pipeline_id: Option<PipelineId>, parent_pipeline_id: Option<PipelineId>,
size: Size2D<f32, CSSPixel>, size: Size2D<f32, CSSPixel>,
is_private: bool, is_private: bool,
inherited_secure_context: Option<bool>,
is_visible: bool, is_visible: bool,
) { ) {
debug!("Creating new browsing context {}", browsing_context_id); debug!("Creating new browsing context {}", browsing_context_id);
@ -1283,6 +1284,7 @@ where
parent_pipeline_id, parent_pipeline_id,
size, size,
is_private, is_private,
inherited_secure_context,
is_visible, is_visible,
); );
self.browsing_contexts self.browsing_contexts
@ -1541,6 +1543,7 @@ where
None, None,
Referrer::NoReferrer, Referrer::NoReferrer,
None, None,
None,
); );
let ctx_id = BrowsingContextId::from(top_level_browsing_context_id); let ctx_id = BrowsingContextId::from(top_level_browsing_context_id);
let pipeline_id = match self.browsing_contexts.get(&ctx_id) { let pipeline_id = match self.browsing_contexts.get(&ctx_id) {
@ -2911,6 +2914,7 @@ where
None, None,
Referrer::NoReferrer, Referrer::NoReferrer,
None, None,
None,
); );
let sandbox = IFrameSandboxState::IFrameSandboxed; let sandbox = IFrameSandboxState::IFrameSandboxed;
let is_private = false; let is_private = false;
@ -3027,6 +3031,7 @@ where
None, None,
Referrer::NoReferrer, Referrer::NoReferrer,
None, None,
None,
); );
let sandbox = IFrameSandboxState::IFrameUnsandboxed; let sandbox = IFrameSandboxState::IFrameUnsandboxed;
let is_private = false; let is_private = false;
@ -3071,6 +3076,7 @@ where
new_browsing_context_info: Some(NewBrowsingContextInfo { new_browsing_context_info: Some(NewBrowsingContextInfo {
parent_pipeline_id: None, parent_pipeline_id: None,
is_private: is_private, is_private: is_private,
inherited_secure_context: None,
is_visible: is_visible, is_visible: is_visible,
}), }),
window_size, window_size,
@ -3178,6 +3184,7 @@ where
new_pipeline_id, new_pipeline_id,
is_private, is_private,
mut replace, mut replace,
..
} = load_info.info; } = load_info.info;
// If no url is specified, reload. // If no url is specified, reload.
@ -3293,9 +3300,9 @@ where
Some(pipeline) => (pipeline.event_loop.clone(), pipeline.browsing_context_id), Some(pipeline) => (pipeline.event_loop.clone(), pipeline.browsing_context_id),
None => return warn!("Script loaded url in closed iframe {}.", parent_pipeline_id), None => return warn!("Script loaded url in closed iframe {}.", parent_pipeline_id),
}; };
let (is_parent_private, is_parent_visible) = let (is_parent_private, is_parent_visible, is_parent_secure) =
match self.browsing_contexts.get(&parent_browsing_context_id) { match self.browsing_contexts.get(&parent_browsing_context_id) {
Some(ctx) => (ctx.is_private, ctx.is_visible), Some(ctx) => (ctx.is_private, ctx.is_visible, ctx.inherited_secure_context),
None => { None => {
return warn!( return warn!(
"New iframe {} loaded in closed parent browsing context {}.", "New iframe {} loaded in closed parent browsing context {}.",
@ -3327,6 +3334,7 @@ where
new_browsing_context_info: Some(NewBrowsingContextInfo { new_browsing_context_info: Some(NewBrowsingContextInfo {
parent_pipeline_id: Some(parent_pipeline_id), parent_pipeline_id: Some(parent_pipeline_id),
is_private: is_private, is_private: is_private,
inherited_secure_context: is_parent_secure,
is_visible: is_parent_visible, is_visible: is_parent_visible,
}), }),
window_size: load_info.window_size.initial_viewport, window_size: load_info.window_size.initial_viewport,
@ -3356,9 +3364,9 @@ where
); );
}, },
}; };
let (is_opener_private, is_opener_visible) = let (is_opener_private, is_opener_visible, is_opener_secure) =
match self.browsing_contexts.get(&opener_browsing_context_id) { match self.browsing_contexts.get(&opener_browsing_context_id) {
Some(ctx) => (ctx.is_private, ctx.is_visible), Some(ctx) => (ctx.is_private, ctx.is_visible, ctx.inherited_secure_context),
None => { None => {
return warn!( return warn!(
"New auxiliary {} loaded in closed opener browsing context {}.", "New auxiliary {} loaded in closed opener browsing context {}.",
@ -3416,6 +3424,7 @@ where
// Auxiliary browsing contexts are always top-level. // Auxiliary browsing contexts are always top-level.
parent_pipeline_id: None, parent_pipeline_id: None,
is_private: is_opener_private, is_private: is_opener_private,
inherited_secure_context: is_opener_secure,
is_visible: is_opener_visible, is_visible: is_opener_visible,
}), }),
window_size: self.window_size.initial_viewport, window_size: self.window_size.initial_viewport,
@ -4747,6 +4756,7 @@ where
new_context_info.parent_pipeline_id, new_context_info.parent_pipeline_id,
change.window_size, change.window_size,
new_context_info.is_private, new_context_info.is_private,
new_context_info.inherited_secure_context,
new_context_info.is_visible, new_context_info.is_visible,
); );
self.update_activity(change.new_pipeline_id); self.update_activity(change.new_pipeline_id);

View file

@ -573,6 +573,7 @@ impl UnprivilegedPipelineContent {
layout_is_busy: layout_thread_busy_flag.clone(), layout_is_busy: layout_thread_busy_flag.clone(),
player_context: self.player_context.clone(), player_context: self.player_context.clone(),
event_loop_waker, event_loop_waker,
inherited_secure_context: self.load_data.inherited_secure_context.clone(),
}, },
self.load_data.clone(), self.load_data.clone(),
self.opts.profile_script_events, self.opts.profile_script_events,

View file

@ -1517,7 +1517,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider):
returnType) returnType)
def MemberCondition(pref, func, exposed): def MemberCondition(pref, func, exposed, secure):
""" """
A string representing the condition for a member to actually be exposed. A string representing the condition for a member to actually be exposed.
Any of the arguments can be None. If not None, they should have the Any of the arguments can be None. If not None, they should have the
@ -1526,11 +1526,14 @@ def MemberCondition(pref, func, exposed):
pref: The name of the preference. pref: The name of the preference.
func: The name of the function. func: The name of the function.
exposed: One or more names of an exposed global. exposed: One or more names of an exposed global.
secure: Requires secure context.
""" """
assert pref is None or isinstance(pref, str) assert pref is None or isinstance(pref, str)
assert func is None or isinstance(func, str) assert func is None or isinstance(func, str)
assert exposed is None or isinstance(exposed, set) assert exposed is None or isinstance(exposed, set)
assert func is None or pref is None or exposed is None assert func is None or pref is None or exposed is None or secure is None
if secure:
return 'Condition::SecureContext()'
if pref: if pref:
return 'Condition::Pref("%s")' % pref return 'Condition::Pref("%s")' % pref
if func: if func:
@ -1580,7 +1583,8 @@ class PropertyDefiner:
"Pref"), "Pref"),
PropertyDefiner.getStringAttr(interfaceMember, PropertyDefiner.getStringAttr(interfaceMember,
"Func"), "Func"),
interfaceMember.exposureSet) interfaceMember.exposureSet,
interfaceMember.getExtendedAttribute("SecureContext"))
def generateGuardedArray(self, array, name, specTemplate, specTerminator, def generateGuardedArray(self, array, name, specTemplate, specTerminator,
specType, getCondition, getDataTuple): specType, getCondition, getDataTuple):
@ -3038,7 +3042,7 @@ let global = incumbent_global.reflector().get_jsobject();\n"""
for m in interface.members: for m in interface.members:
if m.isAttr() and not m.isStatic() and m.type.isJSONType(): if m.isAttr() and not m.isStatic() and m.type.isJSONType():
name = m.identifier.name name = m.identifier.name
conditions = MemberCondition(None, None, m.exposureSet) conditions = MemberCondition(None, None, m.exposureSet, None)
ret_conditions = '&[' + ", ".join(conditions) + "]" ret_conditions = '&[' + ", ".join(conditions) + "]"
ret += fill( ret += fill(
""" """
@ -7838,6 +7842,7 @@ impl %(base)s {
if PropertyDefiner.getStringAttr(m, 'Pref') or \ if PropertyDefiner.getStringAttr(m, 'Pref') or \
PropertyDefiner.getStringAttr(m, 'Func') or \ PropertyDefiner.getStringAttr(m, 'Func') or \
PropertyDefiner.getStringAttr(m, 'Exposed') or \ PropertyDefiner.getStringAttr(m, 'Exposed') or \
m.getExtendedAttribute('SecureContext') or \
(m.isMethod() and m.isIdentifierLess()): (m.isMethod() and m.isIdentifierLess()):
continue continue
display = m.identifier.name + ('()' if m.isMethod() else '') display = m.identifier.name + ('()' if m.isMethod() else '')

View file

@ -6,6 +6,9 @@
use crate::dom::bindings::codegen::InterfaceObjectMap; use crate::dom::bindings::codegen::InterfaceObjectMap;
use crate::dom::bindings::interface::is_exposed_in; use crate::dom::bindings::interface::is_exposed_in;
use crate::dom::globalscope::GlobalScope;
use crate::realms::AlreadyInRealm;
use crate::realms::InRealm;
use crate::script_runtime::JSContext; use crate::script_runtime::JSContext;
use js::rust::HandleObject; use js::rust::HandleObject;
use servo_config::prefs; use servo_config::prefs;
@ -45,16 +48,25 @@ pub enum Condition {
Pref(&'static str), Pref(&'static str),
// The condition is satisfied if the interface is exposed in the global. // The condition is satisfied if the interface is exposed in the global.
Exposed(InterfaceObjectMap::Globals), Exposed(InterfaceObjectMap::Globals),
SecureContext(),
/// The condition is always satisfied. /// The condition is always satisfied.
Satisfied, Satisfied,
} }
fn is_secure_context(cx: JSContext) -> bool {
unsafe {
let in_realm_proof = AlreadyInRealm::assert_for_cx(JSContext::from_ptr(*cx));
GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof)).is_secure_context()
}
}
impl Condition { impl Condition {
pub fn is_satisfied(&self, cx: JSContext, obj: HandleObject, global: HandleObject) -> bool { pub fn is_satisfied(&self, cx: JSContext, obj: HandleObject, global: HandleObject) -> bool {
match *self { match *self {
Condition::Pref(name) => prefs::pref_map().get(name).as_bool().unwrap_or(false), Condition::Pref(name) => prefs::pref_map().get(name).as_bool().unwrap_or(false),
Condition::Func(f) => f(cx, obj), Condition::Func(f) => f(cx, obj),
Condition::Exposed(globals) => is_exposed_in(global, globals), Condition::Exposed(globals) => is_exposed_in(global, globals),
Condition::SecureContext() => is_secure_context(cx),
Condition::Satisfied => true, Condition::Satisfied => true,
} }
} }

View file

@ -57,12 +57,14 @@ impl DissimilarOriginWindow {
global_to_clone_from.scheduler_chan().clone(), global_to_clone_from.scheduler_chan().clone(),
global_to_clone_from.resource_threads().clone(), global_to_clone_from.resource_threads().clone(),
global_to_clone_from.origin().clone(), global_to_clone_from.origin().clone(),
global_to_clone_from.creation_url().clone(),
// FIXME(nox): The microtask queue is probably not important // FIXME(nox): The microtask queue is probably not important
// here, but this whole DOM interface is a hack anyway. // here, but this whole DOM interface is a hack anyway.
global_to_clone_from.microtask_queue().clone(), global_to_clone_from.microtask_queue().clone(),
global_to_clone_from.is_headless(), global_to_clone_from.is_headless(),
global_to_clone_from.get_user_agent(), global_to_clone_from.get_user_agent(),
global_to_clone_from.wgpu_id_hub(), global_to_clone_from.wgpu_id_hub(),
Some(global_to_clone_from.is_secure_context()),
), ),
window_proxy: Dom::from_ref(window_proxy), window_proxy: Dom::from_ref(window_proxy),
location: Default::default(), location: Default::default(),

View file

@ -246,6 +246,9 @@ pub struct GlobalScope {
/// The origin of the globalscope /// The origin of the globalscope
origin: MutableOrigin, origin: MutableOrigin,
/// https://html.spec.whatwg.org/multipage/#concept-environment-creation-url
creation_url: Option<ServoUrl>,
/// A map for storing the previous permission state read results. /// A map for storing the previous permission state read results.
permission_state_invocation_results: DomRefCell<HashMap<String, PermissionState>>, permission_state_invocation_results: DomRefCell<HashMap<String, PermissionState>>,
@ -309,6 +312,9 @@ pub struct GlobalScope {
/// List of ongoing dynamic module imports. /// List of ongoing dynamic module imports.
dynamic_modules: DomRefCell<DynamicModuleList>, dynamic_modules: DomRefCell<DynamicModuleList>,
/// Is considered in a secure context
inherited_secure_context: Option<bool>,
} }
/// A wrapper for glue-code between the ipc router and the event-loop. /// A wrapper for glue-code between the ipc router and the event-loop.
@ -719,10 +725,12 @@ impl GlobalScope {
scheduler_chan: IpcSender<TimerSchedulerMsg>, scheduler_chan: IpcSender<TimerSchedulerMsg>,
resource_threads: ResourceThreads, resource_threads: ResourceThreads,
origin: MutableOrigin, origin: MutableOrigin,
creation_url: Option<ServoUrl>,
microtask_queue: Rc<MicrotaskQueue>, microtask_queue: Rc<MicrotaskQueue>,
is_headless: bool, is_headless: bool,
user_agent: Cow<'static, str>, user_agent: Cow<'static, str>,
gpu_id_hub: Arc<Mutex<Identities>>, gpu_id_hub: Arc<Mutex<Identities>>,
inherited_secure_context: Option<bool>,
) -> Self { ) -> Self {
Self { Self {
message_port_state: DomRefCell::new(MessagePortState::UnManaged), message_port_state: DomRefCell::new(MessagePortState::UnManaged),
@ -747,6 +755,7 @@ impl GlobalScope {
timers: OneshotTimers::new(scheduler_chan), timers: OneshotTimers::new(scheduler_chan),
init_timers: Default::default(), init_timers: Default::default(),
origin, origin,
creation_url,
permission_state_invocation_results: Default::default(), permission_state_invocation_results: Default::default(),
microtask_queue, microtask_queue,
list_auto_close_worker: Default::default(), list_auto_close_worker: Default::default(),
@ -761,6 +770,7 @@ impl GlobalScope {
https_state: Cell::new(HttpsState::None), https_state: Cell::new(HttpsState::None),
console_group_stack: DomRefCell::new(Vec::new()), console_group_stack: DomRefCell::new(Vec::new()),
dynamic_modules: DomRefCell::new(DynamicModuleList::new()), dynamic_modules: DomRefCell::new(DynamicModuleList::new()),
inherited_secure_context,
} }
} }
@ -2311,6 +2321,11 @@ impl GlobalScope {
&self.origin &self.origin
} }
/// Get the creation_url for this global scope
pub fn creation_url(&self) -> &Option<ServoUrl> {
&self.creation_url
}
pub fn image_cache(&self) -> Arc<dyn ImageCache> { pub fn image_cache(&self) -> Arc<dyn ImageCache> {
if let Some(window) = self.downcast::<Window>() { if let Some(window) = self.downcast::<Window>() {
return window.image_cache(); return window.image_cache();
@ -2994,6 +3009,19 @@ impl GlobalScope {
self.https_state.set(https_state); self.https_state.set(https_state);
} }
pub fn is_secure_context(&self) -> bool {
if Some(false) == self.inherited_secure_context {
return false;
}
if let Some(creation_url) = self.creation_url() {
if creation_url.scheme() == "blob" && Some(true) == self.inherited_secure_context {
return true;
}
return creation_url.is_potentially_trustworthy();
}
false
}
/// https://www.w3.org/TR/CSP/#get-csp-of-object /// https://www.w3.org/TR/CSP/#get-csp-of-object
pub fn get_csp_list(&self) -> Option<CspList> { pub fn get_csp_list(&self) -> Option<CspList> {
if let Some(window) = self.downcast::<Window>() { if let Some(window) = self.downcast::<Window>() {

View file

@ -703,12 +703,14 @@ pub fn follow_hyperlink(subject: &Element, hyperlink_suffix: Option<String>) {
// Step 14 // Step 14
let pipeline_id = target_window.upcast::<GlobalScope>().pipeline_id(); let pipeline_id = target_window.upcast::<GlobalScope>().pipeline_id();
let secure = target_window.upcast::<GlobalScope>().is_secure_context();
let load_data = LoadData::new( let load_data = LoadData::new(
LoadOrigin::Script(document.origin().immutable().clone()), LoadOrigin::Script(document.origin().immutable().clone()),
url, url,
Some(pipeline_id), Some(pipeline_id),
referrer, referrer,
referrer_policy, referrer_policy,
Some(secure),
); );
let target = Trusted::new(target_window); let target = Trusted::new(target_window);
let task = task!(navigate_follow_hyperlink: move || { let task = task!(navigate_follow_hyperlink: move || {

View file

@ -811,6 +811,7 @@ impl HTMLFormElement {
None, None,
target_window.upcast::<GlobalScope>().get_referrer(), target_window.upcast::<GlobalScope>().get_referrer(),
target_document.get_referrer_policy(), target_document.get_referrer_policy(),
Some(target_window.upcast::<GlobalScope>().is_secure_context()),
); );
// Step 22 // Step 22

View file

@ -170,6 +170,7 @@ impl HTMLIFrameElement {
top_level_browsing_context_id: top_level_browsing_context_id, top_level_browsing_context_id: top_level_browsing_context_id,
new_pipeline_id: new_pipeline_id, new_pipeline_id: new_pipeline_id,
is_private: false, // FIXME is_private: false, // FIXME
inherited_secure_context: load_data.inherited_secure_context,
replace: replace, replace: replace,
}; };
@ -244,6 +245,7 @@ impl HTMLIFrameElement {
pipeline_id, pipeline_id,
window.upcast::<GlobalScope>().get_referrer(), window.upcast::<GlobalScope>().get_referrer(),
document.get_referrer_policy(), document.get_referrer_policy(),
Some(window.upcast::<GlobalScope>().is_secure_context()),
); );
let element = self.upcast::<Element>(); let element = self.upcast::<Element>();
load_data.srcdoc = String::from(element.get_string_attribute(&local_name!("srcdoc"))); load_data.srcdoc = String::from(element.get_string_attribute(&local_name!("srcdoc")));
@ -327,6 +329,7 @@ impl HTMLIFrameElement {
creator_pipeline_id, creator_pipeline_id,
window.upcast::<GlobalScope>().get_referrer(), window.upcast::<GlobalScope>().get_referrer(),
document.get_referrer_policy(), document.get_referrer_policy(),
Some(window.upcast::<GlobalScope>().is_secure_context()),
); );
let pipeline_id = self.pipeline_id(); let pipeline_id = self.pipeline_id();
@ -354,6 +357,7 @@ impl HTMLIFrameElement {
pipeline_id, pipeline_id,
window.upcast::<GlobalScope>().get_referrer(), window.upcast::<GlobalScope>().get_referrer(),
document.get_referrer_policy(), document.get_referrer_policy(),
Some(window.upcast::<GlobalScope>().is_secure_context()),
); );
let browsing_context_id = BrowsingContextId::new(); let browsing_context_id = BrowsingContextId::new();
let top_level_browsing_context_id = window.window_proxy().top_level_browsing_context_id(); let top_level_browsing_context_id = window.window_proxy().top_level_browsing_context_id();

View file

@ -52,6 +52,7 @@ impl Location {
Some(pipeline_id), Some(pipeline_id),
referrer, referrer,
referrer_policy, referrer_policy,
None, // Top navigation doesn't inherit secure context
); );
// TODO: rethrow exceptions, set exceptions enabled flag. // TODO: rethrow exceptions, set exceptions enabled flag.
self.window self.window

View file

@ -36,5 +36,10 @@ partial interface mixin WindowOrWorkerGlobalScope {
readonly attribute Performance performance; readonly attribute Performance performance;
}; };
// https://w3c.github.io/webappsec-secure-contexts/#monkey-patching-global-object
partial interface mixin WindowOrWorkerGlobalScope {
readonly attribute boolean isSecureContext;
};
Window includes WindowOrWorkerGlobalScope; Window includes WindowOrWorkerGlobalScope;
WorkerGlobalScope includes WindowOrWorkerGlobalScope; WorkerGlobalScope includes WindowOrWorkerGlobalScope;

View file

@ -1381,6 +1381,10 @@ impl WindowMethods for Window {
} }
rval.get() rval.get()
} }
fn IsSecureContext(&self) -> bool {
self.upcast::<GlobalScope>().is_secure_context()
}
} }
impl Window { impl Window {
@ -2357,6 +2361,7 @@ impl Window {
parent_info: Option<PipelineId>, parent_info: Option<PipelineId>,
window_size: WindowSizeData, window_size: WindowSizeData,
origin: MutableOrigin, origin: MutableOrigin,
creator_url: ServoUrl,
navigation_start: u64, navigation_start: u64,
navigation_start_precise: u64, navigation_start_precise: u64,
webgl_chan: Option<WebGLChan>, webgl_chan: Option<WebGLChan>,
@ -2376,6 +2381,7 @@ impl Window {
player_context: WindowGLContext, player_context: WindowGLContext,
event_loop_waker: Option<Box<dyn EventLoopWaker>>, event_loop_waker: Option<Box<dyn EventLoopWaker>>,
gpu_id_hub: Arc<ParkMutex<Identities>>, gpu_id_hub: Arc<ParkMutex<Identities>>,
inherited_secure_context: Option<bool>,
) -> DomRoot<Self> { ) -> DomRoot<Self> {
let layout_rpc: Box<dyn LayoutRPC + Send> = { let layout_rpc: Box<dyn LayoutRPC + Send> = {
let (rpc_send, rpc_recv) = unbounded(); let (rpc_send, rpc_recv) = unbounded();
@ -2396,10 +2402,12 @@ impl Window {
scheduler_chan, scheduler_chan,
resource_threads, resource_threads,
origin, origin,
Some(creator_url),
microtask_queue, microtask_queue,
is_headless, is_headless,
user_agent, user_agent,
gpu_id_hub, gpu_id_hub,
inherited_secure_context,
), ),
script_chan, script_chan,
task_manager, task_manager,

View file

@ -307,6 +307,7 @@ impl WindowProxy {
None, None,
document.global().get_referrer(), document.global().get_referrer(),
document.get_referrer_policy(), document.get_referrer_policy(),
None, // Doesn't inherit secure context
); );
let load_info = AuxiliaryBrowsingContextLoadInfo { let load_info = AuxiliaryBrowsingContextLoadInfo {
load_data: load_data.clone(), load_data: load_data.clone(),
@ -511,12 +512,14 @@ impl WindowProxy {
// Step 14.5 // Step 14.5
let referrer_policy = target_document.get_referrer_policy(); let referrer_policy = target_document.get_referrer_policy();
let pipeline_id = target_window.upcast::<GlobalScope>().pipeline_id(); let pipeline_id = target_window.upcast::<GlobalScope>().pipeline_id();
let secure = target_window.upcast::<GlobalScope>().is_secure_context();
let load_data = LoadData::new( let load_data = LoadData::new(
LoadOrigin::Script(existing_document.origin().immutable().clone()), LoadOrigin::Script(existing_document.origin().immutable().clone()),
url, url,
Some(pipeline_id), Some(pipeline_id),
referrer, referrer,
referrer_policy, referrer_policy,
Some(secure),
); );
let replacement_flag = if new { let replacement_flag = if new {
HistoryEntryReplacement::Enabled HistoryEntryReplacement::Enabled

View file

@ -80,8 +80,10 @@ pub fn prepare_workerscope_init(
worker_id: worker_id.unwrap_or_else(|| WorkerId(Uuid::new_v4())), worker_id: worker_id.unwrap_or_else(|| WorkerId(Uuid::new_v4())),
pipeline_id: global.pipeline_id(), pipeline_id: global.pipeline_id(),
origin: global.origin().immutable().clone(), origin: global.origin().immutable().clone(),
creation_url: global.creation_url().clone(),
is_headless: global.is_headless(), is_headless: global.is_headless(),
user_agent: global.get_user_agent(), user_agent: global.get_user_agent(),
inherited_secure_context: Some(global.is_secure_context()),
}; };
init init
@ -141,10 +143,12 @@ impl WorkerGlobalScope {
init.scheduler_chan, init.scheduler_chan,
init.resource_threads, init.resource_threads,
MutableOrigin::new(init.origin), MutableOrigin::new(init.origin),
init.creation_url,
runtime.microtask_queue.clone(), runtime.microtask_queue.clone(),
init.is_headless, init.is_headless,
init.user_agent, init.user_agent,
gpu_id_hub, gpu_id_hub,
init.inherited_secure_context,
), ),
worker_id: init.worker_id, worker_id: init.worker_id,
worker_name, worker_name,
@ -405,6 +409,11 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
.ascii_serialization(), .ascii_serialization(),
) )
} }
// https://w3c.github.io/webappsec-secure-contexts/#dom-windoworworkerglobalscope-issecurecontext
fn IsSecureContext(&self) -> bool {
self.upcast::<GlobalScope>().is_secure_context()
}
} }
impl WorkerGlobalScope { impl WorkerGlobalScope {

View file

@ -71,10 +71,12 @@ impl WorkletGlobalScope {
init.scheduler_chan.clone(), init.scheduler_chan.clone(),
init.resource_threads.clone(), init.resource_threads.clone(),
MutableOrigin::new(ImmutableOrigin::new_opaque()), MutableOrigin::new(ImmutableOrigin::new_opaque()),
None,
Default::default(), Default::default(),
init.is_headless, init.is_headless,
init.user_agent.clone(), init.user_agent.clone(),
init.gpu_id_hub.clone(), init.gpu_id_hub.clone(),
init.inherited_secure_context,
), ),
base_url, base_url,
to_script_thread_sender: init.to_script_thread_sender.clone(), to_script_thread_sender: init.to_script_thread_sender.clone(),
@ -166,6 +168,8 @@ pub struct WorkletGlobalScopeInit {
pub user_agent: Cow<'static, str>, pub user_agent: Cow<'static, str>,
/// Identity manager for WebGPU resources /// Identity manager for WebGPU resources
pub gpu_id_hub: Arc<Mutex<Identities>>, pub gpu_id_hub: Arc<Mutex<Identities>>,
/// Is considered secure
pub inherited_secure_context: Option<bool>,
} }
/// <https://drafts.css-houdini.org/worklets/#worklet-global-scope-type> /// <https://drafts.css-houdini.org/worklets/#worklet-global-scope-type>

View file

@ -216,6 +216,8 @@ struct InProgressLoad {
canceller: FetchCanceller, canceller: FetchCanceller,
/// Flag for sharing with the layout thread that is not yet created. /// Flag for sharing with the layout thread that is not yet created.
layout_is_busy: Arc<AtomicBool>, layout_is_busy: Arc<AtomicBool>,
/// If inheriting the security context
inherited_secure_context: Option<bool>,
} }
impl InProgressLoad { impl InProgressLoad {
@ -231,6 +233,7 @@ impl InProgressLoad {
url: ServoUrl, url: ServoUrl,
origin: MutableOrigin, origin: MutableOrigin,
layout_is_busy: Arc<AtomicBool>, layout_is_busy: Arc<AtomicBool>,
inherited_secure_context: Option<bool>,
) -> InProgressLoad { ) -> InProgressLoad {
let current_time = get_time(); let current_time = get_time();
let navigation_start_precise = precise_time_ns(); let navigation_start_precise = precise_time_ns();
@ -253,6 +256,7 @@ impl InProgressLoad {
navigation_start_precise: navigation_start_precise, navigation_start_precise: navigation_start_precise,
canceller: Default::default(), canceller: Default::default(),
layout_is_busy: layout_is_busy, layout_is_busy: layout_is_busy,
inherited_secure_context: inherited_secure_context,
} }
} }
} }
@ -692,6 +696,9 @@ pub struct ScriptThread {
/// Receiver to receive commands from optional WebGPU server. /// Receiver to receive commands from optional WebGPU server.
webgpu_port: RefCell<Option<Receiver<WebGPUMsg>>>, webgpu_port: RefCell<Option<Receiver<WebGPUMsg>>>,
// Secure context
inherited_secure_context: Option<bool>,
} }
struct BHMExitSignal { struct BHMExitSignal {
@ -778,6 +785,7 @@ impl ScriptThreadFactory for ScriptThread {
let top_level_browsing_context_id = state.top_level_browsing_context_id; let top_level_browsing_context_id = state.top_level_browsing_context_id;
let parent_info = state.parent_info; let parent_info = state.parent_info;
let opener = state.opener; let opener = state.opener;
let secure = load_data.inherited_secure_context.clone();
let mem_profiler_chan = state.mem_profiler_chan.clone(); let mem_profiler_chan = state.mem_profiler_chan.clone();
let window_size = state.window_size; let window_size = state.window_size;
let layout_is_busy = state.layout_is_busy.clone(); let layout_is_busy = state.layout_is_busy.clone();
@ -816,6 +824,7 @@ impl ScriptThreadFactory for ScriptThread {
load_data.url.clone(), load_data.url.clone(),
origin, origin,
layout_is_busy, layout_is_busy,
secure,
); );
script_thread.pre_page_load(new_load, load_data); script_thread.pre_page_load(new_load, load_data);
@ -1149,6 +1158,7 @@ impl ScriptThread {
is_headless: script_thread.headless, is_headless: script_thread.headless,
user_agent: script_thread.user_agent.clone(), user_agent: script_thread.user_agent.clone(),
gpu_id_hub: script_thread.gpu_id_hub.clone(), gpu_id_hub: script_thread.gpu_id_hub.clone(),
inherited_secure_context: script_thread.inherited_secure_context.clone(),
}; };
Rc::new(WorkletThreadPool::spawn(init)) Rc::new(WorkletThreadPool::spawn(init))
}) })
@ -1404,6 +1414,7 @@ impl ScriptThread {
is_user_interacting: Cell::new(false), is_user_interacting: Cell::new(false),
gpu_id_hub: Arc::new(Mutex::new(Identities::new())), gpu_id_hub: Arc::new(Mutex::new(Identities::new())),
webgpu_port: RefCell::new(None), webgpu_port: RefCell::new(None),
inherited_secure_context: state.inherited_secure_context,
} }
} }
@ -2523,6 +2534,7 @@ impl ScriptThread {
load_data.url.clone(), load_data.url.clone(),
origin, origin,
layout_is_busy.clone(), layout_is_busy.clone(),
load_data.inherited_secure_context.clone(),
); );
if load_data.url.as_str() == "about:blank" { if load_data.url.as_str() == "about:blank" {
self.start_page_load_about_blank(new_load, load_data.js_eval_result); self.start_page_load_about_blank(new_load, load_data.js_eval_result);
@ -3271,6 +3283,7 @@ impl ScriptThread {
incomplete.parent_info, incomplete.parent_info,
incomplete.window_size, incomplete.window_size,
origin.clone(), origin.clone(),
final_url.clone(),
incomplete.navigation_start, incomplete.navigation_start,
incomplete.navigation_start_precise, incomplete.navigation_start_precise,
self.webgl_chan.as_ref().map(|chan| chan.channel()), self.webgl_chan.as_ref().map(|chan| chan.channel()),
@ -3290,6 +3303,7 @@ impl ScriptThread {
self.player_context.clone(), self.player_context.clone(),
self.event_loop_waker.as_ref().map(|w| (*w).clone_box()), self.event_loop_waker.as_ref().map(|w| (*w).clone_box()),
self.gpu_id_hub.clone(), self.gpu_id_hub.clone(),
incomplete.inherited_secure_context,
); );
// Initialize the browsing context for the window. // Initialize the browsing context for the window.

View file

@ -182,6 +182,8 @@ pub struct LoadData {
/// The source to use instead of a network response for a srcdoc document. /// The source to use instead of a network response for a srcdoc document.
pub srcdoc: String, pub srcdoc: String,
/// The inherited context is Secure, None if not inherited
pub inherited_secure_context: Option<bool>,
} }
/// The result of evaluating a javascript scheme url. /// The result of evaluating a javascript scheme url.
@ -202,6 +204,7 @@ impl LoadData {
creator_pipeline_id: Option<PipelineId>, creator_pipeline_id: Option<PipelineId>,
referrer: Referrer, referrer: Referrer,
referrer_policy: Option<ReferrerPolicy>, referrer_policy: Option<ReferrerPolicy>,
inherited_secure_context: Option<bool>,
) -> LoadData { ) -> LoadData {
LoadData { LoadData {
load_origin, load_origin,
@ -214,6 +217,7 @@ impl LoadData {
referrer: referrer, referrer: referrer,
referrer_policy: referrer_policy, referrer_policy: referrer_policy,
srcdoc: "".to_string(), srcdoc: "".to_string(),
inherited_secure_context,
} }
} }
} }
@ -639,6 +643,8 @@ pub struct InitialScriptState {
pub top_level_browsing_context_id: TopLevelBrowsingContextId, pub top_level_browsing_context_id: TopLevelBrowsingContextId,
/// The ID of the opener, if any. /// The ID of the opener, if any.
pub opener: Option<BrowsingContextId>, pub opener: Option<BrowsingContextId>,
/// Loading into a Secure Context
pub inherited_secure_context: Option<bool>,
/// A channel with which messages can be sent to us (the script thread). /// A channel with which messages can be sent to us (the script thread).
pub control_chan: IpcSender<ConstellationControlMsg>, pub control_chan: IpcSender<ConstellationControlMsg>,
/// A port on which messages sent by the constellation to script can be received. /// A port on which messages sent by the constellation to script can be received.
@ -751,6 +757,8 @@ pub struct IFrameLoadInfo {
pub new_pipeline_id: PipelineId, pub new_pipeline_id: PipelineId,
/// Whether this iframe should be considered private /// Whether this iframe should be considered private
pub is_private: bool, pub is_private: bool,
/// Whether this iframe should be considered secure
pub inherited_secure_context: Option<bool>,
/// Wether this load should replace the current entry (reload). If true, the current /// Wether this load should replace the current entry (reload). If true, the current
/// entry will be replaced instead of a new entry being added. /// entry will be replaced instead of a new entry being added.
pub replace: HistoryEntryReplacement, pub replace: HistoryEntryReplacement,
@ -868,10 +876,14 @@ pub struct WorkerGlobalScopeInit {
pub pipeline_id: PipelineId, pub pipeline_id: PipelineId,
/// The origin /// The origin
pub origin: ImmutableOrigin, pub origin: ImmutableOrigin,
/// The creation URL
pub creation_url: Option<ServoUrl>,
/// True if headless mode /// True if headless mode
pub is_headless: bool, pub is_headless: bool,
/// An optional string allowing the user agnet to be set for testing. /// An optional string allowing the user agnet to be set for testing.
pub user_agent: Cow<'static, str>, pub user_agent: Cow<'static, str>,
/// True if secure context
pub inherited_secure_context: Option<bool>,
} }
/// Common entities representing a network load origin /// Common entities representing a network load origin

View file

@ -644,7 +644,14 @@ impl Handler {
let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id; let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id;
let load_data = LoadData::new(LoadOrigin::WebDriver, url, None, Referrer::NoReferrer, None); let load_data = LoadData::new(
LoadOrigin::WebDriver,
url,
None,
Referrer::NoReferrer,
None,
None,
);
let cmd_msg = WebDriverCommandMsg::LoadUrl( let cmd_msg = WebDriverCommandMsg::LoadUrl(
top_level_browsing_context_id, top_level_browsing_context_id,
load_data, load_data,

View file

@ -1825,18 +1825,12 @@
[Window interface: window must inherit property "originIsolated" with the proper type] [Window interface: window must inherit property "originIsolated" with the proper type]
expected: FAIL expected: FAIL
[Window interface: attribute isSecureContext]
expected: FAIL
[Window interface: attribute originIsolated] [Window interface: attribute originIsolated]
expected: FAIL expected: FAIL
[Window interface: attribute crossOriginIsolated] [Window interface: attribute crossOriginIsolated]
expected: FAIL expected: FAIL
[Window interface: window must inherit property "isSecureContext" with the proper type]
expected: FAIL
[idlharness.https.html?include=HTML.*] [idlharness.https.html?include=HTML.*]
[HTMLTableSectionElement interface: document.createElement("tfoot") must inherit property "align" with the proper type] [HTMLTableSectionElement interface: document.createElement("tfoot") must inherit property "align" with the proper type]

View file

@ -548,15 +548,9 @@
[ImageBitmapRenderingContext interface: operation transferFromImageBitmap(ImageBitmap?)] [ImageBitmapRenderingContext interface: operation transferFromImageBitmap(ImageBitmap?)]
expected: FAIL expected: FAIL
[WorkerGlobalScope interface: attribute isSecureContext]
expected: FAIL
[WorkerGlobalScope interface: self must inherit property "crossOriginIsolated" with the proper type] [WorkerGlobalScope interface: self must inherit property "crossOriginIsolated" with the proper type]
expected: FAIL expected: FAIL
[WorkerGlobalScope interface: self must inherit property "isSecureContext" with the proper type]
expected: FAIL
[WorkerGlobalScope interface: attribute crossOriginIsolated] [WorkerGlobalScope interface: attribute crossOriginIsolated]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,8 @@
[skip-document-with-fragment.html] [skip-document-with-fragment.html]
expected: TIMEOUT
[Autofocus elements in iframed documents with URL fragments should be skipped.] [Autofocus elements in iframed documents with URL fragments should be skipped.]
expected: FAIL expected: FAIL
[Autofocus elements in top-level browsing context's documents with URI fragments should be skipped.]
expected: TIMEOUT

View file

@ -1,6 +1,5 @@
[iframe_sandbox_popups_escaping-1.html] [iframe_sandbox_popups_escaping-1.html]
type: testharness type: testharness
expected: CRASH
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used] [Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT expected: FAIL

View file

@ -1,5 +1,4 @@
[iframe_sandbox_popups_escaping-2.html] [iframe_sandbox_popups_escaping-2.html]
expected: CRASH
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used] [Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT expected: FAIL

View file

@ -1,6 +1,5 @@
[iframe_sandbox_popups_escaping-3.html] [iframe_sandbox_popups_escaping-3.html]
type: testharness type: testharness
expected: TIMEOUT
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used] [Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT expected: FAIL

View file

@ -1,6 +1,5 @@
[iframe_sandbox_popups_nonescaping-1.html] [iframe_sandbox_popups_nonescaping-1.html]
type: testharness type: testharness
expected: CRASH
[Check that popups from a sandboxed iframe do not escape the sandbox] [Check that popups from a sandboxed iframe do not escape the sandbox]
expected: NOTRUN expected: FAIL

View file

@ -1,6 +1,5 @@
[iframe_sandbox_popups_nonescaping-2.html] [iframe_sandbox_popups_nonescaping-2.html]
type: testharness type: testharness
expected: TIMEOUT
[Check that popups from a sandboxed iframe do not escape the sandbox] [Check that popups from a sandboxed iframe do not escape the sandbox]
expected: NOTRUN expected: FAIL

View file

@ -1,6 +1,4 @@
[iframe_sandbox_popups_nonescaping-3.html] [iframe_sandbox_popups_nonescaping-3.html]
type: testharness
expected: TIMEOUT
[Check that popups from a sandboxed iframe do not escape the sandbox] [Check that popups from a sandboxed iframe do not escape the sandbox]
expected: NOTRUN expected: FAIL

View file

@ -0,0 +1,5 @@
[basic-popup-and-iframe-tests.html]
expected: TIMEOUT
[Test Window.isSecureContext in a sandboxed iframe loading a srcdoc]
expected: TIMEOUT

View file

@ -0,0 +1,5 @@
[basic-popup-and-iframe-tests.https.html]
expected: TIMEOUT
[Test Window.isSecureContext in a sandboxed iframe loading a srcdoc]
expected: TIMEOUT

View file

@ -0,0 +1,13 @@
[basic-shared-worker.html]
[Shared worker]
expected: FAIL
[Nested worker in shared worker]
expected: FAIL
[Shared worker from https subframe]
expected: FAIL
[Nested worker from shared worker from https subframe]
expected: FAIL

View file

@ -0,0 +1,13 @@
[basic-shared-worker.https.html]
[Shared worker]
expected: FAIL
[Nested worker in shared worker]
expected: FAIL
[Shared worker from https subframe]
expected: FAIL
[Nested worker from shared worker from https subframe]
expected: FAIL

View file

@ -0,0 +1,13 @@
[shared-worker-insecure-first.https.html]
[Shared worker in subframe]
expected: FAIL
[Nested worker in shared worker in subframe]
expected: FAIL
[Shared worker in popup]
expected: FAIL
[Nested worker from shared worker in popup]
expected: FAIL

View file

@ -0,0 +1,13 @@
[shared-worker-secure-first.https.html]
[Shared worker in subframe]
expected: FAIL
[Nested worker in shared worker in subframe]
expected: FAIL
[Shared worker in popup]
expected: FAIL
[Nested worker from shared worker in popup]
expected: FAIL

View file

@ -89,9 +89,6 @@
[XRHand interface: constant LITTLE_PHALANX_INTERMEDIATE on interface prototype object] [XRHand interface: constant LITTLE_PHALANX_INTERMEDIATE on interface prototype object]
expected: FAIL expected: FAIL
[XRFrame interface: operation getJointPose(XRJointSpace, XRSpace)]
expected: FAIL
[XRJointSpace interface: existence and properties of interface object] [XRJointSpace interface: existence and properties of interface object]
expected: FAIL expected: FAIL
@ -164,9 +161,6 @@
[XRHand interface: constant LITTLE_METACARPAL on interface prototype object] [XRHand interface: constant LITTLE_METACARPAL on interface prototype object]
expected: FAIL expected: FAIL
[XRInputSource interface: attribute hand]
expected: FAIL
[XRHand interface: constant RING_METACARPAL on interface object] [XRHand interface: constant RING_METACARPAL on interface object]
expected: FAIL expected: FAIL

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
[watchAdvertisements-succeeds.html] [watchAdvertisements-succeeds.https.html]
type: testharness type: testharness
[watchAdvertisements should succeed.] [watchAdvertisements should succeed.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[device-goes-out-of-range.html] [device-goes-out-of-range.https.html]
type: testharness type: testharness
[Device goes out of range. Reject with NetworkError.] [Device goes out of range. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during.html] [disconnect-called-during.https.html]
type: testharness type: testharness
[disconnect() called during getCharacteristic. Reject with NetworkError.] [disconnect() called during getCharacteristic. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-invalidates-object.html] [disconnect-invalidates-object.https.html]
type: testharness type: testharness
[Calls on a characteristic after we disconnect and connect again. Should reject with InvalidStateError.] [Calls on a characteristic after we disconnect and connect again. Should reject with InvalidStateError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[reconnect-during.html] [reconnect-during.https.html]
type: testharness type: testharness
[disconnect() and connect() called during getCharacteristic. Reject with NetworkError.] [disconnect() and connect() called during getCharacteristic. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[device-goes-out-of-range-with-uuid.html] [device-goes-out-of-range-with-uuid.https.html]
type: testharness type: testharness
[Device goes out of range with UUID. Reject with NetworkError.] [Device goes out of range with UUID. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[device-goes-out-of-range.html] [device-goes-out-of-range.https.html]
type: testharness type: testharness
[Device goes out of range. Reject with NetworkError.] [Device goes out of range. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during-with-uuid.html] [disconnect-called-during-with-uuid.https.html]
type: testharness type: testharness
[disconnect() called during getCharacteristics. Reject with NetworkError.] [disconnect() called during getCharacteristics. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during.html] [disconnect-called-during.https.html]
type: testharness type: testharness
[disconnect() called during getCharacteristics. Reject with NetworkError.] [disconnect() called during getCharacteristics. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-invalidates-objects.html] [disconnect-invalidates-objects.https.html]
type: testharness type: testharness
[Calls on characteristics after we disconnect and connect again. Should reject with InvalidStateError.] [Calls on characteristics after we disconnect and connect again. Should reject with InvalidStateError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[device-goes-out-of-range.html] [device-goes-out-of-range.https.html]
type: testharness type: testharness
[Device goes out of range. Reject with NetworkError.] [Device goes out of range. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during.html] [disconnect-called-during.https.html]
type: testharness type: testharness
[disconnect() called during getDescriptor. Reject with NetworkError.] [disconnect() called during getDescriptor. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[device-goes-out-of-range-with-uuid.html] [device-goes-out-of-range-with-uuid.https.html]
type: testharness type: testharness
[Device goes out of range. Reject with NetworkError.] [Device goes out of range. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[device-goes-out-of-range.html] [device-goes-out-of-range.https.html]
type: testharness type: testharness
[Device goes out of range. Reject with NetworkError.] [Device goes out of range. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during-with-uuid.html] [disconnect-called-during-with-uuid.https.html]
type: testharness type: testharness
[disconnect() called during getDescriptors. Reject with NetworkError.] [disconnect() called during getDescriptors. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during.html] [disconnect-called-during.https.html]
type: testharness type: testharness
[disconnect() called during getDescriptors. Reject with NetworkError.] [disconnect() called during getDescriptors. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,5 +0,0 @@
[device-goes-out-of-range.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -0,0 +1,5 @@
[device-goes-out-of-range.https.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during.html] [disconnect-called-during.https.html]
type: testharness type: testharness
[disconnect() called during getPrimaryService. Reject with NetworkError.] [disconnect() called during getPrimaryService. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,5 +0,0 @@
[device-goes-out-of-range-with-uuid.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -0,0 +1,5 @@
[device-goes-out-of-range-with-uuid.https.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -1,5 +0,0 @@
[device-goes-out-of-range.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -0,0 +1,5 @@
[device-goes-out-of-range.https.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during-with-uuid.html] [disconnect-called-during-with-uuid.https.html]
type: testharness type: testharness
[disconnect() called during getPrimaryServices. Reject with NetworkError.] [disconnect() called during getPrimaryServices. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during.html] [disconnect-called-during.https.html]
type: testharness type: testharness
[disconnect() called during getPrimaryServices. Reject with NetworkError.] [disconnect() called during getPrimaryServices. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[idl-BluetoothUUID.html] [idl-BluetoothUUID.https.html]
[Non-number and non-strings] [Non-number and non-strings]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[interfaces.html] [interfaces.https.html]
type: testharness type: testharness
expected: ERROR expected: ERROR
[Bluetooth interface: operation getAvailability()] [Bluetooth interface: operation getAvailability()]

View file

@ -1,5 +0,0 @@
[device-goes-out-of-range.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -0,0 +1,5 @@
[device-goes-out-of-range.https.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during.html] [disconnect-called-during.https.html]
type: testharness type: testharness
[disconnect() called during readValue. Reject with NetworkError.] [disconnect() called during readValue. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[event-is-fired.html] [event-is-fired.https.html]
type: testharness type: testharness
[Reading a characteristic should fire an event.] [Reading a characteristic should fire an event.]
expected: FAIL expected: FAIL

View file

@ -1,5 +0,0 @@
[device-goes-out-of-range.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -0,0 +1,5 @@
[device-goes-out-of-range.https.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during.html] [disconnect-called-during.https.html]
type: testharness type: testharness
[disconnect() called during startNotifications. Reject with NetworkError.] [disconnect() called during startNotifications. Reject with NetworkError.]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,4 @@
[disconnect-called-during.html] [disconnect-called-during.https.html]
type: testharness type: testharness
[disconnect() called during stopNotifications. Reject with InvalidStateError.] [disconnect() called during stopNotifications. Reject with InvalidStateError.]
expected: FAIL expected: FAIL

View file

@ -1,5 +0,0 @@
[device-goes-out-of-range.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -0,0 +1,5 @@
[device-goes-out-of-range.https.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -1,5 +0,0 @@
[device-goes-out-of-range.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

View file

@ -0,0 +1,5 @@
[device-goes-out-of-range.https.html]
type: testharness
[Device goes out of range. Reject with NetworkError.]
expected: FAIL

Some files were not shown because too many files have changed in this diff Show more