mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Auto merge of #9244 - paulrouget:securitychange, r=jdm
mozbrowsersecuritychange event Fixes #8544 No test yet. Is there a way to mock a https connection? Also, I wish I could use the `HTTPSState` enum instead of a `String` when calling `trigger_mozbrowser_event` (https://github.com/servo/servo/compare/master...paulrouget:securitychange?expand=1#diff-30a18e04d7e0b66aafdf192e416cad44R306) but that would require `constellation_msg.rs` to know about `HTTPSState`, which is defined in `document.rs`, which would add a dependency to `components/msg`. I could define `HTTPSState` somewhere else maybe? Or maybe it's fine to use a `String`. But then, should I use the HTTPSState strings (`"modern/deprecated/none"`) or the mozbrowser strings (`"secure/insecure/broken"`) (as it is now) <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9244) <!-- Reviewable:end -->
This commit is contained in:
commit
3d63f09361
13 changed files with 135 additions and 4 deletions
|
@ -8,6 +8,7 @@ use hyper::http::RawStatus;
|
|||
use hyper::mime::{Mime, SubLevel, TopLevel};
|
||||
use mime_classifier::MIMEClassifier;
|
||||
use net_traits::ProgressMsg::Done;
|
||||
use net_traits::response::HttpsState;
|
||||
use net_traits::{LoadConsumer, LoadData, Metadata};
|
||||
use resource_thread::{CancellationListener, send_error, start_sending_sniffed_opt};
|
||||
use std::sync::Arc;
|
||||
|
@ -28,6 +29,7 @@ pub fn factory(mut load_data: LoadData,
|
|||
charset: Some("utf-8".to_owned()),
|
||||
headers: None,
|
||||
status: Some(RawStatus(200, "OK".into())),
|
||||
https_state: HttpsState::None,
|
||||
};
|
||||
if let Ok(chan) = start_sending_sniffed_opt(start_chan,
|
||||
metadata,
|
||||
|
|
|
@ -26,6 +26,7 @@ use mime_classifier::MIMEClassifier;
|
|||
use msg::constellation_msg::{PipelineId};
|
||||
use net_traits::ProgressMsg::{Done, Payload};
|
||||
use net_traits::hosts::replace_hosts;
|
||||
use net_traits::response::HttpsState;
|
||||
use net_traits::{CookieSource, IncludeSubdomains, LoadConsumer, LoadContext, LoadData, Metadata};
|
||||
use openssl::ssl::error::{SslError, OpensslError};
|
||||
use openssl::ssl::{SSL_OP_NO_SSLV2, SSL_OP_NO_SSLV3, SSL_VERIFY_PEER, SslContext, SslMethod};
|
||||
|
@ -769,6 +770,11 @@ pub fn load<A>(load_data: LoadData,
|
|||
});
|
||||
metadata.headers = Some(adjusted_headers);
|
||||
metadata.status = Some(response.status_raw().clone());
|
||||
metadata.https_state = if doc_url.scheme == "https" {
|
||||
HttpsState::Modern
|
||||
} else {
|
||||
HttpsState::None
|
||||
};
|
||||
|
||||
// --- Tell devtools that we got a response
|
||||
// Send an HttpResponse message to devtools with the corresponding request_id
|
||||
|
|
|
@ -312,6 +312,9 @@ pub struct Metadata {
|
|||
#[ignore_heap_size_of = "Defined in hyper"]
|
||||
/// HTTP Status
|
||||
pub status: Option<RawStatus>,
|
||||
|
||||
/// Is successful HTTPS connection
|
||||
pub https_state: response::HttpsState,
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
|
@ -324,6 +327,7 @@ impl Metadata {
|
|||
headers: None,
|
||||
// https://fetch.spec.whatwg.org/#concept-response-status-message
|
||||
status: Some(RawStatus(200, "OK".into())),
|
||||
https_state: response::HttpsState::None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ pub enum CacheState {
|
|||
}
|
||||
|
||||
/// [Https state](https://fetch.spec.whatwg.org/#concept-response-https-state)
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Copy, HeapSizeOf, Deserialize, Serialize)]
|
||||
pub enum HttpsState {
|
||||
None,
|
||||
Deprecated,
|
||||
|
|
|
@ -60,6 +60,7 @@ use msg::constellation_msg::{PipelineId, SubpageId, WindowSizeData};
|
|||
use net_traits::Metadata;
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
|
||||
use net_traits::response::HttpsState;
|
||||
use net_traits::storage_thread::StorageType;
|
||||
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
||||
use profile_traits::time::ProfilerChan as TimeProfilerChan;
|
||||
|
@ -299,6 +300,7 @@ no_jsmanaged_fields!(Mime);
|
|||
no_jsmanaged_fields!(AttrIdentifier);
|
||||
no_jsmanaged_fields!(AttrValue);
|
||||
no_jsmanaged_fields!(ElementSnapshot);
|
||||
no_jsmanaged_fields!(HttpsState);
|
||||
|
||||
impl JSTraceable for ConstellationChan<ScriptMsg> {
|
||||
#[inline]
|
||||
|
|
|
@ -84,6 +84,7 @@ use msg::constellation_msg::{ConstellationChan, Key, KeyModifiers, KeyState};
|
|||
use msg::constellation_msg::{PipelineId, SubpageId};
|
||||
use net_traits::ControlMsg::{GetCookiesForUrl, SetCookiesForUrl};
|
||||
use net_traits::CookieSource::NonHTTP;
|
||||
use net_traits::response::HttpsState;
|
||||
use net_traits::{AsyncResponseTarget, PendingAsyncLoad};
|
||||
use num::ToPrimitive;
|
||||
use script_thread::{MainThreadScriptMsg, Runnable};
|
||||
|
@ -204,6 +205,8 @@ pub struct Document {
|
|||
dom_complete: Cell<u64>,
|
||||
/// Vector to store CSS errors
|
||||
css_errors_store: DOMRefCell<Vec<CSSError>>,
|
||||
/// https://html.spec.whatwg.org/multipage/#concept-document-https-state
|
||||
https_state: Cell<HttpsState>,
|
||||
}
|
||||
|
||||
#[derive(JSTraceable, HeapSizeOf)]
|
||||
|
@ -289,6 +292,11 @@ impl Document {
|
|||
self.is_html_document
|
||||
}
|
||||
|
||||
pub fn set_https_state(&self, https_state: HttpsState) {
|
||||
self.https_state.set(https_state);
|
||||
self.trigger_mozbrowser_event(MozBrowserEvent::SecurityChange(https_state));
|
||||
}
|
||||
|
||||
pub fn report_css_error(&self, css_error: CSSError) {
|
||||
self.css_errors_store.borrow_mut().push(css_error);
|
||||
}
|
||||
|
@ -1523,6 +1531,7 @@ impl Document {
|
|||
dom_content_loaded_event_end: Cell::new(Default::default()),
|
||||
dom_complete: Cell::new(Default::default()),
|
||||
css_errors_store: DOMRefCell::new(vec![]),
|
||||
https_state: Cell::new(HttpsState::None),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use dom::attr::{Attr, AttrValue};
|
||||
use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserElementIconChangeEventDetail;
|
||||
use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserElementSecurityChangeDetail;
|
||||
use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserShowModalPromptEventDetail;
|
||||
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding;
|
||||
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods;
|
||||
|
@ -29,6 +30,7 @@ use js::jsval::{UndefinedValue, NullValue};
|
|||
use layout_interface::ReflowQueryType;
|
||||
use msg::constellation_msg::{ConstellationChan};
|
||||
use msg::constellation_msg::{NavigationDirection, PipelineId, SubpageId};
|
||||
use net_traits::response::HttpsState;
|
||||
use page::IterablePage;
|
||||
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
||||
use script_traits::{IFrameLoadInfo, MozBrowserEvent, ScriptMsg as ConstellationMsg};
|
||||
|
@ -275,10 +277,26 @@ impl MozBrowserEventDetailBuilder for HTMLIFrameElement {
|
|||
match event {
|
||||
MozBrowserEvent::AsyncScroll | MozBrowserEvent::Close | MozBrowserEvent::ContextMenu |
|
||||
MozBrowserEvent::Error | MozBrowserEvent::LoadEnd | MozBrowserEvent::LoadStart |
|
||||
MozBrowserEvent::OpenWindow | MozBrowserEvent::SecurityChange | MozBrowserEvent::OpenSearch |
|
||||
MozBrowserEvent::OpenWindow | MozBrowserEvent::OpenSearch |
|
||||
MozBrowserEvent::UsernameAndPasswordRequired => {
|
||||
rval.set(NullValue());
|
||||
}
|
||||
MozBrowserEvent::SecurityChange(https_state) => {
|
||||
BrowserElementSecurityChangeDetail {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsersecuritychange
|
||||
state: Some(DOMString::from(match https_state {
|
||||
HttpsState::Modern => "secure",
|
||||
HttpsState::Deprecated => "broken",
|
||||
HttpsState::None => "insecure",
|
||||
}.to_owned())),
|
||||
// FIXME - Not supported yet:
|
||||
trackingContent: None,
|
||||
mixedContent: None,
|
||||
trackingState: None,
|
||||
extendedValidation: None,
|
||||
mixedState: None,
|
||||
}.to_jsval(cx, rval);
|
||||
}
|
||||
MozBrowserEvent::LocationChange(ref string) | MozBrowserEvent::TitleChange(ref string) => {
|
||||
string.to_jsval(cx, rval);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,36 @@ callback BrowserElementNextPaintEventCallback = void ();
|
|||
interface BrowserElement {
|
||||
};
|
||||
|
||||
dictionary BrowserElementSecurityChangeDetail {
|
||||
|
||||
// state:
|
||||
// "insecure" indicates that the data corresponding to
|
||||
// the request was received over an insecure channel.
|
||||
//
|
||||
// "broken" indicates an unknown security state. This
|
||||
// may mean that the request is being loaded as part
|
||||
// of a page in which some content was received over
|
||||
// an insecure channel.
|
||||
//
|
||||
// "secure" indicates that the data corresponding to the
|
||||
// request was received over a secure channel.
|
||||
DOMString state;
|
||||
|
||||
// trackingState:
|
||||
// "loaded_tracking_content": tracking content has been loaded.
|
||||
// "blocked_tracking_content": tracking content has been blocked from loading.
|
||||
DOMString trackingState;
|
||||
|
||||
// mixedState:
|
||||
// "blocked_mixed_active_content": Mixed active content has been blocked from loading.
|
||||
// "loaded_mixed_active_content": Mixed active content has been loaded.
|
||||
DOMString mixedState;
|
||||
|
||||
boolean extendedValidation;
|
||||
boolean trackingContent;
|
||||
boolean mixedContent;
|
||||
};
|
||||
|
||||
dictionary BrowserElementIconChangeEventDetail {
|
||||
DOMString rel;
|
||||
DOMString href;
|
||||
|
|
|
@ -1878,6 +1878,8 @@ impl ScriptThread {
|
|||
DOMString::new()
|
||||
};
|
||||
|
||||
document.set_https_state(metadata.https_state);
|
||||
|
||||
match metadata.content_type {
|
||||
Some(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _))) => {
|
||||
parse_xml(document.r(),
|
||||
|
|
|
@ -46,6 +46,7 @@ use msg::constellation_msg::{PipelineNamespaceId, SubpageId};
|
|||
use msg::webdriver_msg::WebDriverScriptCommand;
|
||||
use net_traits::ResourceThread;
|
||||
use net_traits::image_cache_thread::ImageCacheThread;
|
||||
use net_traits::response::HttpsState;
|
||||
use net_traits::storage_thread::StorageThread;
|
||||
use profile_traits::mem;
|
||||
use std::any::Any;
|
||||
|
@ -423,7 +424,7 @@ pub enum MozBrowserEvent {
|
|||
/// Sent when window.open() is called within a browser `<iframe>`.
|
||||
OpenWindow,
|
||||
/// Sent when the SSL state changes within a browser `<iframe>`.
|
||||
SecurityChange,
|
||||
SecurityChange(HttpsState),
|
||||
/// Sent when alert(), confirm(), or prompt() is called within a browser `<iframe>`.
|
||||
ShowModalPrompt(String, String, String, String), // TODO(simartin): Handle unblock()
|
||||
/// Sent when the document.title changes within a browser `<iframe>`.
|
||||
|
@ -447,7 +448,7 @@ impl MozBrowserEvent {
|
|||
MozBrowserEvent::LoadStart => "mozbrowserloadstart",
|
||||
MozBrowserEvent::LocationChange(_) => "mozbrowserlocationchange",
|
||||
MozBrowserEvent::OpenWindow => "mozbrowseropenwindow",
|
||||
MozBrowserEvent::SecurityChange => "mozbrowsersecuritychange",
|
||||
MozBrowserEvent::SecurityChange(_) => "mozbrowsersecuritychange",
|
||||
MozBrowserEvent::ShowModalPrompt(_, _, _, _) => "mozbrowsershowmodalprompt",
|
||||
MozBrowserEvent::TitleChange(_) => "mozbrowsertitlechange",
|
||||
MozBrowserEvent::UsernameAndPasswordRequired => "mozbrowserusernameandpasswordrequired",
|
||||
|
|
|
@ -5916,6 +5916,12 @@
|
|||
"url": "/_mozilla/mozilla/mozbrowser/mozbrowsericonchange_event.html"
|
||||
}
|
||||
],
|
||||
"mozilla/mozbrowser/mozbrowsersecuritychange_event.html": [
|
||||
{
|
||||
"path": "mozilla/mozbrowser/mozbrowsersecuritychange_event.html",
|
||||
"url": "/_mozilla/mozilla/mozbrowser/mozbrowsersecuritychange_event.html"
|
||||
}
|
||||
],
|
||||
"mozilla/mozbrowser/mozbrowsershowmodalprompt_event.html": [
|
||||
{
|
||||
"path": "mozilla/mozbrowser/mozbrowsershowmodalprompt_event.html",
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[mozbrowsersecuritychange_event.html]
|
||||
type: testharness
|
||||
[mozbrowsersecuritychange event is dispatched when content security state changes]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<head>
|
||||
<title>mozbrowsersecuritychange event is dispatched when content security state changes</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
async_test(function(t) {
|
||||
|
||||
const HTTP_URL = "http://web-platform.test:8000";
|
||||
const HTTPS_URL = "https://web-platform.test:8443";
|
||||
|
||||
var urls = [ HTTP_URL, HTTPS_URL, HTTP_URL ];
|
||||
var url_index = 0;
|
||||
|
||||
var expectedEvents = [
|
||||
"insecure",
|
||||
"secure",
|
||||
"insecure",
|
||||
];
|
||||
|
||||
var receivedEvents = [];
|
||||
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.mozbrowser = "true";
|
||||
iframe.src = urls[url_index++];
|
||||
|
||||
iframe.addEventListener("mozbrowsersecuritychange", t.step_func(e => {
|
||||
|
||||
receivedEvents.push(e.detail.state);
|
||||
|
||||
if (receivedEvents.length == expectedEvents.length) {
|
||||
assert_array_equals(receivedEvents, expectedEvents);
|
||||
t.done();
|
||||
} else {
|
||||
iframe.src = urls[url_index++];
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
Loading…
Add table
Add a link
Reference in a new issue