From 6ccbad804824c1f3158f3c7a670507ef58935165 Mon Sep 17 00:00:00 2001 From: Morris Tseng Date: Sun, 26 Mar 2017 02:29:16 -0700 Subject: [PATCH 01/57] servo: Merge #15905 - Add gradient border support (from mephisto41:add-border-gradient); r=emilio webrender add gradient border support in https://github.com/servo/webrender/pull/953. This pr add support in servo. --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes do not require tests because it should be covered by wpt Source-Repo: https://github.com/servo/servo Source-Revision: fd8127b23b177886217eb1f21963e6c02528647a --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 9f3188db40cd1d21acb98f2b7f6927961c8e71ad --- servo/components/gfx/display_list/mod.rs | 25 +++++- .../components/layout/display_list_builder.rs | 88 ++++++++++++++----- servo/components/layout/webrender_helpers.rs | 16 +++- 3 files changed, 98 insertions(+), 31 deletions(-) diff --git a/servo/components/gfx/display_list/mod.rs b/servo/components/gfx/display_list/mod.rs index 78d50530168c..ee3494e1b959 100644 --- a/servo/components/gfx/display_list/mod.rs +++ b/servo/components/gfx/display_list/mod.rs @@ -886,10 +886,7 @@ pub struct IframeDisplayItem { /// Paints a gradient. #[derive(Clone, Deserialize, HeapSizeOf, Serialize)] -pub struct GradientDisplayItem { - /// Fields common to all display items. - pub base: BaseDisplayItem, - +pub struct Gradient { /// The start point of the gradient (computed during display list construction). pub start_point: Point2D, @@ -900,6 +897,15 @@ pub struct GradientDisplayItem { pub stops: Vec, } +#[derive(Clone, Deserialize, HeapSizeOf, Serialize)] +pub struct GradientDisplayItem { + /// Fields common to all display item. + pub base: BaseDisplayItem, + + /// Contains all gradient data. Included start, end point and color stops. + pub gradient: Gradient, +} + /// A normal border, supporting CSS border styles. #[derive(Clone, HeapSizeOf, Deserialize, Serialize)] pub struct NormalBorder { @@ -939,11 +945,22 @@ pub struct ImageBorder { pub repeat_vertical: webrender_traits::RepeatMode, } +/// A border that is made of linear gradient +#[derive(Clone, HeapSizeOf, Deserialize, Serialize)] +pub struct GradientBorder { + /// The gradient info that this border uses, border-image-source. + pub gradient: Gradient, + + /// Outsets for the border, as per border-image-outset. + pub outset: SideOffsets2D, +} + /// Specifies the type of border #[derive(Clone, HeapSizeOf, Deserialize, Serialize)] pub enum BorderDetails { Normal(NormalBorder), Image(ImageBorder), + Gradient(GradientBorder), } /// Paints a border. diff --git a/servo/components/layout/display_list_builder.rs b/servo/components/layout/display_list_builder.rs index bf0550b03637..456acf95c864 100644 --- a/servo/components/layout/display_list_builder.rs +++ b/servo/components/layout/display_list_builder.rs @@ -20,6 +20,7 @@ use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED}; use flow_ref::FlowRef; use fragment::{CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo}; use fragment::{SpecificFragmentInfo, TruncatedFragmentInfo}; +use gfx::display_list; use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails}; use gfx::display_list::{BorderDisplayItem, ImageBorder, NormalBorder}; use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion}; @@ -350,6 +351,12 @@ pub trait FragmentDisplayListBuilding { image_url: &ServoUrl, background_index: usize); + fn convert_gradient(&self, + absolute_bounds: &Rect, + gradient: &Gradient, + style: &ServoComputedValues) + -> Option; + /// Adds the display items necessary to paint the background linear gradient of this fragment /// to the appropriate section of the display list. fn build_display_list_for_background_gradient(&self, @@ -831,20 +838,13 @@ impl FragmentDisplayListBuilding for Fragment { } } - fn build_display_list_for_background_gradient(&self, - state: &mut DisplayListBuildState, - display_list_section: DisplayListSection, - absolute_bounds: &Rect, - clip: &ClippingRegion, - gradient: &Gradient, - style: &ServoComputedValues) { - let mut clip = clip.clone(); - clip.intersect_rect(absolute_bounds); - - + fn convert_gradient(&self, + absolute_bounds: &Rect, + gradient: &Gradient, + style: &ServoComputedValues) -> Option { // FIXME: Repeating gradients aren't implemented yet. if gradient.repeating { - return; + return None; } let angle = if let GradientKind::Linear(angle_or_corner) = gradient.gradient_kind { match angle_or_corner { @@ -869,7 +869,7 @@ impl FragmentDisplayListBuilding for Fragment { } } else { // FIXME: Radial gradients aren't implemented yet. - return; + return None; }; // Get correct gradient line length, based on: @@ -953,19 +953,39 @@ impl FragmentDisplayListBuilding for Fragment { let center = Point2D::new(absolute_bounds.origin.x + absolute_bounds.size.width / 2, absolute_bounds.origin.y + absolute_bounds.size.height / 2); - let base = state.create_base_display_item(absolute_bounds, - &clip, - self.node, - style.get_cursor(Cursor::Default), - display_list_section); - let gradient_display_item = DisplayItem::Gradient(box GradientDisplayItem { - base: base, + Some(display_list::Gradient { start_point: center - delta, end_point: center + delta, stops: stops, - }); + }) + } - state.add_display_item(gradient_display_item); + fn build_display_list_for_background_gradient(&self, + state: &mut DisplayListBuildState, + display_list_section: DisplayListSection, + absolute_bounds: &Rect, + clip: &ClippingRegion, + gradient: &Gradient, + style: &ServoComputedValues) { + let mut clip = clip.clone(); + clip.intersect_rect(absolute_bounds); + + let grad = self.convert_gradient(absolute_bounds, gradient, style); + + if let Some(x) = grad { + let base = state.create_base_display_item(absolute_bounds, + &clip, + self.node, + style.get_cursor(Cursor::Default), + display_list_section); + + let gradient_display_item = DisplayItem::Gradient(box GradientDisplayItem { + base: base, + gradient: x, + }); + + state.add_display_item(gradient_display_item); + } } fn build_display_list_for_box_shadow_if_applicable(&self, @@ -1076,8 +1096,28 @@ impl FragmentDisplayListBuilding for Fragment { }), })); } - Some(computed::Image::Gradient(..)) => { - // TODO(gw): Handle border-image with gradient. + Some(computed::Image::Gradient(ref gradient)) => { + match gradient.gradient_kind { + GradientKind::Linear(_) => { + let grad = self.convert_gradient(&bounds, gradient, style); + + if let Some(x) = grad { + state.add_display_item(DisplayItem::Border(box BorderDisplayItem { + base: base, + border_widths: border.to_physical(style.writing_mode), + details: BorderDetails::Gradient(display_list::GradientBorder { + gradient: x, + + // TODO(gw): Support border-image-outset + outset: SideOffsets2D::zero(), + }), + })); + } + } + GradientKind::Radial(_, _) => { + // TODO(gw): Handle border-image with radial gradient. + } + } } Some(computed::Image::ImageRect(..)) => { // TODO: Handle border-image with `-moz-image-rect`. diff --git a/servo/components/layout/webrender_helpers.rs b/servo/components/layout/webrender_helpers.rs index 2e94b79adaa1..3d2f434053d0 100644 --- a/servo/components/layout/webrender_helpers.rs +++ b/servo/components/layout/webrender_helpers.rs @@ -351,20 +351,30 @@ impl WebRenderDisplayItemConverter for DisplayItem { } } } + BorderDetails::Gradient(ref gradient) => { + webrender_traits::BorderDetails::Gradient(webrender_traits::GradientBorder { + gradient: builder.create_gradient( + gradient.gradient.start_point.to_pointf(), + gradient.gradient.end_point.to_pointf(), + gradient.gradient.stops.clone(), + ExtendMode::Clamp), + outset: gradient.outset, + }) + } }; builder.push_border(rect, clip, widths, details); } DisplayItem::Gradient(ref item) => { let rect = item.base.bounds.to_rectf(); - let start_point = item.start_point.to_pointf(); - let end_point = item.end_point.to_pointf(); + let start_point = item.gradient.start_point.to_pointf(); + let end_point = item.gradient.end_point.to_pointf(); let clip = item.base.clip.to_clip_region(builder); builder.push_gradient(rect, clip, start_point, end_point, - item.stops.clone(), + item.gradient.stops.clone(), ExtendMode::Clamp); } DisplayItem::Line(..) => { From a8d1b9bde0a97c5959993bba0b1dcd85bb892ea8 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 26 Mar 2017 10:17:16 -0700 Subject: [PATCH 02/57] servo: Merge #16131 - Use NetworkConnector directly to account for replaced hosts (from nox:tungstenite); r=jdm Source-Repo: https://github.com/servo/servo Source-Revision: 1105100c3beb9cff3a71677937269ecc523f2924 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : c15f500b44f6ceba2296635274bbc14b2e61753b --- servo/components/net/fetch/methods.rs | 2 +- servo/components/net/http_loader.rs | 27 +-- servo/components/net/websocket_loader.rs | 158 +++++++++--------- servo/components/net_traits/hosts.rs | 32 ++-- .../components/script/dom/htmlformelement.rs | 25 ++- servo/components/script/dom/url.rs | 5 +- servo/components/script/dom/urlhelper.rs | 36 +--- servo/components/url/lib.rs | 18 +- servo/tests/unit/net/resource_thread.rs | 6 +- 9 files changed, 150 insertions(+), 159 deletions(-) diff --git a/servo/components/net/fetch/methods.rs b/servo/components/net/fetch/methods.rs index 90d1feed2d4a..841ba94dd1ce 100644 --- a/servo/components/net/fetch/methods.rs +++ b/servo/components/net/fetch/methods.rs @@ -192,7 +192,7 @@ pub fn main_fetch(request: Rc, .read() .unwrap() .is_host_secure(request.current_url().domain().unwrap()) { - request.url_list.borrow_mut().last_mut().unwrap().as_mut_url().unwrap().set_scheme("https").unwrap(); + request.url_list.borrow_mut().last_mut().unwrap().as_mut_url().set_scheme("https").unwrap(); } } diff --git a/servo/components/net/http_loader.rs b/servo/components/net/http_loader.rs index 750a94c56364..ca9720344715 100644 --- a/servo/components/net/http_loader.rs +++ b/servo/components/net/http_loader.rs @@ -15,6 +15,7 @@ use hsts::HstsList; use hyper::Error as HttpError; use hyper::LanguageTag; use hyper::client::{Pool, Request as HyperRequest, Response as HyperResponse}; +use hyper::client::pool::PooledStream; use hyper::header::{AcceptEncoding, AcceptLanguage, AccessControlAllowCredentials}; use hyper::header::{AccessControlAllowOrigin, AccessControlAllowHeaders, AccessControlAllowMethods}; use hyper::header::{AccessControlRequestHeaders, AccessControlMaxAge, AccessControlRequestMethod}; @@ -24,17 +25,18 @@ use hyper::header::{IfUnmodifiedSince, IfModifiedSince, IfNoneMatch, Location, P use hyper::header::{QualityItem, Referer, SetCookie, UserAgent, qitem}; use hyper::header::Origin as HyperOrigin; use hyper::method::Method; -use hyper::net::Fresh; +use hyper::net::{Fresh, HttpStream, HttpsStream, NetworkConnector}; use hyper::status::StatusCode; use hyper_serde::Serde; use log; use msg::constellation_msg::PipelineId; use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy}; -use net_traits::hosts::replace_hosts; +use net_traits::hosts::replace_host; use net_traits::request::{CacheMode, CredentialsMode, Destination, Origin}; use net_traits::request::{RedirectMode, Referrer, Request, RequestMode, ResponseTainting}; use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType}; use openssl; +use openssl::ssl::SslStream; use openssl::ssl::error::{OpensslError, SslError}; use resource_thread::AuthCache; use servo_url::{ImmutableOrigin, ServoUrl}; @@ -125,12 +127,18 @@ struct NetworkHttpRequestFactory { pub connector: Arc>, } +impl NetworkConnector for NetworkHttpRequestFactory { + type Stream = PooledStream>>; + + fn connect(&self, host: &str, port: u16, scheme: &str) -> Result { + self.connector.connect(&replace_host(host), port, scheme) + } +} + impl NetworkHttpRequestFactory { fn create(&self, url: ServoUrl, method: Method, headers: Headers) -> Result, NetworkError> { - let connection = HyperRequest::with_connector(method, - url.clone().into_url().unwrap(), - &*self.connector); + let connection = HyperRequest::with_connector(method, url.clone().into_url(), self); if let Err(HttpError::Ssl(ref error)) = connection { let error: &(Error + Send + 'static) = &**error; @@ -222,7 +230,7 @@ fn strict_origin_when_cross_origin(referrer_url: ServoUrl, url: ServoUrl) -> Opt fn strip_url(mut referrer_url: ServoUrl, origin_only: bool) -> Option { if referrer_url.scheme() == "https" || referrer_url.scheme() == "http" { { - let referrer = referrer_url.as_mut_url().unwrap(); + let referrer = referrer_url.as_mut_url(); referrer.set_username("").unwrap(); referrer.set_password(None).unwrap(); referrer.set_fragment(None); @@ -408,7 +416,6 @@ fn obtain_response(request_factory: &NetworkHttpRequestFactory, is_xhr: bool) -> Result<(WrappedHttpResponse, Option), NetworkError> { let null_data = None; - let connection_url = replace_hosts(&url); // loop trying connections in connection pool // they may have grown stale (disconnected), in which case we'll get @@ -439,7 +446,7 @@ fn obtain_response(request_factory: &NetworkHttpRequestFactory, } if log_enabled!(log::LogLevel::Info) { - info!("{} {}", method, connection_url); + info!("{} {}", method, url); for header in headers.iter() { info!(" - {}", header); } @@ -448,7 +455,7 @@ fn obtain_response(request_factory: &NetworkHttpRequestFactory, let connect_start = precise_time_ms(); - let request = try!(request_factory.create(connection_url.clone(), method.clone(), + let request = try!(request_factory.create(url.clone(), method.clone(), headers.clone())); let connect_end = precise_time_ms(); @@ -900,7 +907,7 @@ fn http_network_or_cache_fetch(request: Rc, let headers = &mut *http_request.headers.borrow_mut(); let host = Host { hostname: current_url.host_str().unwrap().to_owned(), - port: current_url.port_or_known_default() + port: current_url.port() }; headers.set(host); // unlike http_loader, we should not set the accept header diff --git a/servo/components/net/websocket_loader.rs b/servo/components/net/websocket_loader.rs index 34c177989931..97e56fe076e8 100644 --- a/servo/components/net/websocket_loader.rs +++ b/servo/components/net/websocket_loader.rs @@ -9,7 +9,7 @@ use http_loader; use hyper::header::{Host, SetCookie}; use net_traits::{CookieSource, MessageData, WebSocketCommunicate}; use net_traits::{WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent}; -use net_traits::hosts::replace_hosts; +use net_traits::hosts::replace_host_in_url; use servo_url::ServoUrl; use std::ascii::AsciiExt; use std::sync::{Arc, Mutex, RwLock}; @@ -25,84 +25,6 @@ use websocket::stream::WebSocketStream; use websocket::ws::receiver::Receiver as WSReceiver; use websocket::ws::sender::Sender as Sender_Object; -// https://fetch.spec.whatwg.org/#concept-websocket-establish -fn establish_a_websocket_connection(resource_url: &ServoUrl, - origin: String, - protocols: Vec, - cookie_jar: Arc>) - -> WebSocketResult<(Option, - Sender, - Receiver)> { - // Steps 1-2 are not really applicable here, given we don't exactly go - // through the same infrastructure as the Fetch spec. - - if should_be_blocked_due_to_bad_port(resource_url) { - // Subset of steps 11-12, we inline the bad port check here from the - // main fetch algorithm for the same reason steps 1-2 are not - // applicable. - return Err(WebSocketError::RequestError("Request should be blocked due to bad port.")); - } - - // Steps 3-7. - let net_url = replace_hosts(resource_url); - let mut request = try!(Client::connect(net_url.as_url())); - - // Client::connect sets the Host header to the host of the URL that is - // passed to it, so we need to reset it afterwards to the correct one. - request.headers.set(Host { - hostname: resource_url.host_str().unwrap().to_owned(), - port: resource_url.port(), - }); - - // Step 8. - if !protocols.is_empty() { - request.headers.set(WebSocketProtocol(protocols.clone())); - } - - // Steps 9-10. - // TODO: support for permessage-deflate extension. - - // Subset of step 11. - // See step 2 of https://fetch.spec.whatwg.org/#concept-fetch. - request.headers.set(Origin(origin)); - - // Transitive subset of step 11. - // See step 17.1 of https://fetch.spec.whatwg.org/#concept-http-network-or-cache-fetch. - http_loader::set_request_cookies(&resource_url, &mut request.headers, &cookie_jar); - - // Step 11, somewhat. - let response = try!(request.send()); - - // Step 12, 14. - try!(response.validate()); - - // Step 13 and transitive subset of step 14. - // See step 6 of http://tools.ietf.org/html/rfc6455#section-4.1. - let protocol_in_use = response.protocol().and_then(|header| { - // https://github.com/whatwg/fetch/issues/515 - header.first().cloned() - }); - if let Some(ref protocol_name) = protocol_in_use { - if !protocols.is_empty() && !protocols.iter().any(|p| (&**p).eq_ignore_ascii_case(protocol_name)) { - return Err(WebSocketError::ProtocolError("Protocol in Use not in client-supplied protocol list")); - }; - }; - - // Transitive subset of step 11. - // See step 15 of https://fetch.spec.whatwg.org/#http-network-fetch. - if let Some(cookies) = response.headers.get::() { - let mut jar = cookie_jar.write().unwrap(); - for cookie in &**cookies { - if let Some(cookie) = Cookie::new_wrapped(cookie.clone(), resource_url, CookieSource::HTTP) { - jar.push(cookie, resource_url, CookieSource::HTTP); - } - } - } - - let (sender, receiver) = response.begin().split(); - Ok((protocol_in_use, sender, receiver)) -} - pub fn init(connect: WebSocketCommunicate, connect_data: WebSocketConnectData, cookie_jar: Arc>) { thread::Builder::new().name(format!("WebSocket connection to {}", connect_data.resource_url)).spawn(move || { let channel = establish_a_websocket_connection(&connect_data.resource_url, @@ -182,3 +104,81 @@ pub fn init(connect: WebSocketCommunicate, connect_data: WebSocketConnectData, c } }).expect("Thread spawning failed"); } + +// https://fetch.spec.whatwg.org/#concept-websocket-establish +fn establish_a_websocket_connection(resource_url: &ServoUrl, + origin: String, + protocols: Vec, + cookie_jar: Arc>) + -> WebSocketResult<(Option, + Sender, + Receiver)> { + // Steps 1-2 are not really applicable here, given we don't exactly go + // through the same infrastructure as the Fetch spec. + + if should_be_blocked_due_to_bad_port(resource_url) { + // Subset of steps 11-12, we inline the bad port check here from the + // main fetch algorithm for the same reason steps 1-2 are not + // applicable. + return Err(WebSocketError::RequestError("Request should be blocked due to bad port.")); + } + + // Steps 3-7. + let net_url = replace_host_in_url(resource_url.clone()); + let mut request = try!(Client::connect(net_url.as_url())); + + // Client::connect sets the Host header to the host of the URL that is + // passed to it, so we need to reset it afterwards to the correct one. + request.headers.set(Host { + hostname: resource_url.host_str().unwrap().to_owned(), + port: resource_url.port(), + }); + + // Step 8. + if !protocols.is_empty() { + request.headers.set(WebSocketProtocol(protocols.clone())); + } + + // Steps 9-10. + // TODO: support for permessage-deflate extension. + + // Subset of step 11. + // See step 2 of https://fetch.spec.whatwg.org/#concept-fetch. + request.headers.set(Origin(origin)); + + // Transitive subset of step 11. + // See step 17.1 of https://fetch.spec.whatwg.org/#concept-http-network-or-cache-fetch. + http_loader::set_request_cookies(&resource_url, &mut request.headers, &cookie_jar); + + // Step 11, somewhat. + let response = try!(request.send()); + + // Step 12, 14. + try!(response.validate()); + + // Step 13 and transitive subset of step 14. + // See step 6 of http://tools.ietf.org/html/rfc6455#section-4.1. + let protocol_in_use = response.protocol().and_then(|header| { + // https://github.com/whatwg/fetch/issues/515 + header.first().cloned() + }); + if let Some(ref protocol_name) = protocol_in_use { + if !protocols.is_empty() && !protocols.iter().any(|p| (&**p).eq_ignore_ascii_case(protocol_name)) { + return Err(WebSocketError::ProtocolError("Protocol in Use not in client-supplied protocol list")); + }; + }; + + // Transitive subset of step 11. + // See step 15 of https://fetch.spec.whatwg.org/#http-network-fetch. + if let Some(cookies) = response.headers.get::() { + let mut jar = cookie_jar.write().unwrap(); + for cookie in &**cookies { + if let Some(cookie) = Cookie::new_wrapped(cookie.clone(), resource_url, CookieSource::HTTP) { + jar.push(cookie, resource_url, CookieSource::HTTP); + } + } + } + + let (sender, receiver) = response.begin().split(); + Ok((protocol_in_use, sender, receiver)) +} diff --git a/servo/components/net_traits/hosts.rs b/servo/components/net_traits/hosts.rs index dc81906683ee..741d9734df49 100644 --- a/servo/components/net_traits/hosts.rs +++ b/servo/components/net_traits/hosts.rs @@ -4,6 +4,7 @@ use parse_hosts::HostsFile; use servo_url::ServoUrl; +use std::borrow::Cow; use std::collections::HashMap; use std::env; use std::fs::File; @@ -56,19 +57,24 @@ pub fn parse_hostsfile(hostsfile_content: &str) -> HashMap { host_table } -pub fn replace_hosts(url: &ServoUrl) -> ServoUrl { - HOST_TABLE.lock().unwrap().as_ref().map_or_else(|| url.clone(), - |host_table| host_replacement(host_table, url)) +pub fn replace_host(host: &str) -> Cow { + HOST_TABLE.lock().unwrap().as_ref() + .and_then(|table| table.get(host)) + .map_or(host.into(), |replaced_host| replaced_host.to_string().into()) } -pub fn host_replacement(host_table: &HashMap, url: &ServoUrl) -> ServoUrl { - url.domain() - .and_then(|domain| { - host_table.get(domain).map(|ip| { - let mut new_url = url.clone(); - new_url.set_ip_host(*ip).unwrap(); - new_url - }) - }) - .unwrap_or_else(|| url.clone()) +pub fn replace_host_in_url(url: ServoUrl) -> ServoUrl { + if let Some(table) = HOST_TABLE.lock().unwrap().as_ref() { + host_replacement(table, url) + } else { + url + } +} + +pub fn host_replacement(host_table: &HashMap, mut url: ServoUrl) -> ServoUrl { + let replacement = url.domain().and_then(|domain| host_table.get(domain)); + if let Some(ip) = replacement { + url.set_ip_host(*ip).unwrap(); + } + url } diff --git a/servo/components/script/dom/htmlformelement.rs b/servo/components/script/dom/htmlformelement.rs index b958e8f12252..afcfd9c66901 100755 --- a/servo/components/script/dom/htmlformelement.rs +++ b/servo/components/script/dom/htmlformelement.rs @@ -384,12 +384,12 @@ impl HTMLFormElement { fn mutate_action_url(&self, form_data: &mut Vec, mut load_data: LoadData, encoding: EncodingRef) { let charset = &*encoding.whatwg_name().unwrap(); - if let Some(ref mut url) = load_data.url.as_mut_url() { - url.query_pairs_mut().clear() - .encoding_override(Some(self.pick_encoding())) - .extend_pairs(form_data.into_iter() - .map(|field| (field.name.clone(), field.replace_value(charset)))); - } + load_data.url + .as_mut_url() + .query_pairs_mut().clear() + .encoding_override(Some(self.pick_encoding())) + .extend_pairs(form_data.into_iter() + .map(|field| (field.name.clone(), field.replace_value(charset)))); self.plan_to_navigate(load_data); } @@ -403,13 +403,12 @@ impl HTMLFormElement { let charset = &*encoding.whatwg_name().unwrap(); load_data.headers.set(ContentType::form_url_encoded()); - - if let Some(ref mut url) = load_data.url.as_mut_url() { - url.query_pairs_mut().clear() - .encoding_override(Some(self.pick_encoding())) - .extend_pairs(form_data.into_iter() - .map(|field| (field.name.clone(), field.replace_value(charset)))); - } + load_data.url + .as_mut_url() + .query_pairs_mut().clear() + .encoding_override(Some(self.pick_encoding())) + .extend_pairs(form_data.into_iter() + .map(|field| (field.name.clone(), field.replace_value(charset)))); load_data.url.query().unwrap_or("").to_string().into_bytes() } diff --git a/servo/components/script/dom/url.rs b/servo/components/script/dom/url.rs index cf8a6201f8b9..a02a735638fc 100644 --- a/servo/components/script/dom/url.rs +++ b/servo/components/script/dom/url.rs @@ -52,9 +52,8 @@ impl URL { } pub fn set_query_pairs(&self, pairs: &[(String, String)]) { - if let Some(ref mut url) = self.url.borrow_mut().as_mut_url() { - url.query_pairs_mut().clear().extend_pairs(pairs); - } + let mut url = self.url.borrow_mut(); + url.as_mut_url().query_pairs_mut().clear().extend_pairs(pairs); } } diff --git a/servo/components/script/dom/urlhelper.rs b/servo/components/script/dom/urlhelper.rs index e001faf7a81a..d00189156f04 100644 --- a/servo/components/script/dom/urlhelper.rs +++ b/servo/components/script/dom/urlhelper.rs @@ -45,49 +45,31 @@ impl UrlHelper { USVString(quirks::username(url.as_url()).to_owned()) } pub fn SetHash(url: &mut ServoUrl, value: USVString) { - if let Some(ref mut url) = url.as_mut_url() { - quirks::set_hash(url, &value.0) - } + quirks::set_hash(url.as_mut_url(), &value.0) } pub fn SetHost(url: &mut ServoUrl, value: USVString) { - if let Some(ref mut url) = url.as_mut_url() { - let _ = quirks::set_host(url, &value.0); - } + let _ = quirks::set_host(url.as_mut_url(), &value.0); } pub fn SetPort(url: &mut ServoUrl, value: USVString) { - if let Some(ref mut url) = url.as_mut_url() { - let _ = quirks::set_port(url, &value.0); - } + let _ = quirks::set_port(url.as_mut_url(), &value.0); } pub fn SetSearch(url: &mut ServoUrl, value: USVString) { - if let Some(ref mut url) = url.as_mut_url() { - quirks::set_search(url, &value.0) - } + quirks::set_search(url.as_mut_url(), &value.0) } pub fn SetPathname(url: &mut ServoUrl, value: USVString) { - if let Some(ref mut url) = url.as_mut_url() { - quirks::set_pathname(url, &value.0) - } + quirks::set_pathname(url.as_mut_url(), &value.0) } pub fn SetHostname(url: &mut ServoUrl, value: USVString) { - if let Some(ref mut url) = url.as_mut_url() { - let _ = quirks::set_hostname(url, &value.0); - } + let _ = quirks::set_hostname(url.as_mut_url(), &value.0); } pub fn SetPassword(url: &mut ServoUrl, value: USVString) { - if let Some(ref mut url) = url.as_mut_url() { - let _ = quirks::set_password(url, &value.0); - } + let _ = quirks::set_password(url.as_mut_url(), &value.0); } pub fn SetProtocol(url: &mut ServoUrl, value: USVString) { - if let Some(ref mut url) = url.as_mut_url() { - let _ = quirks::set_protocol(url, &value.0); - } + let _ = quirks::set_protocol(url.as_mut_url(), &value.0); } pub fn SetUsername(url: &mut ServoUrl, value: USVString) { - if let Some(ref mut url) = url.as_mut_url() { - let _ = quirks::set_username(url, &value.0); - } + let _ = quirks::set_username(url.as_mut_url(), &value.0); } // https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy pub fn is_origin_trustworthy(url: &ServoUrl) -> bool { diff --git a/servo/components/url/lib.rs b/servo/components/url/lib.rs index 766c5bd5f5c9..3ed02fae11d7 100644 --- a/servo/components/url/lib.rs +++ b/servo/components/url/lib.rs @@ -47,10 +47,8 @@ impl ServoUrl { Arc::try_unwrap(self.0).unwrap_or_else(|s| (*s).clone()).into_string() } - // NOTE: These methods return options that are always true temporarily until - // we special-case some urls to avoid going through rust-url. - pub fn into_url(self) -> Option { - Some(Arc::try_unwrap(self.0).unwrap_or_else(|s| (*s).clone())) + pub fn into_url(self) -> Url { + Arc::try_unwrap(self.0).unwrap_or_else(|s| (*s).clone()) } pub fn as_url(&self) -> &Url { @@ -94,24 +92,24 @@ impl ServoUrl { self.0.as_str() } - pub fn as_mut_url(&mut self) -> Option<&mut Url> { - Some(Arc::make_mut(&mut self.0)) + pub fn as_mut_url(&mut self) -> &mut Url { + Arc::make_mut(&mut self.0) } pub fn set_username(&mut self, user: &str) -> Result<(), ()> { - Arc::make_mut(&mut self.0).set_username(user) + self.as_mut_url().set_username(user) } pub fn set_ip_host(&mut self, addr: IpAddr) -> Result<(), ()> { - Arc::make_mut(&mut self.0).set_ip_host(addr) + self.as_mut_url().set_ip_host(addr) } pub fn set_password(&mut self, pass: Option<&str>) -> Result<(), ()> { - Arc::make_mut(&mut self.0).set_password(pass) + self.as_mut_url().set_password(pass) } pub fn set_fragment(&mut self, fragment: Option<&str>) { - Arc::make_mut(&mut self.0).set_fragment(fragment) + self.as_mut_url().set_fragment(fragment) } pub fn username(&self) -> &str { diff --git a/servo/tests/unit/net/resource_thread.rs b/servo/tests/unit/net/resource_thread.rs index 0e3f01bb54c8..5062917b8dc9 100644 --- a/servo/tests/unit/net/resource_thread.rs +++ b/servo/tests/unit/net/resource_thread.rs @@ -151,11 +151,11 @@ fn test_replace_hosts() { host_table.insert("servo.test.server".to_owned(), ip("127.0.0.2")); let url = ServoUrl::parse("http://foo.bar.com:8000/foo").unwrap(); - assert_eq!(host_replacement(&host_table, &url).host_str().unwrap(), "127.0.0.1"); + assert_eq!(host_replacement(&host_table, url).host_str().unwrap(), "127.0.0.1"); let url = ServoUrl::parse("http://servo.test.server").unwrap(); - assert_eq!(host_replacement(&host_table, &url).host_str().unwrap(), "127.0.0.2"); + assert_eq!(host_replacement(&host_table, url).host_str().unwrap(), "127.0.0.2"); let url = ServoUrl::parse("http://a.foo.bar.com").unwrap(); - assert_eq!(host_replacement(&host_table, &url).host_str().unwrap(), "a.foo.bar.com"); + assert_eq!(host_replacement(&host_table, url).host_str().unwrap(), "a.foo.bar.com"); } From fa7afbcd275024163f404a8edc12c781eba1f617 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 26 Mar 2017 11:36:51 -0700 Subject: [PATCH 03/57] servo: Merge #16139 - Update rustc to 1.17.0-nightly (7dd4e2db7 2017-03-26) (from servo:rustup); r=emilio Source-Repo: https://github.com/servo/servo Source-Revision: 7f2a4e01b1c989f86a7a80af5ffe16ec93c34809 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 69c85cc061116261ded7e2da64ec0c8b16588896 --- servo/components/script/dom/element.rs | 4 ++-- servo/rust-commit-hash | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/servo/components/script/dom/element.rs b/servo/components/script/dom/element.rs index 59cc15875606..f11392cb4aa3 100644 --- a/servo/components/script/dom/element.rs +++ b/servo/components/script/dom/element.rs @@ -180,9 +180,9 @@ pub enum AdjacentPosition { } impl<'a> TryFrom<&'a str> for AdjacentPosition { - type Err = Error; + type Error = Error; - fn try_from(position: &'a str) -> Result { + fn try_from(position: &'a str) -> Result { match_ignore_ascii_case! { &*position, "beforebegin" => Ok(AdjacentPosition::BeforeBegin), "afterbegin" => Ok(AdjacentPosition::AfterBegin), diff --git a/servo/rust-commit-hash b/servo/rust-commit-hash index 87e4ade6ceca..9a8973790ee4 100644 --- a/servo/rust-commit-hash +++ b/servo/rust-commit-hash @@ -1 +1 @@ -8c72b7651f231f589bc81d78fb9602d5a0899213 +7dd4e2db785c8ec360a989f69891b1e97dd4d369 From d0e7f70a9bc004ac73a1fae5fe5279bf66e85623 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 26 Mar 2017 12:23:17 -0700 Subject: [PATCH 04/57] servo: Merge #16137 - Replace use of rustc_serialize::base64 by base64 (from nox:die-rustc-serialize-die); r=emilio Source-Repo: https://github.com/servo/servo Source-Revision: d992442dc6bb0b0c006b516c36ef4c6664e6b74c --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 75532b20415e21fbb1b16a599ca14a6ba9a72882 --- servo/Cargo.lock | 14 ++++++++++++-- servo/components/net/Cargo.toml | 2 +- servo/components/net/data_loader.rs | 4 ++-- servo/components/net/lib.rs | 2 +- servo/components/net/subresource_integrity.rs | 4 ++-- servo/components/script/Cargo.toml | 2 +- servo/components/script/dom/filereader.rs | 10 ++-------- servo/components/script/dom/htmlcanvaselement.rs | 4 ++-- servo/components/script/dom/window.rs | 9 +++------ servo/components/script/lib.rs | 2 +- servo/components/webdriver_server/Cargo.toml | 1 + servo/components/webdriver_server/lib.rs | 10 ++-------- 12 files changed, 30 insertions(+), 34 deletions(-) diff --git a/servo/Cargo.lock b/servo/Cargo.lock index 5e3948c63321..a586bdf60104 100644 --- a/servo/Cargo.lock +++ b/servo/Cargo.lock @@ -135,6 +135,14 @@ dependencies = [ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base64" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bincode" version = "1.0.0-alpha2" @@ -1671,6 +1679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "net" version = "0.0.1" dependencies = [ + "base64 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "brotli 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", @@ -1688,7 +1697,6 @@ dependencies = [ "openssl 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-verify 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "profile_traits 0.0.1", - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2241,6 +2249,7 @@ dependencies = [ "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "audio-video-metadata 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bluetooth_traits 0.0.1", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2285,7 +2294,6 @@ dependencies = [ "ref_filter_map 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ref_slice 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "script_layout_interface 0.0.1", "script_plugins 0.0.1", "script_traits 0.0.1", @@ -3157,6 +3165,7 @@ dependencies = [ name = "webdriver_server" version = "0.0.1" dependencies = [ + "base64 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3336,6 +3345,7 @@ dependencies = [ "checksum azure 0.15.0 (git+https://github.com/servo/rust-azure)" = "" "checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80" "checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842" +"checksum base64 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9892882c3bd89ed02dec391c128984c772b663a29700c32b5de0b33861cdf2bd" "checksum bincode 1.0.0-alpha2 (registry+https://github.com/rust-lang/crates.io-index)" = "62650bb5651ba8f0580cebf4ef255d791b8b0ef53800322661e1bb5791d42966" "checksum bindgen 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "facc480c409c373db3c870e377ce223e5e07d979efc2604691dc6f583e8ded0f" "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c" diff --git a/servo/components/net/Cargo.toml b/servo/components/net/Cargo.toml index 0751f05d212b..22366e90c5c3 100644 --- a/servo/components/net/Cargo.toml +++ b/servo/components/net/Cargo.toml @@ -10,6 +10,7 @@ name = "net" path = "lib.rs" [dependencies] +base64 = "0.4.1" brotli = "1.0.6" cookie = "0.2.5" devtools_traits = {path = "../devtools_traits"} @@ -27,7 +28,6 @@ net_traits = {path = "../net_traits"} openssl = "0.7.6" openssl-verify = "0.1" profile_traits = {path = "../profile_traits"} -rustc-serialize = "0.3" serde = "0.9" serde_derive = "0.9" serde_json = "0.9" diff --git a/servo/components/net/data_loader.rs b/servo/components/net/data_loader.rs index 9b2b8ce2ac74..b95a2ab34123 100644 --- a/servo/components/net/data_loader.rs +++ b/servo/components/net/data_loader.rs @@ -2,8 +2,8 @@ * 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 base64; use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value}; -use rustc_serialize::base64::FromBase64; use servo_url::ServoUrl; use url::Position; use url::percent_encoding::percent_decode; @@ -46,7 +46,7 @@ pub fn decode(url: &ServoUrl) -> Result { // FIXME(#2909): It’s unclear what to do with non-alphabet characters, // but Acid 3 apparently depends on spaces being ignored. bytes = bytes.into_iter().filter(|&b| b != b' ').collect::>(); - match bytes.from_base64() { + match base64::decode(&bytes) { Err(..) => return Err(DecodeError::NonBase64DataUri), Ok(data) => bytes = data, } diff --git a/servo/components/net/lib.rs b/servo/components/net/lib.rs index 90999cfcf62d..f7724b082224 100644 --- a/servo/components/net/lib.rs +++ b/servo/components/net/lib.rs @@ -7,6 +7,7 @@ #![feature(mpsc_select)] #![feature(step_by)] +extern crate base64; extern crate brotli; extern crate cookie as cookie_rs; extern crate devtools_traits; @@ -25,7 +26,6 @@ extern crate net_traits; extern crate openssl; extern crate openssl_verify; extern crate profile_traits; -extern crate rustc_serialize; extern crate serde; #[macro_use] extern crate serde_derive; diff --git a/servo/components/net/subresource_integrity.rs b/servo/components/net/subresource_integrity.rs index 7268edbf80e5..bddef7d18a89 100644 --- a/servo/components/net/subresource_integrity.rs +++ b/servo/components/net/subresource_integrity.rs @@ -2,9 +2,9 @@ * 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 base64; use net_traits::response::{Response, ResponseBody, ResponseType}; use openssl::crypto::hash::{hash, Type as MessageDigest}; -use rustc_serialize::base64::{STANDARD, ToBase64}; use std::iter::Filter; use std::str::Split; use std::sync::MutexGuard; @@ -120,7 +120,7 @@ fn apply_algorithm_to_response(body: MutexGuard, -> String { if let ResponseBody::Done(ref vec) = *body { let response_digest = hash(message_digest, vec); - response_digest.to_base64(STANDARD) + base64::encode(&response_digest) } else { unreachable!("Tried to calculate digest of incomplete response body") } diff --git a/servo/components/script/Cargo.toml b/servo/components/script/Cargo.toml index 266dc4c2ce88..699574f30dad 100644 --- a/servo/components/script/Cargo.toml +++ b/servo/components/script/Cargo.toml @@ -28,6 +28,7 @@ angle = {git = "https://github.com/servo/angle", branch = "servo"} app_units = "0.4" audio-video-metadata = "0.1.2" atomic_refcell = "0.1" +base64 = "0.4.1" bitflags = "0.7" bluetooth_traits = {path = "../bluetooth_traits"} byteorder = "1.0" @@ -69,7 +70,6 @@ range = {path = "../range"} ref_filter_map = "1.0.1" ref_slice = "1.0" regex = "0.2" -rustc-serialize = "0.3" script_layout_interface = {path = "../script_layout_interface"} script_plugins = {path = "../script_plugins"} script_traits = {path = "../script_traits"} diff --git a/servo/components/script/dom/filereader.rs b/servo/components/script/dom/filereader.rs index e28c08b5efa7..61da63a57e68 100644 --- a/servo/components/script/dom/filereader.rs +++ b/servo/components/script/dom/filereader.rs @@ -2,6 +2,7 @@ * 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 base64; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; @@ -29,7 +30,6 @@ use js::jsapi::JSAutoCompartment; use js::jsapi::JSContext; use js::jsval::{self, JSVal}; use js::typedarray::{ArrayBuffer, CreateWith}; -use rustc_serialize::base64::{CharacterSet, Config, Newline, ToBase64}; use script_thread::RunnableWrapper; use servo_atoms::Atom; use std::cell::Cell; @@ -247,13 +247,7 @@ impl FileReader { //https://w3c.github.io/FileAPI/#dfn-readAsDataURL fn perform_readasdataurl(result: &DOMRefCell>, data: ReadMetaData, bytes: &[u8]) { - let config = Config { - char_set: CharacterSet::UrlSafe, - newline: Newline::LF, - pad: true, - line_length: None - }; - let base64 = bytes.to_base64(config); + let base64 = base64::encode(bytes); let output = if data.blobtype.is_empty() { format!("data:base64,{}", base64) diff --git a/servo/components/script/dom/htmlcanvaselement.rs b/servo/components/script/dom/htmlcanvaselement.rs index dbbf695b2d42..ed8aca71c1d5 100644 --- a/servo/components/script/dom/htmlcanvaselement.rs +++ b/servo/components/script/dom/htmlcanvaselement.rs @@ -2,6 +2,7 @@ * 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 base64; use canvas_traits::{CanvasMsg, FromScriptMsg}; use dom::attr::Attr; use dom::bindings::cell::DOMRefCell; @@ -33,7 +34,6 @@ use ipc_channel::ipc::{self, IpcSender}; use js::error::throw_type_error; use js::jsapi::{HandleValue, JSContext}; use offscreen_gl_context::GLContextAttributes; -use rustc_serialize::base64::{STANDARD, ToBase64}; use script_layout_interface::HTMLCanvasData; use std::iter::repeat; use style::attr::AttrValue; @@ -296,7 +296,7 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement { encoder.encode(&raw_data, self.Width(), self.Height(), ColorType::RGBA(8)).unwrap(); } - let encoded = encoded.to_base64(STANDARD); + let encoded = base64::encode(&encoded); Ok(DOMString::from(format!("data:{};base64,{}", mime_type, encoded))) } } diff --git a/servo/components/script/dom/window.rs b/servo/components/script/dom/window.rs index b390c44217ad..9f25edc3a076 100644 --- a/servo/components/script/dom/window.rs +++ b/servo/components/script/dom/window.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use app_units::Au; +use base64; use bluetooth_traits::BluetoothRequest; use cssparser::Parser; use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType}; @@ -68,7 +69,6 @@ use num_traits::ToPrimitive; use open; use profile_traits::mem::ProfilerChan as MemProfilerChan; use profile_traits::time::ProfilerChan as TimeProfilerChan; -use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64}; use script_layout_interface::{TrustedNodeAddress, PendingImageState}; use script_layout_interface::message::{Msg, Reflow, ReflowQueryType, ScriptReflow}; use script_layout_interface::reporter::CSSErrorReporter; @@ -410,16 +410,13 @@ pub fn base64_btoa(input: DOMString) -> Fallible { // "and then must apply the base64 algorithm to that sequence of // octets, and return the result. [RFC4648]" - Ok(DOMString::from(octets.to_base64(STANDARD))) + Ok(DOMString::from(base64::encode(&octets))) } } // https://html.spec.whatwg.org/multipage/#atob pub fn base64_atob(input: DOMString) -> Fallible { // "Remove all space characters from input." - // serialize::base64::from_base64 ignores \r and \n, - // but it treats the other space characters as - // invalid input. fn is_html_space(c: char) -> bool { HTML_SPACE_CHARACTERS.iter().any(|&m| m == c) } @@ -456,7 +453,7 @@ pub fn base64_atob(input: DOMString) -> Fallible { return Err(Error::InvalidCharacter) } - match input.from_base64() { + match base64::decode(&input) { Ok(data) => Ok(DOMString::from(data.iter().map(|&b| b as char).collect::())), Err(..) => Err(Error::InvalidCharacter) } diff --git a/servo/components/script/lib.rs b/servo/components/script/lib.rs index aa2e2f4baf5c..ade3543bbe82 100644 --- a/servo/components/script/lib.rs +++ b/servo/components/script/lib.rs @@ -28,6 +28,7 @@ extern crate angle; extern crate app_units; extern crate atomic_refcell; extern crate audio_video_metadata; +extern crate base64; #[macro_use] extern crate bitflags; extern crate bluetooth_traits; @@ -78,7 +79,6 @@ extern crate range; extern crate ref_filter_map; extern crate ref_slice; extern crate regex; -extern crate rustc_serialize; extern crate script_layout_interface; extern crate script_traits; extern crate selectors; diff --git a/servo/components/webdriver_server/Cargo.toml b/servo/components/webdriver_server/Cargo.toml index e84f1ff0662d..08f21a60b5dc 100644 --- a/servo/components/webdriver_server/Cargo.toml +++ b/servo/components/webdriver_server/Cargo.toml @@ -10,6 +10,7 @@ name = "webdriver_server" path = "lib.rs" [dependencies] +base64 = "0.4.1" cookie = "0.2.5" euclid = "0.11" hyper = "0.9.9" diff --git a/servo/components/webdriver_server/lib.rs b/servo/components/webdriver_server/lib.rs index 831a8d323def..d0aa102e2e9e 100644 --- a/servo/components/webdriver_server/lib.rs +++ b/servo/components/webdriver_server/lib.rs @@ -7,6 +7,7 @@ #![deny(unsafe_code)] +extern crate base64; extern crate cookie as cookie_rs; extern crate euclid; extern crate hyper; @@ -34,7 +35,6 @@ use keys::keycodes_to_keys; use msg::constellation_msg::{FrameId, PipelineId, TraversalDirection}; use net_traits::image::base::PixelFormat; use regex::Captures; -use rustc_serialize::base64::{CharacterSet, Config, Newline, ToBase64}; use rustc_serialize::json::{Json, ToJson}; use script_traits::{ConstellationMsg, LoadData, WebDriverCommandMsg}; use script_traits::webdriver_msg::{LoadStatus, WebDriverCookieError, WebDriverFrameId}; @@ -831,13 +831,7 @@ impl Handler { let mut png_data = Vec::new(); DynamicImage::ImageRgb8(rgb).save(&mut png_data, ImageFormat::PNG).unwrap(); - let config = Config { - char_set: CharacterSet::Standard, - newline: Newline::LF, - pad: true, - line_length: None - }; - let encoded = png_data.to_base64(config); + let encoded = base64::encode(&png_data); Ok(WebDriverResponse::Generic(ValueResponse::new(encoded.to_json()))) } From ec4e11d8873f05d7788a3cc36d0f6dc2b286b95e Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Sun, 26 Mar 2017 14:04:07 -0700 Subject: [PATCH 05/57] servo: Merge #16113 - Update WR (opaque rect optimization, stacking context culling) (from glennw:update-wr-opaque-opt); r=mrobinson Source-Repo: https://github.com/servo/servo Source-Revision: 3b79bc25825ea416298b1917e0bd409b7044f837 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : becb4839ec630c1b8d5d59c6f14655def789c5ab --- servo/Cargo.lock | 50 +++++++++---------- .../components/canvas/canvas_paint_thread.rs | 3 +- servo/components/canvas/webgl_paint_thread.rs | 3 +- servo/components/layout/webrender_helpers.rs | 5 -- 4 files changed, 29 insertions(+), 32 deletions(-) diff --git a/servo/Cargo.lock b/servo/Cargo.lock index a586bdf60104..ee28bed693f2 100644 --- a/servo/Cargo.lock +++ b/servo/Cargo.lock @@ -292,7 +292,7 @@ dependencies = [ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "offscreen_gl_context 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "servo_config 0.0.1", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -306,7 +306,7 @@ dependencies = [ "ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -427,8 +427,8 @@ dependencies = [ "servo_url 0.0.1", "style_traits 0.0.1", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.25.0 (git+https://github.com/servo/webrender)", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -461,7 +461,7 @@ dependencies = [ "servo_remutex 0.0.1", "servo_url 0.0.1", "style_traits 0.0.1", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", "webvr_traits 0.0.1", ] @@ -706,7 +706,7 @@ dependencies = [ "servo_geometry 0.0.1", "servo_url 0.0.1", "style_traits 0.0.1", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", "x11 2.12.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -988,7 +988,7 @@ dependencies = [ "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", "truetype 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", "xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1067,7 +1067,7 @@ dependencies = [ "servo_url 0.0.1", "style_traits 0.0.1", "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "x11 2.12.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1378,7 +1378,7 @@ dependencies = [ "style_traits 0.0.1", "unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1418,7 +1418,7 @@ dependencies = [ "servo_geometry 0.0.1", "servo_url 0.0.1", "style 0.0.1", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1432,7 +1432,7 @@ dependencies = [ "profile_traits 0.0.1", "script_traits 0.0.1", "servo_url 0.0.1", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1517,8 +1517,8 @@ dependencies = [ "style 0.0.1", "style_traits 0.0.1", "webdriver_server 0.0.1", - "webrender 0.25.0 (git+https://github.com/servo/webrender)", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", "webvr 0.0.1", "webvr_traits 0.0.1", ] @@ -1667,7 +1667,7 @@ dependencies = [ "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1709,7 +1709,7 @@ dependencies = [ "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1767,7 +1767,7 @@ dependencies = [ "servo_url 0.0.1", "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -2312,7 +2312,7 @@ dependencies = [ "tinyfiledialogs 2.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", "webvr 0.0.1", "webvr_traits 0.0.1", "xml5ever 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3186,8 +3186,8 @@ dependencies = [ [[package]] name = "webrender" -version = "0.25.0" -source = "git+https://github.com/servo/webrender#0794911f97cae92496fca992d7430da696fa24eb" +version = "0.26.0" +source = "git+https://github.com/servo/webrender#b2dd9f792d0cb3dfc591567c105755f56f35956d" dependencies = [ "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.0-alpha2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3209,13 +3209,13 @@ dependencies = [ "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", ] [[package]] name = "webrender_traits" -version = "0.26.0" -source = "git+https://github.com/servo/webrender#0794911f97cae92496fca992d7430da696fa24eb" +version = "0.27.0" +source = "git+https://github.com/servo/webrender#b2dd9f792d0cb3dfc591567c105755f56f35956d" dependencies = [ "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3239,7 +3239,7 @@ dependencies = [ "msg 0.0.1", "script_traits 0.0.1", "servo_config 0.0.1", - "webrender_traits 0.26.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.27.0 (git+https://github.com/servo/webrender)", "webvr_traits 0.0.1", ] @@ -3582,8 +3582,8 @@ dependencies = [ "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" "checksum webdriver 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdc28802daddee94267a657ffeac2593a33881fb7a3a44fedd320b1319efcaf6" -"checksum webrender 0.25.0 (git+https://github.com/servo/webrender)" = "" -"checksum webrender_traits 0.26.0 (git+https://github.com/servo/webrender)" = "" +"checksum webrender 0.26.0 (git+https://github.com/servo/webrender)" = "" +"checksum webrender_traits 0.27.0 (git+https://github.com/servo/webrender)" = "" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum ws 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04614a58714f3fd4a8b1da4bcae9f031c532d35988c3d39627619248113f8be8" diff --git a/servo/components/canvas/canvas_paint_thread.rs b/servo/components/canvas/canvas_paint_thread.rs index 8aca22bdbfb1..7f09603d3226 100644 --- a/servo/components/canvas/canvas_paint_thread.rs +++ b/servo/components/canvas/canvas_paint_thread.rs @@ -567,7 +567,8 @@ impl<'a> CanvasPaintThread<'a> { offset: 0, is_opaque: false, }, - element.into()); + element.into(), + None); let data = CanvasImageData { image_key: self.webrender_image_key, diff --git a/servo/components/canvas/webgl_paint_thread.rs b/servo/components/canvas/webgl_paint_thread.rs index 2894df71a063..b5893c150585 100644 --- a/servo/components/canvas/webgl_paint_thread.rs +++ b/servo/components/canvas/webgl_paint_thread.rs @@ -261,7 +261,8 @@ impl WebGLPaintThread { offset: 0, is_opaque: false, }, - pixels.clone()); + pixels.clone(), + None); let image_data = CanvasImageData { image_key: image_key, diff --git a/servo/components/layout/webrender_helpers.rs b/servo/components/layout/webrender_helpers.rs index 3d2f434053d0..8c8427522efe 100644 --- a/servo/components/layout/webrender_helpers.rs +++ b/servo/components/layout/webrender_helpers.rs @@ -404,10 +404,6 @@ impl WebRenderDisplayItemConverter for DisplayItem { let stacking_context = &item.stacking_context; debug_assert!(stacking_context.context_type == StackingContextType::Real); - let clip = builder.new_clip_region(&stacking_context.overflow.to_rectf(), - vec![], - None); - let transform = stacking_context.transform.map(|transform| { LayoutTransform::from_untyped(&transform).into() }); @@ -417,7 +413,6 @@ impl WebRenderDisplayItemConverter for DisplayItem { builder.push_stacking_context(stacking_context.scroll_policy, stacking_context.bounds.to_rectf(), - clip, stacking_context.z_index, transform, perspective, From 926cc5294bec9520a1e0693d8ad5128fed3ff067 Mon Sep 17 00:00:00 2001 From: streichgeorg Date: Sun, 26 Mar 2017 14:56:23 -0700 Subject: [PATCH 06/57] servo: Merge #16136 - to_css of counter-increment returns none when there are no properties (from streichgeorg:counter); r=emilio Changed to_css in style::properties::longhands::counter_increment returns "none" if there are no properties defined. --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #15977 (github issue number if applicable). - [X] There are tests for these changes OR - [ ] These changes do not require tests because _____ Source-Repo: https://github.com/servo/servo Source-Revision: f4371dfa0231282ef4dfa47bdfc6d31fa5ce1a0d --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : c09d2af0d5eabc68a48798e40d08bf2a03425ba3 --- .../properties/longhand/counters.mako.rs | 5 ++++ .../unit/style/properties/serialization.rs | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/servo/components/style/properties/longhand/counters.mako.rs b/servo/components/style/properties/longhand/counters.mako.rs index f6b8173c610c..c4bbba8785a5 100644 --- a/servo/components/style/properties/longhand/counters.mako.rs +++ b/servo/components/style/properties/longhand/counters.mako.rs @@ -269,6 +269,10 @@ impl ToCss for SpecifiedValue { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + if self.0.is_empty() { + return dest.write_str("none"); + } + let mut first = true; for pair in &self.0 { if !first { @@ -278,6 +282,7 @@ try!(serialize_identifier(&pair.0, dest)); try!(write!(dest, " {}", pair.1)); } + Ok(()) } } diff --git a/servo/tests/unit/style/properties/serialization.rs b/servo/tests/unit/style/properties/serialization.rs index c95ae49cf7ed..73fdf184584e 100644 --- a/servo/tests/unit/style/properties/serialization.rs +++ b/servo/tests/unit/style/properties/serialization.rs @@ -1170,4 +1170,30 @@ mod shorthand_serialization { assert_eq!(shadow.to_css_string(), shadow_css); } } + + mod counter_increment { + pub use super::*; + pub use style::properties::longhands::counter_increment::SpecifiedValue as CounterIncrement; + + #[test] + fn counter_increment_with_properties_should_serialize_correctly() { + let mut properties = Vec::new(); + + properties.push(("counter1".to_owned(), 1)); + properties.push(("counter2".to_owned(), -4)); + + let counter_increment = CounterIncrement(properties); + let counter_increment_css = "counter1 1 counter2 -4"; + + assert_eq!(counter_increment.to_css_string(), counter_increment_css); + } + + #[test] + fn counter_increment_without_properties_should_serialize_correctly() { + let counter_increment = CounterIncrement(Vec::new()); + let counter_increment_css = "none"; + + assert_eq!(counter_increment.to_css_string(), counter_increment_css); + } + } } From 8abe43df06d67eebb5e67cd35045901da67b99d2 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Mon, 6 Mar 2017 17:19:26 +1300 Subject: [PATCH 07/57] bug 1343802 remove unused moz_gtk_enable_style_props r=jhorak+328198 MozReview-Commit-ID: KbAIRCyqmJ8 --HG-- extra : rebase_source : 4b468d9b6bab63a69df389d1a7624272f9ec1a43 --- widget/gtk/gtk2drawing.c | 8 -------- widget/gtk/gtk3drawing.cpp | 8 -------- widget/gtk/gtkdrawing.h | 12 ------------ 3 files changed, 28 deletions(-) diff --git a/widget/gtk/gtk2drawing.c b/widget/gtk/gtk2drawing.c index 1ac34eca425e..18855107e892 100644 --- a/widget/gtk/gtk2drawing.c +++ b/widget/gtk/gtk2drawing.c @@ -66,7 +66,6 @@ static GtkWidget* gHPanedWidget; static GtkWidget* gVPanedWidget; static GtkWidget* gScrolledWindowWidget; -static style_prop_t style_prop_func; static gboolean have_arrow_scaling; static gboolean is_initialized; @@ -79,13 +78,6 @@ moz_gtk_set_widget_name(GtkWidget* widget) gtk_widget_set_name(widget, "MozillaGtkWidget"); } -gint -moz_gtk_enable_style_props(style_prop_t styleGetProp) -{ - style_prop_func = styleGetProp; - return MOZ_GTK_SUCCESS; -} - static gint ensure_window_widget() { diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index 8ccc1e8e163d..a3dcb2648540 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -18,7 +18,6 @@ #include -static style_prop_t style_prop_func; static gboolean have_arrow_scaling; static gboolean checkbox_check_state; static gboolean notebook_has_tab_gap; @@ -77,13 +76,6 @@ GetStateFlagsFromGtkTabFlags(GtkTabFlags flags) GTK_STATE_FLAG_NORMAL : GTK_STATE_FLAG_ACTIVE; } -gint -moz_gtk_enable_style_props(style_prop_t styleGetProp) -{ - style_prop_func = styleGetProp; - return MOZ_GTK_SUCCESS; -} - gint moz_gtk_init() { diff --git a/widget/gtk/gtkdrawing.h b/widget/gtk/gtkdrawing.h index 16c49ab0d265..f88c7322018d 100644 --- a/widget/gtk/gtkdrawing.h +++ b/widget/gtk/gtkdrawing.h @@ -67,9 +67,6 @@ typedef enum { MOZ_GTK_TAB_SELECTED = 1 << 10 } GtkTabFlags; -/* function type for moz_gtk_enable_style_props */ -typedef gint (*style_prop_t)(GtkStyle*, const gchar*, gint); - /*** result/error codes ***/ #define MOZ_GTK_SUCCESS 0 #define MOZ_GTK_UNKNOWN_WIDGET -1 @@ -271,15 +268,6 @@ typedef enum { */ gint moz_gtk_init(); -/** - * Enable GTK+ 1.2.9+ theme enhancements. You must provide a pointer - * to the GTK+ 1.2.9+ function "gtk_style_get_prop_experimental". - * styleGetProp: pointer to gtk_style_get_prop_experimental - * - * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise - */ -gint moz_gtk_enable_style_props(style_prop_t styleGetProp); - /** * Perform cleanup of the drawing library. You should call this function * when your program exits, or you no longer need the library. From 713232a30d7a9f362ef7c3243cdd55cc1087105f Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 8 Mar 2017 18:24:19 +1300 Subject: [PATCH 08/57] bug 1343802 remove code for native scrollbar thumb border sizes r=jhorak+328198 There is no need to calculate thumb borders because thumb border-box sizes are determined with GetMinimumWidgetSize, which includes GTK margin, border, and padding, and the interior border width is irrelevant because thumbs have no children. MozReview-Commit-ID: K2N2RBJBRsB --HG-- extra : rebase_source : c750cdf9c9722f7796c89b8083bf2bfd32fffcbb --- widget/gtk/gtk3drawing.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index a3dcb2648540..d3ddff3e709a 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -2248,17 +2248,6 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, } break; - case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL: - case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL: - { - if (gtk_check_version(3,20,0) == nullptr) { - style = ClaimStyleContext(widget); - moz_gtk_add_margin_border_padding(style, left, top, right, bottom); - ReleaseStyleContext(style); - } - return MOZ_GTK_SUCCESS; - } - break; /* These widgets have no borders, since they are not containers. */ case MOZ_GTK_CHECKBUTTON_LABEL: case MOZ_GTK_RADIOBUTTON_LABEL: @@ -2267,6 +2256,8 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, case MOZ_GTK_CHECKBUTTON: case MOZ_GTK_RADIOBUTTON: case MOZ_GTK_SCROLLBAR_BUTTON: + case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL: + case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL: case MOZ_GTK_SCALE_THUMB_HORIZONTAL: case MOZ_GTK_SCALE_THUMB_VERTICAL: case MOZ_GTK_GRIPPER: From 1acd8cdab129366576d53efcaebbee203f6f997f Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Thu, 23 Mar 2017 18:23:26 +1300 Subject: [PATCH 09/57] bug 1343802 calculate scrollbar metrics in one place r=jhorak+328198 Changes in behavior are intended to be minimal, but this adds distinct metrics for horizontal and vertical scrollbars even with GTK versions < 3.20. Updates on theme changes will be restored in a subsequent patch. MozReview-Commit-ID: 4vi2nKxCxW7 --HG-- extra : rebase_source : 5e968126af00a7c1ff0a45d2ba3b46a0a20424be --- widget/gtk/gtk3drawing.cpp | 228 ++++++++++++++++++++------------ widget/gtk/gtkdrawing.h | 54 ++++---- widget/gtk/nsNativeThemeGTK.cpp | 121 +++++++---------- 3 files changed, 222 insertions(+), 181 deletions(-) diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index d3ddff3e709a..6c69e42647eb 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -23,6 +23,8 @@ static gboolean checkbox_check_state; static gboolean notebook_has_tab_gap; static gboolean is_initialized; +static ScrollbarGTKMetrics sScrollbarMetrics[2]; + #define ARROW_UP 0 #define ARROW_DOWN G_PI #define ARROW_RIGHT G_PI_2 @@ -435,7 +437,11 @@ calculate_arrow_rect(GtkWidget* arrow, GdkRectangle* rect, return MOZ_GTK_SUCCESS; } -void +/** + * Get minimum widget size as sum of margin, padding, border and + * min-width/min-height. + */ +static void moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width, int* height) { @@ -458,6 +464,14 @@ moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width, padding.top + padding.bottom; } +static MozGtkSize +GetMinMarginBox(WidgetNodeType aNodeType) +{ + gint width, height; + moz_gtk_get_widget_min_size(aNodeType, &width, &height); + return {width, height}; +} + static void Inset(GdkRectangle* rect, GtkBorder& aBorder) { @@ -538,18 +552,22 @@ moz_gtk_scrollbar_button_paint(cairo_t *cr, const GdkRectangle* aRect, // box occupies the full width of the "contents" gadget content box. InsetByMargin(&rect, style); } else { - // Scrollbar button has to be inset by trough_border because its DOM - // element is filling width of vertical scrollbar's track (or height - // in case of horizontal scrollbars). - MozGtkScrollbarMetrics metrics; - moz_gtk_get_scrollbar_metrics(&metrics); - if (flags & MOZ_GTK_STEPPER_VERTICAL) { - rect.x += metrics.trough_border; - rect.width = metrics.slider_width; - } else { - rect.y += metrics.trough_border; - rect.height = metrics.slider_width; - } + // Scrollbar button has to be inset by trough_border because its DOM + // element is filling width of vertical scrollbar's track (or height + // in case of horizontal scrollbars). + GtkOrientation orientation = flags & MOZ_GTK_STEPPER_VERTICAL ? + GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL; + const auto& metrics = sScrollbarMetrics[orientation]; + if (!metrics.initialized) { + NS_WARNING("Didn't measure before drawing?"); + } + if (flags & MOZ_GTK_STEPPER_VERTICAL) { + rect.x += metrics.border.track.left; + rect.width = metrics.size.thumb.width; + } else { + rect.y += metrics.border.track.top; + rect.height = metrics.size.thumb.height; + } } gtk_render_background(style, cr, rect.x, rect.y, rect.width, rect.height); @@ -2001,6 +2019,20 @@ static void moz_gtk_add_margin_border_padding(GtkStyleContext *style, moz_gtk_add_style_padding(style, left, top, right, bottom); } +static GtkBorder +GetMarginBorderPadding(GtkStyleContext* aStyle) +{ + gint left = 0, top = 0, right = 0, bottom = 0; + moz_gtk_add_margin_border_padding(aStyle, &left, &top, &right, &bottom); + // narrowing conversions to gint16: + GtkBorder result; + result.left = left; + result.right = right; + result.top = top; + result.bottom = bottom; + return result; +} + gint moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, gint* right, gint* bottom, GtkTextDirection direction, @@ -2204,49 +2236,6 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, return MOZ_GTK_SUCCESS; } - case MOZ_GTK_SCROLLBAR_VERTICAL: - case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL: - { - if (gtk_check_version(3,20,0) == nullptr) { - style = ClaimStyleContext(widget); - moz_gtk_add_margin_border_padding(style, left, top, right, bottom); - ReleaseStyleContext(style); - if (widget == MOZ_GTK_SCROLLBAR_VERTICAL) { - style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL); - moz_gtk_add_margin_border_padding(style, left, top, right, bottom); - ReleaseStyleContext(style); - } - } else { - MozGtkScrollbarMetrics metrics; - moz_gtk_get_scrollbar_metrics(&metrics); - /* Top and bottom border for whole vertical scrollbar, top and bottom - * border for horizontal track - to correctly position thumb element */ - *top = *bottom = metrics.trough_border; - } - return MOZ_GTK_SUCCESS; - } - break; - - case MOZ_GTK_SCROLLBAR_HORIZONTAL: - case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL: - { - if (gtk_check_version(3,20,0) == nullptr) { - style = ClaimStyleContext(widget); - moz_gtk_add_margin_border_padding(style, left, top, right, bottom); - ReleaseStyleContext(style); - if (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) { - style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL); - moz_gtk_add_margin_border_padding(style, left, top, right, bottom); - ReleaseStyleContext(style); - } - } else { - MozGtkScrollbarMetrics metrics; - moz_gtk_get_scrollbar_metrics(&metrics); - *left = *right = metrics.trough_border; - } - return MOZ_GTK_SUCCESS; - } - break; /* These widgets have no borders, since they are not containers. */ case MOZ_GTK_CHECKBUTTON_LABEL: @@ -2555,23 +2544,108 @@ moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* return MOZ_GTK_SUCCESS; } -gint -moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics) +static MozGtkSize +SizeFromLengthAndBreadth(GtkOrientation aOrientation, + gint aLength, gint aBreadth) { - // For Gtk >= 3.20 scrollbar metrics are ignored - MOZ_ASSERT(gtk_check_version(3, 20, 0) != nullptr); + return aOrientation == GTK_ORIENTATION_HORIZONTAL ? + MozGtkSize({aLength, aBreadth}) : MozGtkSize({aBreadth, aLength}); +} - GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_VERTICAL); - gtk_style_context_get_style(style, - "slider_width", &metrics->slider_width, - "trough_border", &metrics->trough_border, - "stepper_size", &metrics->stepper_size, - "stepper_spacing", &metrics->stepper_spacing, - "min-slider-length", &metrics->min_slider_size, - nullptr); +const ScrollbarGTKMetrics* +GetScrollbarMetrics(GtkOrientation aOrientation) +{ + auto metrics = &sScrollbarMetrics[aOrientation]; + if (metrics->initialized) + return metrics; + + metrics->initialized = true; + + WidgetNodeType scrollbar = aOrientation == GTK_ORIENTATION_HORIZONTAL ? + MOZ_GTK_SCROLLBAR_HORIZONTAL : MOZ_GTK_SCROLLBAR_VERTICAL; + + if (gtk_get_minor_version() < 20) { + gint slider_width, trough_border, stepper_size, min_slider_size; + gboolean backward, forward, secondary_backward, secondary_forward; + + GtkStyleContext* style = ClaimStyleContext(scrollbar); + gtk_style_context_get_style(style, + "slider-width", &slider_width, + "trough-border", &trough_border, + "stepper-size", &stepper_size, + "min-slider-length", &min_slider_size, + "has-backward-stepper", &backward, + "has-forward-stepper", &forward, + "has-secondary-backward-stepper", + &secondary_backward, + "has-secondary-forward-stepper", + &secondary_forward, nullptr); + ReleaseStyleContext(style); + + metrics->size.thumb = + SizeFromLengthAndBreadth(aOrientation, min_slider_size, slider_width); + metrics->size.button = + SizeFromLengthAndBreadth(aOrientation, stepper_size, slider_width); + // overall scrollbar + gint breadth = slider_width + 2 * trough_border; + // Require room for the slider in the track if we don't have buttons. + bool hasButtons = backward || forward || + secondary_backward || secondary_forward; + gint length = hasButtons ? 0 : min_slider_size + 2 * trough_border; + metrics->size.scrollbar = + SizeFromLengthAndBreadth(aOrientation, length, breadth); + + // Borders on the major axis are set on the outermost scrollbar + // element to correctly position the buttons when + // trough-under-steppers is true. + // Borders on the minor axis are set on the track element so that it + // receives mouse events, as in GTK. + // Other borders have been zero-initialized. + if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { + metrics->border.scrollbar.left = + metrics->border.scrollbar.right = + metrics->border.track.top = + metrics->border.track.bottom = trough_border; + } else { + metrics->border.scrollbar.top = + metrics->border.scrollbar.bottom = + metrics->border.track.left = + metrics->border.track.right = trough_border; + } + + return metrics; + } + + // GTK version > 3.20 + WidgetNodeType contents, track, thumb; + if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { + contents = MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL; + track = MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL; + thumb = MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL; + } else { + contents = MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL; + track = MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL; + thumb = MOZ_GTK_SCROLLBAR_THUMB_VERTICAL; + } + // thumb + metrics->size.thumb = GetMinMarginBox(thumb); + // track + GtkStyleContext* style = ClaimStyleContext(track); + metrics->border.track = GetMarginBorderPadding(style); ReleaseStyleContext(style); + // button + metrics->size.button = GetMinMarginBox(MOZ_GTK_SCROLLBAR_BUTTON); + // scrollbar + style = ClaimStyleContext(scrollbar); + metrics->border.scrollbar = GetMarginBorderPadding(style); + ReleaseStyleContext(style); + style = ClaimStyleContext(contents); + GtkBorder contentsBorder = GetMarginBorderPadding(style); + ReleaseStyleContext(style); + metrics->size.scrollbar = metrics->size.thumb + metrics->border.track + + contentsBorder + metrics->border.scrollbar; - return MOZ_GTK_SUCCESS; + return metrics; } /* cairo_t *cr argument has to be a system-cairo. */ @@ -2818,22 +2892,6 @@ GtkWidget* moz_gtk_get_scrollbar_widget(void) return GetWidget(MOZ_GTK_SCROLLBAR_HORIZONTAL); } -gboolean moz_gtk_has_scrollbar_buttons(void) -{ - gboolean backward, forward, secondary_backward, secondary_forward; - MOZ_ASSERT(is_initialized, "Forgot to call moz_gtk_init()"); - GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_VERTICAL); - gtk_style_context_get_style(style, - "has-backward-stepper", &backward, - "has-forward-stepper", &forward, - "has-secondary-backward-stepper", &secondary_backward, - "has-secondary-forward-stepper", &secondary_forward, - NULL); - ReleaseStyleContext(style); - - return backward | forward | secondary_forward | secondary_forward; -} - gint moz_gtk_shutdown() { diff --git a/widget/gtk/gtkdrawing.h b/widget/gtk/gtkdrawing.h index f88c7322018d..4b3598d9342e 100644 --- a/widget/gtk/gtkdrawing.h +++ b/widget/gtk/gtkdrawing.h @@ -39,13 +39,33 @@ typedef struct { gint32 maxpos; } GtkWidgetState; +/** + * A size in the same GTK pixel units as GtkBorder and GdkRectangle. + */ +struct MozGtkSize { + gint width; + gint height; + + MozGtkSize operator+(const GtkBorder& aBorder) const + { + gint resultWidth = width + aBorder.left + aBorder.right; + gint resultHeight = height + aBorder.top + aBorder.bottom; + return {resultWidth, resultHeight}; + } +}; + typedef struct { - gint slider_width; - gint trough_border; - gint stepper_size; - gint stepper_spacing; - gint min_slider_size; -} MozGtkScrollbarMetrics; + bool initialized; + struct { + MozGtkSize scrollbar; + MozGtkSize thumb; + MozGtkSize button; + } size; + struct { + GtkBorder scrollbar; + GtkBorder track; + } border; +} ScrollbarGTKMetrics; typedef enum { MOZ_GTK_STEPPER_DOWN = 1 << 0, @@ -420,13 +440,10 @@ gint moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height); /** - * Get the desired metrics for a GtkScrollbar - * metrics: [IN] struct which will contain the metrics - * - * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise + * Get the metrics in GTK pixels for a scrollbar. */ -gint -moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics* metrics); +const ScrollbarGTKMetrics* +GetScrollbarMetrics(GtkOrientation aOrientation); /** * Get the desired size of a dropdown arrow button @@ -517,19 +534,6 @@ GtkWidget* moz_gtk_get_scrollbar_widget(void); gint moz_gtk_get_tab_thickness(WidgetNodeType aNodeType); -/** - * Get a boolean which indicates whether the theme draws scrollbar buttons. - * If TRUE, draw scrollbar buttons. - */ -gboolean moz_gtk_has_scrollbar_buttons(void); - -/** - * Get minimum widget size as sum of margin, padding, border and min-width, - * min-height. - */ -void moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width, - int* height); - #if (MOZ_WIDGET_GTK == 2) #ifdef __cplusplus } diff --git a/widget/gtk/nsNativeThemeGTK.cpp b/widget/gtk/nsNativeThemeGTK.cpp index 89b8ab7dc8da..8b06eb5be9a3 100644 --- a/widget/gtk/nsNativeThemeGTK.cpp +++ b/widget/gtk/nsNativeThemeGTK.cpp @@ -1265,6 +1265,36 @@ nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame, GtkTextDirection direction = GetTextDirection(aFrame); aResult->top = aResult->left = aResult->right = aResult->bottom = 0; switch (aWidgetType) { + case NS_THEME_SCROLLBAR_HORIZONTAL: + case NS_THEME_SCROLLBAR_VERTICAL: + { + GtkOrientation orientation = + aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; + const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation); + + const GtkBorder& border = metrics->border.scrollbar; + aResult->top = border.top; + aResult->right = border.right; + aResult->bottom = border.bottom; + aResult->left = border.left; + } + break; + case NS_THEME_SCROLLBARTRACK_HORIZONTAL: + case NS_THEME_SCROLLBARTRACK_VERTICAL: + { + GtkOrientation orientation = + aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; + const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation); + + const GtkBorder& border = metrics->border.track; + aResult->top = border.top; + aResult->right = border.right; + aResult->bottom = border.bottom; + aResult->left = border.left; + } + break; case NS_THEME_TOOLBOX: // gtk has no toolbox equivalent. So, although we map toolbox to // gtk's 'toolbar' for purposes of painting the widget background, @@ -1419,33 +1449,22 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, case NS_THEME_SCROLLBARBUTTON_UP: case NS_THEME_SCROLLBARBUTTON_DOWN: { - if (gtk_check_version(3,20,0) == nullptr) { - moz_gtk_get_widget_min_size(MOZ_GTK_SCROLLBAR_BUTTON, - &(aResult->width), &(aResult->height)); - } else { - MozGtkScrollbarMetrics metrics; - moz_gtk_get_scrollbar_metrics(&metrics); - - aResult->width = metrics.slider_width; - aResult->height = metrics.stepper_size; - } + const ScrollbarGTKMetrics* metrics = + GetScrollbarMetrics(GTK_ORIENTATION_VERTICAL); + aResult->width = metrics->size.button.width; + aResult->height = metrics->size.button.height; *aIsOverridable = false; } break; case NS_THEME_SCROLLBARBUTTON_LEFT: case NS_THEME_SCROLLBARBUTTON_RIGHT: { - if (gtk_check_version(3,20,0) == nullptr) { - moz_gtk_get_widget_min_size(MOZ_GTK_SCROLLBAR_BUTTON, - &(aResult->width), &(aResult->height)); - } else { - MozGtkScrollbarMetrics metrics; - moz_gtk_get_scrollbar_metrics(&metrics); + const ScrollbarGTKMetrics* metrics = + GetScrollbarMetrics(GTK_ORIENTATION_HORIZONTAL); - aResult->width = metrics.stepper_size; - aResult->height = metrics.slider_width; - } + aResult->width = metrics->size.button.width; + aResult->height = metrics->size.button.height; *aIsOverridable = false; } break; @@ -1472,65 +1491,25 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, * the thumb isn't a direct child of the scrollbar, unlike the buttons * or track. So add a minimum size to the track as well to prevent a * 0-width scrollbar. */ - if (gtk_check_version(3,20,0) == nullptr) { - // Thumb min dimensions to start with - WidgetNodeType thumbType = aWidgetType == NS_THEME_SCROLLBAR_VERTICAL ? - MOZ_GTK_SCROLLBAR_THUMB_VERTICAL : MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL; - moz_gtk_get_widget_min_size(thumbType, &(aResult->width), &(aResult->height)); - - // Add scrollbar's borders - nsIntMargin border; - nsNativeThemeGTK::GetWidgetBorder(aFrame->PresContext()->DeviceContext(), - aFrame, aWidgetType, &border); - aResult->width += border.left + border.right; - aResult->height += border.top + border.bottom; - - // Add track's borders - uint8_t trackType = aWidgetType == NS_THEME_SCROLLBAR_VERTICAL ? - NS_THEME_SCROLLBARTRACK_VERTICAL : NS_THEME_SCROLLBARTRACK_HORIZONTAL; - nsNativeThemeGTK::GetWidgetBorder(aFrame->PresContext()->DeviceContext(), - aFrame, trackType, &border); - aResult->width += border.left + border.right; - aResult->height += border.top + border.bottom; - } else { - MozGtkScrollbarMetrics metrics; - moz_gtk_get_scrollbar_metrics(&metrics); - - // Require room for the slider in the track if we don't have buttons. - bool hasScrollbarButtons = moz_gtk_has_scrollbar_buttons(); - - if (aWidgetType == NS_THEME_SCROLLBAR_VERTICAL) { - aResult->width = metrics.slider_width + 2 * metrics.trough_border; - if (!hasScrollbarButtons) - aResult->height = metrics.min_slider_size + 2 * metrics.trough_border; - } else { - aResult->height = metrics.slider_width + 2 * metrics.trough_border; - if (!hasScrollbarButtons) - aResult->width = metrics.min_slider_size + 2 * metrics.trough_border; - } - *aIsOverridable = false; - } + GtkOrientation orientation = + aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; + const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation); + aResult->width = metrics->size.scrollbar.width; + aResult->height = metrics->size.scrollbar.height; } break; case NS_THEME_SCROLLBARTHUMB_VERTICAL: case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: { - if (gtk_check_version(3,20,0) == nullptr) { - moz_gtk_get_widget_min_size(NativeThemeToGtkTheme(aWidgetType, aFrame), - &(aResult->width), &(aResult->height)); - } else { - MozGtkScrollbarMetrics metrics; - moz_gtk_get_scrollbar_metrics(&metrics); + GtkOrientation orientation = + aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; + const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation); - if (aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL) { - aResult->width = metrics.slider_width; - aResult->height = metrics.min_slider_size; - } else { - aResult->height = metrics.slider_width; - aResult->width = metrics.min_slider_size; - } - } + aResult->width = metrics->size.thumb.width; + aResult->height = metrics->size.thumb.height; *aIsOverridable = false; } break; From 62cb3af1245d62de09573ed5395be8fe9a48b981 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Tue, 21 Mar 2017 17:14:55 +1300 Subject: [PATCH 10/57] bug 1343802 remove moz_gtk_get_scrollbar_widget() r=jhorak+328198 This was used with GTK2, but is now unnecessary as discussed in bug 1278282. moz_gtk_init() is now called from only one place and so will be called only once. MozReview-Commit-ID: 2KwJop6qsV9 --HG-- extra : rebase_source : 5649f34914f03f8285eeaad7937d1ecab853649d --- widget/gtk/gtk3drawing.cpp | 12 ------------ widget/gtk/gtkdrawing.h | 6 ------ widget/gtk/nsLookAndFeel.cpp | 8 ++++---- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index 6c69e42647eb..71fbde179d78 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -21,7 +21,6 @@ static gboolean have_arrow_scaling; static gboolean checkbox_check_state; static gboolean notebook_has_tab_gap; -static gboolean is_initialized; static ScrollbarGTKMetrics sScrollbarMetrics[2]; @@ -81,10 +80,6 @@ GetStateFlagsFromGtkTabFlags(GtkTabFlags flags) gint moz_gtk_init() { - if (is_initialized) - return MOZ_GTK_SUCCESS; - - is_initialized = TRUE; have_arrow_scaling = (gtk_major_version > 2 || (gtk_major_version == 2 && gtk_minor_version >= 12)); if (gtk_major_version > 3 || @@ -2887,18 +2882,11 @@ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr, return MOZ_GTK_UNKNOWN_WIDGET; } -GtkWidget* moz_gtk_get_scrollbar_widget(void) -{ - return GetWidget(MOZ_GTK_SCROLLBAR_HORIZONTAL); -} - gint moz_gtk_shutdown() { /* This will destroy all of our widgets */ ResetWidgetCache(); - is_initialized = FALSE; - return MOZ_GTK_SUCCESS; } diff --git a/widget/gtk/gtkdrawing.h b/widget/gtk/gtkdrawing.h index 4b3598d9342e..e3a4ff94cf4f 100644 --- a/widget/gtk/gtkdrawing.h +++ b/widget/gtk/gtkdrawing.h @@ -522,12 +522,6 @@ gint moz_gtk_get_menu_separator_height(gint* size); */ gint moz_gtk_splitter_get_metrics(gint orientation, gint* size); -/** - * Retrieve an actual GTK scrollbar widget for style analysis. It will not - * be modified. - */ -GtkWidget* moz_gtk_get_scrollbar_widget(void); - /** * Get the YTHICKNESS of a tab (notebook extension). */ diff --git a/widget/gtk/nsLookAndFeel.cpp b/widget/gtk/nsLookAndFeel.cpp index 1047f017447b..5f2a399e36f4 100644 --- a/widget/gtk/nsLookAndFeel.cpp +++ b/widget/gtk/nsLookAndFeel.cpp @@ -777,11 +777,11 @@ nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) aResult = threshold; } break; - case eIntID_ScrollArrowStyle: - moz_gtk_init(); - aResult = - ConvertGTKStepperStyleToMozillaScrollArrowStyle(moz_gtk_get_scrollbar_widget()); + case eIntID_ScrollArrowStyle: { + GtkWidget* scrollbar = GetWidget(MOZ_GTK_SCROLLBAR_HORIZONTAL); + aResult = ConvertGTKStepperStyleToMozillaScrollArrowStyle(scrollbar); break; + } case eIntID_ScrollSliderStyle: aResult = eScrollThumbStyle_Proportional; break; From bf6572082000be8c5242f529660921dc04a50685 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Tue, 21 Mar 2017 17:12:34 +1300 Subject: [PATCH 11/57] bug 1343802 remove have_arrow_scaling, which was always true r=jhorak+328198 MozReview-Commit-ID: AeM2oKoPCTs --HG-- extra : rebase_source : f2013b07ff2f344107fac5e21ac491953f38ecc4 --- widget/gtk/gtk3drawing.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index 71fbde179d78..cc08539d6922 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -18,7 +18,6 @@ #include -static gboolean have_arrow_scaling; static gboolean checkbox_check_state; static gboolean notebook_has_tab_gap; @@ -80,8 +79,6 @@ GetStateFlagsFromGtkTabFlags(GtkTabFlags flags) gint moz_gtk_init() { - have_arrow_scaling = (gtk_major_version > 2 || - (gtk_major_version == 2 && gtk_minor_version >= 12)); if (gtk_major_version > 3 || (gtk_major_version == 3 && gtk_minor_version >= 14)) checkbox_check_state = GTK_STATE_FLAG_CHECKED; @@ -409,9 +406,8 @@ calculate_arrow_rect(GtkWidget* arrow, GdkRectangle* rect, gfloat mxalign, myalign; GtkMisc* misc = GTK_MISC(arrow); - if (have_arrow_scaling) - gtk_style_context_get_style(gtk_widget_get_style_context(arrow), - "arrow_scaling", &arrow_scaling, NULL); + gtk_style_context_get_style(gtk_widget_get_style_context(arrow), + "arrow_scaling", &arrow_scaling, NULL); gtk_misc_get_padding(misc, &mxpad, &mypad); extent = MIN((rect->width - mxpad * 2), From d25338e8222eca88d21061538a1062078a277fd6 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Tue, 21 Mar 2017 17:27:41 +1300 Subject: [PATCH 12/57] bug 1343802 update notebook_has_tab_gap and scrollbar metrics after theme changes r=jhorak+328198 MozReview-Commit-ID: IRPXNwLe5Ey --HG-- extra : rebase_source : 1b8a8691b793380421fc01e439050125fdfd71f2 --- widget/gtk/gtk3drawing.cpp | 11 ++++++++++- widget/gtk/gtkdrawing.h | 5 +++++ widget/gtk/nsLookAndFeel.cpp | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index cc08539d6922..87cb32b3be0e 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -85,6 +85,14 @@ moz_gtk_init() else checkbox_check_state = GTK_STATE_FLAG_ACTIVE; + moz_gtk_refresh(); + + return MOZ_GTK_SUCCESS; +} + +void +moz_gtk_refresh() +{ if (gtk_check_version(3, 12, 0) == nullptr && gtk_check_version(3, 20, 0) != nullptr) { @@ -98,7 +106,8 @@ moz_gtk_init() notebook_has_tab_gap = true; } - return MOZ_GTK_SUCCESS; + sScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false; + sScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false; } gint diff --git a/widget/gtk/gtkdrawing.h b/widget/gtk/gtkdrawing.h index e3a4ff94cf4f..1d9142c91b4b 100644 --- a/widget/gtk/gtkdrawing.h +++ b/widget/gtk/gtkdrawing.h @@ -288,6 +288,11 @@ typedef enum { */ gint moz_gtk_init(); +/** + * Updates the drawing library when the theme changes. + */ +void moz_gtk_refresh(); + /** * Perform cleanup of the drawing library. You should call this function * when your program exits, or you no longer need the library. diff --git a/widget/gtk/nsLookAndFeel.cpp b/widget/gtk/nsLookAndFeel.cpp index 5f2a399e36f4..8868f3363233 100644 --- a/widget/gtk/nsLookAndFeel.cpp +++ b/widget/gtk/nsLookAndFeel.cpp @@ -1445,6 +1445,7 @@ void nsLookAndFeel::RefreshImpl() { nsXPLookAndFeel::RefreshImpl(); + moz_gtk_refresh(); mDefaultFontCached = false; mButtonFontCached = false; From 2e7cb463b097e4386f3fe7c6a563199ddb6f0bec Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Thu, 23 Mar 2017 18:31:16 +1300 Subject: [PATCH 13/57] bug 1343802 adjust scrollbar track border to prevent thumb expanding to fill available breadth r=jhorak+328198+328198 MozReview-Commit-ID: 7KJGnds0ngL --HG-- extra : rebase_source : c14cb16e27423f2887348d392c7c37f1aa02082a --- widget/gtk/gtk3drawing.cpp | 67 ++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index 87cb32b3be0e..6702ff95c8c1 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -2564,22 +2564,27 @@ GetScrollbarMetrics(GtkOrientation aOrientation) WidgetNodeType scrollbar = aOrientation == GTK_ORIENTATION_HORIZONTAL ? MOZ_GTK_SCROLLBAR_HORIZONTAL : MOZ_GTK_SCROLLBAR_VERTICAL; + gboolean backward, forward, secondary_backward, secondary_forward; + GtkStyleContext* style = ClaimStyleContext(scrollbar); + gtk_style_context_get_style(style, + "has-backward-stepper", &backward, + "has-forward-stepper", &forward, + "has-secondary-backward-stepper", + &secondary_backward, + "has-secondary-forward-stepper", + &secondary_forward, nullptr); + bool hasButtons = + backward || forward || secondary_backward || secondary_forward; + if (gtk_get_minor_version() < 20) { gint slider_width, trough_border, stepper_size, min_slider_size; - gboolean backward, forward, secondary_backward, secondary_forward; - GtkStyleContext* style = ClaimStyleContext(scrollbar); gtk_style_context_get_style(style, "slider-width", &slider_width, "trough-border", &trough_border, "stepper-size", &stepper_size, "min-slider-length", &min_slider_size, - "has-backward-stepper", &backward, - "has-forward-stepper", &forward, - "has-secondary-backward-stepper", - &secondary_backward, - "has-secondary-forward-stepper", - &secondary_forward, nullptr); + nullptr); ReleaseStyleContext(style); metrics->size.thumb = @@ -2589,8 +2594,6 @@ GetScrollbarMetrics(GtkOrientation aOrientation) // overall scrollbar gint breadth = slider_width + 2 * trough_border; // Require room for the slider in the track if we don't have buttons. - bool hasButtons = backward || forward || - secondary_backward || secondary_forward; gint length = hasButtons ? 0 : min_slider_size + 2 * trough_border; metrics->size.scrollbar = SizeFromLengthAndBreadth(aOrientation, length, breadth); @@ -2617,6 +2620,10 @@ GetScrollbarMetrics(GtkOrientation aOrientation) } // GTK version > 3.20 + // scrollbar + metrics->border.scrollbar = GetMarginBorderPadding(style); + ReleaseStyleContext(style); + WidgetNodeType contents, track, thumb; if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { contents = MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL; @@ -2630,20 +2637,44 @@ GetScrollbarMetrics(GtkOrientation aOrientation) // thumb metrics->size.thumb = GetMinMarginBox(thumb); // track - GtkStyleContext* style = ClaimStyleContext(track); + style = ClaimStyleContext(track); metrics->border.track = GetMarginBorderPadding(style); ReleaseStyleContext(style); + MozGtkSize trackSizeForThumb = metrics->size.thumb + metrics->border.track; // button - metrics->size.button = GetMinMarginBox(MOZ_GTK_SCROLLBAR_BUTTON); - // scrollbar - style = ClaimStyleContext(scrollbar); - metrics->border.scrollbar = GetMarginBorderPadding(style); - ReleaseStyleContext(style); + if (hasButtons) { + metrics->size.button = GetMinMarginBox(MOZ_GTK_SCROLLBAR_BUTTON); + // If the buttons will cause Gecko to expand the track to fill + // available breadth, then add to the track border to prevent Gecko + // from expanding the thumb to fill available breadth. + if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { + gint extra = metrics->size.button.height - trackSizeForThumb.height; + if (extra > 0) { + // If extra is odd, then the thumb is 0.5 pixels above + // center as in gtk_range_compute_slider_position(). + metrics->border.track.top += extra / 2; + metrics->border.track.bottom += extra - extra / 2; + // Update size for change in border. + trackSizeForThumb.height += extra; + } + } else { + gint extra = metrics->size.button.width - trackSizeForThumb.width; + if (extra > 0) { + // If extra is odd, then the thumb is 0.5 pixels to the left + // of center as in gtk_range_compute_slider_position(). + metrics->border.track.left += extra / 2; + metrics->border.track.right += extra - extra / 2; + trackSizeForThumb.width += extra; + } + } + } + style = ClaimStyleContext(contents); GtkBorder contentsBorder = GetMarginBorderPadding(style); ReleaseStyleContext(style); - metrics->size.scrollbar = metrics->size.thumb + metrics->border.track + - contentsBorder + metrics->border.scrollbar; + + metrics->size.scrollbar = + trackSizeForThumb + contentsBorder + metrics->border.scrollbar; return metrics; } From cb62e93514037de940bd240cd2707074d7ce7eff Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Tue, 21 Mar 2017 20:50:36 +1300 Subject: [PATCH 14/57] bug 1343802 swap vertical scrollbar button dimensions for horizontal scrollbars r=jhorak+328198 MozReview-Commit-ID: 4fK0hFRWn1p --HG-- extra : rebase_source : 5342134f69a210f2afdcd835dbb4bbbde429b506 --- widget/gtk/gtk3drawing.cpp | 7 ++++--- widget/gtk/gtkdrawing.h | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index 6702ff95c8c1..2a481d70b587 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -2644,10 +2644,11 @@ GetScrollbarMetrics(GtkOrientation aOrientation) // button if (hasButtons) { metrics->size.button = GetMinMarginBox(MOZ_GTK_SCROLLBAR_BUTTON); - // If the buttons will cause Gecko to expand the track to fill - // available breadth, then add to the track border to prevent Gecko - // from expanding the thumb to fill available breadth. if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { + metrics->size.button.Rotate(); + // If the buttons will cause Gecko to expand the track to fill + // available breadth, then add to the track border to prevent Gecko + // from expanding the thumb to fill available breadth. gint extra = metrics->size.button.height - trackSizeForThumb.height; if (extra > 0) { // If extra is odd, then the thumb is 0.5 pixels above diff --git a/widget/gtk/gtkdrawing.h b/widget/gtk/gtkdrawing.h index 1d9142c91b4b..521ed05e09c7 100644 --- a/widget/gtk/gtkdrawing.h +++ b/widget/gtk/gtkdrawing.h @@ -52,6 +52,12 @@ struct MozGtkSize { gint resultHeight = height + aBorder.top + aBorder.bottom; return {resultWidth, resultHeight}; } + void Rotate() + { + gint tmp = width; + width = height; + height = tmp; + } }; typedef struct { From 36050a07d8130e173e90f612f2517d2df59a1a28 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 22 Mar 2017 15:53:49 +1300 Subject: [PATCH 15/57] bug 1343802 consider scrollbar trough min-width/min-height properties r=jhorak+328198 in determining breadth of trough and scrollbar. MozReview-Commit-ID: 3orNXdv6uZh --HG-- extra : rebase_source : ad840ac199569da2e2fed7aa5e37ecc48a022fe2 --- widget/gtk/gtk3drawing.cpp | 66 +++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index 2a481d70b587..e079d46f1a84 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -437,6 +437,18 @@ calculate_arrow_rect(GtkWidget* arrow, GdkRectangle* rect, return MOZ_GTK_SUCCESS; } +static MozGtkSize +GetMinContentBox(GtkStyleContext* style) +{ + GtkStateFlags state_flags = gtk_style_context_get_state(style); + gint width, height; + gtk_style_context_get(style, state_flags, + "min-width", &width, + "min-height", &height, + nullptr); + return {width, height}; +} + /** * Get minimum widget size as sum of margin, padding, border and * min-width/min-height. @@ -2639,34 +2651,42 @@ GetScrollbarMetrics(GtkOrientation aOrientation) // track style = ClaimStyleContext(track); metrics->border.track = GetMarginBorderPadding(style); + MozGtkSize trackMinSize = GetMinContentBox(style) + metrics->border.track; ReleaseStyleContext(style); MozGtkSize trackSizeForThumb = metrics->size.thumb + metrics->border.track; // button if (hasButtons) { metrics->size.button = GetMinMarginBox(MOZ_GTK_SCROLLBAR_BUTTON); - if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { - metrics->size.button.Rotate(); - // If the buttons will cause Gecko to expand the track to fill - // available breadth, then add to the track border to prevent Gecko - // from expanding the thumb to fill available breadth. - gint extra = metrics->size.button.height - trackSizeForThumb.height; - if (extra > 0) { - // If extra is odd, then the thumb is 0.5 pixels above - // center as in gtk_range_compute_slider_position(). - metrics->border.track.top += extra / 2; - metrics->border.track.bottom += extra - extra / 2; - // Update size for change in border. - trackSizeForThumb.height += extra; - } - } else { - gint extra = metrics->size.button.width - trackSizeForThumb.width; - if (extra > 0) { - // If extra is odd, then the thumb is 0.5 pixels to the left - // of center as in gtk_range_compute_slider_position(). - metrics->border.track.left += extra / 2; - metrics->border.track.right += extra - extra / 2; - trackSizeForThumb.width += extra; - } + } else { + metrics->size.button = {0, 0}; + } + if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { + metrics->size.button.Rotate(); + // If the track is wider than necessary for the thumb, including when + // the buttons will cause Gecko to expand the track to fill + // available breadth, then add to the track border to prevent Gecko + // from expanding the thumb to fill available breadth. + gint extra = + std::max(trackMinSize.height, + metrics->size.button.height) - trackSizeForThumb.height; + if (extra > 0) { + // If extra is odd, then the thumb is 0.5 pixels above + // center as in gtk_range_compute_slider_position(). + metrics->border.track.top += extra / 2; + metrics->border.track.bottom += extra - extra / 2; + // Update size for change in border. + trackSizeForThumb.height += extra; + } + } else { + gint extra = + std::max(trackMinSize.width, + metrics->size.button.width) - trackSizeForThumb.width; + if (extra > 0) { + // If extra is odd, then the thumb is 0.5 pixels to the left + // of center as in gtk_range_compute_slider_position(). + metrics->border.track.left += extra / 2; + metrics->border.track.right += extra - extra / 2; + trackSizeForThumb.width += extra; } } From 4cf270684e77af355ec8525f1dcbbc6d10c737b2 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Thu, 23 Mar 2017 18:17:49 +1300 Subject: [PATCH 16/57] bug 1343802 draw trough centered instead of filling the scrollbar r=jhorak+328198 to follow the behavior of version 3.20 GtkRange's contents_gadget. MozReview-Commit-ID: BQE6mQqsan8 --HG-- extra : rebase_source : ee0f35da45f3da2248f50ee925fb7f8e9b848636 --- widget/gtk/gtk3drawing.cpp | 34 +++++++++++++++++++++++++++++++--- widget/gtk/gtkdrawing.h | 16 +++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index e079d46f1a84..1eb37c878cee 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -39,6 +39,9 @@ static gint moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect, GtkWidgetState* state, GtkTextDirection direction); +static GtkBorder +GetMarginBorderPadding(GtkStyleContext* aStyle); + // GetStateFlagsFromGtkWidgetState() can be safely used for the specific // GtkWidgets that set both prelight and active flags. For other widgets, // either the GtkStateFlags or Gecko's GtkWidgetState need to be carefully @@ -651,12 +654,37 @@ moz_gtk_draw_styled_frame(GtkStyleContext* style, cairo_t *cr, static gint moz_gtk_scrollbar_trough_paint(WidgetNodeType widget, - cairo_t *cr, const GdkRectangle* rect, + cairo_t *cr, const GdkRectangle* aRect, GtkWidgetState* state, GtkTextDirection direction) { - GtkStyleContext* style = ClaimStyleContext(widget, direction); - moz_gtk_draw_styled_frame(style, cr, rect, state->focused); + GdkRectangle rect = *aRect; + GtkStyleContext* style; + + if (gtk_get_minor_version() >= 20) { + WidgetNodeType thumb = widget == MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL ? + MOZ_GTK_SCROLLBAR_THUMB_VERTICAL : + MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL; + MozGtkSize thumbSize = GetMinMarginBox(thumb); + style = ClaimStyleContext(widget, direction); + MozGtkSize trackSize = GetMinContentBox(style); + trackSize.Include(thumbSize); + trackSize += GetMarginBorderPadding(style); + // Gecko's trough |aRect| fills available breadth, but GTK's trough is + // centered in the contents_gadget. The centering here round left + // and up, like gtk_box_gadget_allocate_child(). + if (widget == MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL) { + rect.x += (rect.width - trackSize.width)/2; + rect.width = trackSize.width; + } else { + rect.y += (rect.height - trackSize.height)/2; + rect.height = trackSize.height; + } + } else { + style = ClaimStyleContext(widget, direction); + } + + moz_gtk_draw_styled_frame(style, cr, &rect, state->focused); ReleaseStyleContext(style); return MOZ_GTK_SUCCESS; diff --git a/widget/gtk/gtkdrawing.h b/widget/gtk/gtkdrawing.h index 521ed05e09c7..9753174443a2 100644 --- a/widget/gtk/gtkdrawing.h +++ b/widget/gtk/gtkdrawing.h @@ -46,11 +46,21 @@ struct MozGtkSize { gint width; gint height; + MozGtkSize& operator+=(const GtkBorder& aBorder) + { + width += aBorder.left + aBorder.right; + height += aBorder.top + aBorder.bottom; + return *this; + } MozGtkSize operator+(const GtkBorder& aBorder) const { - gint resultWidth = width + aBorder.left + aBorder.right; - gint resultHeight = height + aBorder.top + aBorder.bottom; - return {resultWidth, resultHeight}; + MozGtkSize result = *this; + return result += aBorder; + } + void Include(MozGtkSize aOther) + { + width = std::max(width, aOther.width); + height = std::max(height, aOther.height); } void Rotate() { From 6040f31965b4b1540f401bf0d5523d9fad3f4376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 26 Mar 2017 16:42:48 -0700 Subject: [PATCH 17/57] servo: Merge #16142 - style: Make PercentageOrNumber also reject negative percentages (from emilio:dumbness); r=canaltinova It always returns true, so this is just stupid. Source-Repo: https://github.com/servo/servo Source-Revision: 7b64c3c4196ac6c12a02413d209bfa744e9a637b --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 2502f283df799ce839a74fbd2177fcdcb1aab482 --- .../style/values/specified/length.rs | 23 ++++++++++++++----- .../components/style/values/specified/mod.rs | 11 ++++----- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/servo/components/style/values/specified/length.rs b/servo/components/style/values/specified/length.rs index 5aa839874b43..58c14b713762 100644 --- a/servo/components/style/values/specified/length.rs +++ b/servo/components/style/values/specified/length.rs @@ -909,15 +909,26 @@ impl ToCss for Percentage { } } +impl Percentage { + fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result { + match try!(input.next()) { + Token::Percentage(ref value) if context.is_ok(value.unit_value) => { + Ok(Percentage(value.unit_value)) + } + _ => Err(()) + } + } + + /// Parses a percentage token, but rejects it if it's negative. + pub fn parse_non_negative(input: &mut Parser) -> Result { + Self::parse_internal(input, AllowedNumericType::NonNegative) + } +} + impl Parse for Percentage { #[inline] fn parse(_context: &ParserContext, input: &mut Parser) -> Result { - let context = AllowedNumericType::All; - match try!(input.next()) { - Token::Percentage(ref value) if context.is_ok(value.unit_value) => - Ok(Percentage(value.unit_value)), - _ => Err(()) - } + Self::parse_internal(input, AllowedNumericType::All) } } diff --git a/servo/components/style/values/specified/mod.rs b/servo/components/style/values/specified/mod.rs index 1a7fda7a6731..1cea83d5329e 100644 --- a/servo/components/style/values/specified/mod.rs +++ b/servo/components/style/values/specified/mod.rs @@ -538,8 +538,8 @@ impl Parse for Number { impl Number { fn parse_with_minimum(input: &mut Parser, min: CSSFloat) -> Result { match parse_number(input) { - Ok(value) if value < min => Err(()), - value => value.map(Number), + Ok(value) if value >= min => Ok(Number(value)), + _ => Err(()), } } @@ -585,13 +585,12 @@ pub enum NumberOrPercentage { no_viewport_percentage!(NumberOrPercentage); impl Parse for NumberOrPercentage { - fn parse(context: &ParserContext, input: &mut Parser) -> Result { - if let Ok(per) = input.try(|input| Percentage::parse(context, input)) { + fn parse(_context: &ParserContext, input: &mut Parser) -> Result { + if let Ok(per) = input.try(Percentage::parse_non_negative) { return Ok(NumberOrPercentage::Percentage(per)); } - let num = try!(Number::parse_non_negative(input)); - Ok(NumberOrPercentage::Number(num)) + Number::parse_non_negative(input).map(NumberOrPercentage::Number) } } From f63f14451694ba3c6d581662fbc25534b811b259 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Mon, 27 Mar 2017 09:15:26 +0900 Subject: [PATCH 18/57] Bug 1350743 - Make KeyframeEffectReadOnly::ResolveBaseStyle return void. r=birtles Also it's renamed to EnsureBaseStyle. We didn't use the return value at all. MozReview-Commit-ID: Cu4rnAP883M --HG-- extra : rebase_source : 1ced02e7ebd6a3c6c66c45f4a2a0b24e0bce6031 --- dom/animation/KeyframeEffectReadOnly.cpp | 54 ++++++++++++------------ dom/animation/KeyframeEffectReadOnly.h | 7 +-- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/dom/animation/KeyframeEffectReadOnly.cpp b/dom/animation/KeyframeEffectReadOnly.cpp index 2332ee98237e..3c83ded7962f 100644 --- a/dom/animation/KeyframeEffectReadOnly.cpp +++ b/dom/animation/KeyframeEffectReadOnly.cpp @@ -407,33 +407,6 @@ KeyframeEffectReadOnly::CompositeValue( return StyleAnimationValue(); } -StyleAnimationValue -KeyframeEffectReadOnly::ResolveBaseStyle(nsCSSPropertyID aProperty, - nsStyleContext* aStyleContext) -{ - StyleAnimationValue result; - if (mBaseStyleValues.Get(aProperty, &result)) { - return result; - } - - RefPtr styleContextWithoutAnimation = - aStyleContext->PresContext()->StyleSet()->AsGecko()-> - ResolveStyleByRemovingAnimation(mTarget->mElement, - aStyleContext, - eRestyle_AllHintsWithAnimations); - DebugOnly success = - StyleAnimationValue::ExtractComputedValue(aProperty, - styleContextWithoutAnimation, - result); - - MOZ_ASSERT(success, "Should be able to extract computed animation value"); - MOZ_ASSERT(!result.IsNull(), "Should have a valid StyleAnimationValue"); - - mBaseStyleValues.Put(aProperty, result); - - return result; -} - StyleAnimationValue KeyframeEffectReadOnly::GetUnderlyingStyle( nsCSSPropertyID aProperty, @@ -496,12 +469,37 @@ KeyframeEffectReadOnly::EnsureBaseStyles( continue; } - Unused << ResolveBaseStyle(property.mProperty, aStyleContext); + EnsureBaseStyle(property.mProperty, aStyleContext); break; } } } +void +KeyframeEffectReadOnly::EnsureBaseStyle(nsCSSPropertyID aProperty, + nsStyleContext* aStyleContext) +{ + if (mBaseStyleValues.Contains(aProperty)) { + return; + } + + RefPtr styleContextWithoutAnimation = + aStyleContext->PresContext()->StyleSet()->AsGecko()-> + ResolveStyleByRemovingAnimation(mTarget->mElement, + aStyleContext, + eRestyle_AllHintsWithAnimations); + StyleAnimationValue result; + DebugOnly success = + StyleAnimationValue::ExtractComputedValue(aProperty, + styleContextWithoutAnimation, + result); + + MOZ_ASSERT(success, "Should be able to extract computed animation value"); + MOZ_ASSERT(!result.IsNull(), "Should have a valid StyleAnimationValue"); + + mBaseStyleValues.Put(aProperty, result); +} + void KeyframeEffectReadOnly::WillComposeStyle() { diff --git a/dom/animation/KeyframeEffectReadOnly.h b/dom/animation/KeyframeEffectReadOnly.h index f0441eff6d9e..9ef92df5f5d7 100644 --- a/dom/animation/KeyframeEffectReadOnly.h +++ b/dom/animation/KeyframeEffectReadOnly.h @@ -417,9 +417,10 @@ protected: // FIXME: Bug 1311257: Support missing keyframes. } - // Returns the base style resolved by |aStyleContext| for |aProperty|. - StyleAnimationValue ResolveBaseStyle(nsCSSPropertyID aProperty, - nsStyleContext* aStyleContext); + // If no base style is already stored for |aProperty|, resolves the base style + // for |aProperty| using |aStyleContext| and stores it in mBaseStyleValues. + void EnsureBaseStyle(nsCSSPropertyID aProperty, + nsStyleContext* aStyleContext); Maybe mTarget; From 7b0ef88536fec58a5855bdf923a3318e87933501 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Mon, 27 Mar 2017 09:15:26 +0900 Subject: [PATCH 19/57] Bug 1350743 - Re-use nsStyleContext without animations to extract animation values for each property. r=birtles MozReview-Commit-ID: L4AmCAp0DLn --HG-- extra : rebase_source : 568be90539c7ffb0c47e03c4a8d1687e5560e87d --- dom/animation/KeyframeEffectReadOnly.cpp | 27 ++++++++++++++++-------- dom/animation/KeyframeEffectReadOnly.h | 6 +++++- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/dom/animation/KeyframeEffectReadOnly.cpp b/dom/animation/KeyframeEffectReadOnly.cpp index 3c83ded7962f..e4e79a8fcbd8 100644 --- a/dom/animation/KeyframeEffectReadOnly.cpp +++ b/dom/animation/KeyframeEffectReadOnly.cpp @@ -463,35 +463,44 @@ KeyframeEffectReadOnly::EnsureBaseStyles( mBaseStyleValues.Clear(); + RefPtr cachedBaseStyleContext; + for (const AnimationProperty& property : aProperties) { for (const AnimationPropertySegment& segment : property.mSegments) { if (segment.HasReplacableValues()) { continue; } - EnsureBaseStyle(property.mProperty, aStyleContext); + EnsureBaseStyle(property.mProperty, + aStyleContext, + cachedBaseStyleContext); break; } } } void -KeyframeEffectReadOnly::EnsureBaseStyle(nsCSSPropertyID aProperty, - nsStyleContext* aStyleContext) +KeyframeEffectReadOnly::EnsureBaseStyle( + nsCSSPropertyID aProperty, + nsStyleContext* aStyleContext, + RefPtr& aCachedBaseStyleContext) { if (mBaseStyleValues.Contains(aProperty)) { return; } - RefPtr styleContextWithoutAnimation = - aStyleContext->PresContext()->StyleSet()->AsGecko()-> - ResolveStyleByRemovingAnimation(mTarget->mElement, - aStyleContext, - eRestyle_AllHintsWithAnimations); + if (!aCachedBaseStyleContext) { + aCachedBaseStyleContext = + aStyleContext->PresContext()->StyleSet()->AsGecko()-> + ResolveStyleByRemovingAnimation(mTarget->mElement, + aStyleContext, + eRestyle_AllHintsWithAnimations); + } + StyleAnimationValue result; DebugOnly success = StyleAnimationValue::ExtractComputedValue(aProperty, - styleContextWithoutAnimation, + aCachedBaseStyleContext, result); MOZ_ASSERT(success, "Should be able to extract computed animation value"); diff --git a/dom/animation/KeyframeEffectReadOnly.h b/dom/animation/KeyframeEffectReadOnly.h index 9ef92df5f5d7..7ef1f9aa680a 100644 --- a/dom/animation/KeyframeEffectReadOnly.h +++ b/dom/animation/KeyframeEffectReadOnly.h @@ -419,8 +419,12 @@ protected: // If no base style is already stored for |aProperty|, resolves the base style // for |aProperty| using |aStyleContext| and stores it in mBaseStyleValues. + // If |aCachedBaseStyleContext| is non-null, it will be used, otherwise the + // base style context will be resolved and stored in + // |aCachedBaseStyleContext|. void EnsureBaseStyle(nsCSSPropertyID aProperty, - nsStyleContext* aStyleContext); + nsStyleContext* aStyleContext, + RefPtr& aCachedBaseStyleContext); Maybe mTarget; From 2e2e70805e611caaa28f9667f4364ec733ebbbbd Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Mon, 27 Mar 2017 09:15:26 +0900 Subject: [PATCH 20/57] Bug 1350743 - Rename AnimationPropertySegment::HasReplacableValues to AnimationPropertySegment::HasReplaceableValues. r=birtles MozReview-Commit-ID: KNwZhFvG5PJ --HG-- extra : rebase_source : 28819462a86d1ad2050314dc7a5f5a68e69bf7b9 --- dom/animation/KeyframeEffectReadOnly.cpp | 4 ++-- dom/animation/KeyframeEffectReadOnly.h | 8 ++++---- layout/base/nsLayoutUtils.cpp | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dom/animation/KeyframeEffectReadOnly.cpp b/dom/animation/KeyframeEffectReadOnly.cpp index e4e79a8fcbd8..4383b66a3788 100644 --- a/dom/animation/KeyframeEffectReadOnly.cpp +++ b/dom/animation/KeyframeEffectReadOnly.cpp @@ -467,7 +467,7 @@ KeyframeEffectReadOnly::EnsureBaseStyles( for (const AnimationProperty& property : aProperties) { for (const AnimationPropertySegment& segment : property.mSegments) { - if (segment.HasReplacableValues()) { + if (segment.HasReplaceableValues()) { continue; } @@ -1660,7 +1660,7 @@ KeyframeEffectReadOnly::CalculateCumulativeChangeHint( // we can't throttle animations which will not cause any layout changes // on invisible elements because we can't calculate the change hint for // such properties until we compose it. - if (!segment.HasReplacableValues()) { + if (!segment.HasReplaceableValues()) { mCumulativeChangeHint = ~nsChangeHint_Hints_CanIgnoreIfNotVisible; return; } diff --git a/dom/animation/KeyframeEffectReadOnly.h b/dom/animation/KeyframeEffectReadOnly.h index 7ef1f9aa680a..4fd3f02982f6 100644 --- a/dom/animation/KeyframeEffectReadOnly.h +++ b/dom/animation/KeyframeEffectReadOnly.h @@ -65,18 +65,18 @@ struct AnimationPropertySegment dom::CompositeOperation mFromComposite = dom::CompositeOperation::Replace; dom::CompositeOperation mToComposite = dom::CompositeOperation::Replace; - bool HasReplacableValues() const + bool HasReplaceableValues() const { - return HasReplacableFromValue() && HasReplacableToValue(); + return HasReplaceableFromValue() && HasReplaceableToValue(); } - bool HasReplacableFromValue() const + bool HasReplaceableFromValue() const { return !mFromValue.IsNull() && mFromComposite == dom::CompositeOperation::Replace; } - bool HasReplacableToValue() const + bool HasReplaceableToValue() const { return !mToValue.IsNull() && mToComposite == dom::CompositeOperation::Replace; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index f5eed0d1335a..b43b3ef12197 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -603,10 +603,10 @@ GetMinAndMaxScaleForAnimationProperty(const nsIFrame* aFrame, for (const AnimationPropertySegment& segment : prop.mSegments) { // In case of add or accumulate composite, StyleAnimationValue does // not have a valid value. - if (segment.HasReplacableFromValue()) { + if (segment.HasReplaceableFromValue()) { UpdateMinMaxScale(aFrame, segment.mFromValue, aMinScale, aMaxScale); } - if (segment.HasReplacableToValue()) { + if (segment.HasReplaceableToValue()) { UpdateMinMaxScale(aFrame, segment.mToValue, aMinScale, aMaxScale); } } From f02a65b840c3f91a2441aa46bd8a3166f0bcebb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 26 Mar 2017 17:21:49 -0700 Subject: [PATCH 21/57] servo: Merge #16141 - style: Add ::from_ident helper to avoid tokenizing the same value multiple times (from emilio:keyword-from-ident); r=nox We can use this to avoid tokenizing multiple times in some places, like #16127. Source-Repo: https://github.com/servo/servo Source-Revision: 447742b0a70395e55d6d1518fa51ad5b190abc8c --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 25adf3ad8feae17a3038424f4c9274d44c54fc58 --- servo/components/style_traits/values.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/servo/components/style_traits/values.rs b/servo/components/style_traits/values.rs index c06652d06db7..a142f3bab489 100644 --- a/servo/components/style_traits/values.rs +++ b/servo/components/style_traits/values.rs @@ -117,7 +117,12 @@ macro_rules! __define_css_keyword_enum__actual { /// Parse this property from a CSS input stream. pub fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> { let ident = input.expect_ident()?; - match_ignore_ascii_case! { &ident, + Self::from_ident(&ident) + } + + /// Parse this property from an already-tokenized identifier. + pub fn from_ident(ident: &str) -> Result<$name, ()> { + match_ignore_ascii_case! { ident, $( $css => Ok($name::$variant), )+ _ => Err(()) } From 829c0b3b869be33cc7c6700f3192549750fa785c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 26 Mar 2017 18:05:40 -0700 Subject: [PATCH 22/57] servo: Merge #16143 - style: Be consistent with naming and serialization of "0" with LenghtOrPercentageOrNumber (from emilio:lops); r=Manishearth Source-Repo: https://github.com/servo/servo Source-Revision: c20bbb920c8368898cb851ef7e02dc9791bf80aa --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : c5e215913d6d306a9a3691ca9b9beeb06bd57b4d --- .../properties/longhand/inherited_svg.mako.rs | 4 +++- servo/components/style/values/computed/mod.rs | 2 +- servo/components/style/values/specified/mod.rs | 16 ++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/servo/components/style/properties/longhand/inherited_svg.mako.rs b/servo/components/style/properties/longhand/inherited_svg.mako.rs index 5c2fee9a4271..31d393f13fca 100644 --- a/servo/components/style/properties/longhand/inherited_svg.mako.rs +++ b/servo/components/style/properties/longhand/inherited_svg.mako.rs @@ -92,7 +92,9 @@ ${helpers.predefined_type("stroke-opacity", "Opacity", "1.0", products="gecko", animatable=False, spec="https://www.w3.org/TR/SVG11/painting.html#StrokeOpacityProperty")} -${helpers.predefined_type("stroke-dasharray", "LoPOrNumber", "Either::Second(0.0)", +${helpers.predefined_type("stroke-dasharray", + "LengthOrPercentageOrNumber", + "Either::Second(0.0)", "parse_non_negative", vector="True", products="gecko", diff --git a/servo/components/style/values/computed/mod.rs b/servo/components/style/values/computed/mod.rs index 9ed8f81ee137..6436c7ffff79 100644 --- a/servo/components/style/values/computed/mod.rs +++ b/servo/components/style/values/computed/mod.rs @@ -400,7 +400,7 @@ impl ToCss for SVGPaint { } /// | | -pub type LoPOrNumber = Either; +pub type LengthOrPercentageOrNumber = Either; #[derive(Clone, PartialEq, Eq, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] diff --git a/servo/components/style/values/specified/mod.rs b/servo/components/style/values/specified/mod.rs index 1cea83d5329e..5e3fb5c59828 100644 --- a/servo/components/style/values/specified/mod.rs +++ b/servo/components/style/values/specified/mod.rs @@ -979,18 +979,18 @@ impl ToComputedValue for SVGPaintKind { } /// | | -pub type LoPOrNumber = Either; +pub type LengthOrPercentageOrNumber = Either; -impl LoPOrNumber { +impl LengthOrPercentageOrNumber { /// parse a | enforcing that the contents aren't negative pub fn parse_non_negative(_: &ParserContext, input: &mut Parser) -> Result { - if let Ok(lop) = input.try(LengthOrPercentage::parse_non_negative) { - Ok(Either::First(lop)) - } else if let Ok(num) = input.try(Number::parse_non_negative) { - Ok(Either::Second(num)) - } else { - Err(()) + // NB: Parse numbers before Lengths so we are consistent about how to + // recognize and serialize "0". + if let Ok(num) = input.try(Number::parse_non_negative) { + return Ok(Either::Second(num)) } + + LengthOrPercentage::parse_non_negative(input).map(Either::First) } } From e13f0faefe227e5bdd933d8d1be2d844f7dfaaf9 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Wed, 8 Mar 2017 17:11:27 +0800 Subject: [PATCH 23/57] Bug 1318226. P1 - preserve the order of regular tasks. r=bholley MozReview-Commit-ID: FYjbJWYDyd0 --HG-- extra : rebase_source : 1baeeb8d4e5904094bd258893d5cb59ec9ac8944 extra : intermediate-source : 224087f24319d562484be55f3b97a21f9d50577b extra : source : b6e940be26be76ae7620037b93c98e42504ed979 --- xpcom/threads/TaskDispatcher.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/xpcom/threads/TaskDispatcher.h b/xpcom/threads/TaskDispatcher.h index 405c3acfee47..7e28a62c3b19 100644 --- a/xpcom/threads/TaskDispatcher.h +++ b/xpcom/threads/TaskDispatcher.h @@ -124,7 +124,15 @@ public: already_AddRefed aRunnable, AbstractThread::DispatchFailureHandling aFailureHandling) override { - PerThreadTaskGroup& group = EnsureTaskGroup(aThread); + // To preserve the event order, we need to append a new group if the last + // group is not targeted for |aThread|. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1318226&mark=0-3#c0 + // for the details of the issue. + if (mTaskGroups.Length() == 0 || mTaskGroups.LastElement()->mThread != aThread) { + mTaskGroups.AppendElement(new PerThreadTaskGroup(aThread)); + } + + PerThreadTaskGroup& group = *mTaskGroups.LastElement(); group.mRegularTasks.AppendElement(aRunnable); // The task group needs to assert dispatch success if any of the runnables @@ -142,11 +150,11 @@ public: void DispatchTasksFor(AbstractThread* aThread) override { + // Dispatch all groups that match |aThread|. for (size_t i = 0; i < mTaskGroups.Length(); ++i) { if (mTaskGroups[i]->mThread == aThread) { DispatchTaskGroup(Move(mTaskGroups[i])); - mTaskGroups.RemoveElementAt(i); - return; + mTaskGroups.RemoveElementAt(i--); } } } From b45a420b3e80733b8d2ee241b7acfa59ad8665fd Mon Sep 17 00:00:00 2001 From: JW Wang Date: Thu, 17 Nov 2016 14:25:53 +0800 Subject: [PATCH 24/57] Bug 1318226. P2 - add gtest TestTaskQueue to test the order of regular tasks. r=bholley MozReview-Commit-ID: 9Eg2ALRsV9j --HG-- extra : rebase_source : 7245dc59749598f631bae3be46e46661e11642f6 extra : intermediate-source : 4fd827e0797d7bc1ac19c81a6e0b7915cf154bfe extra : source : a96d4417c994020fa8d3df33a894a89192033fe4 --- xpcom/tests/gtest/TestTaskQueue.cpp | 73 +++++++++++++++++++++++++++++ xpcom/tests/gtest/moz.build | 1 + 2 files changed, 74 insertions(+) create mode 100644 xpcom/tests/gtest/TestTaskQueue.cpp diff --git a/xpcom/tests/gtest/TestTaskQueue.cpp b/xpcom/tests/gtest/TestTaskQueue.cpp new file mode 100644 index 000000000000..1e764fcc1ea2 --- /dev/null +++ b/xpcom/tests/gtest/TestTaskQueue.cpp @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "gtest/gtest.h" +#include "mozilla/SharedThreadPool.h" +#include "mozilla/TaskQueue.h" +#include "VideoUtils.h" + +namespace TestTaskQueue { + +using namespace mozilla; + +TEST(TaskQueue, EventOrder) +{ + RefPtr tq1 = + new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK), true); + RefPtr tq2 = + new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK), true); + RefPtr tq3 = + new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK), true); + + bool errored = false; + int counter = 0; + int sync = 0; + Monitor monitor("TaskQueue::EventOrder::monitor"); + + // We expect task1 happens before task3. + for (int i = 0; i < 10000; ++i) { + tq1->Dispatch(NS_NewRunnableFunction([&] () { + tq2->Dispatch(NS_NewRunnableFunction([] () { // task0 + })); + tq3->Dispatch(NS_NewRunnableFunction([&] () { // task1 + EXPECT_EQ(1, ++counter); + errored = counter != 1; + MonitorAutoLock mon(monitor); + ++sync; + mon.Notify(); + })); + tq2->Dispatch(NS_NewRunnableFunction([&] () { // task2 + tq3->Dispatch(NS_NewRunnableFunction([&] () { // task3 + EXPECT_EQ(0, --counter); + errored = counter != 0; + MonitorAutoLock mon(monitor); + ++sync; + mon.Notify(); + })); + })); + }), AbstractThread::AssertDispatchSuccess, AbstractThread::TailDispatch); + + // Ensure task1 and task3 are done before next loop. + MonitorAutoLock mon(monitor); + while (sync != 2) { + mon.Wait(); + } + sync = 0; + + if (errored) { + break; + } + } + + tq1->BeginShutdown(); + tq1->AwaitShutdownAndIdle(); + tq2->BeginShutdown(); + tq2->AwaitShutdownAndIdle(); + tq3->BeginShutdown(); + tq3->AwaitShutdownAndIdle(); +} + +} // namespace TestTaskQueue diff --git a/xpcom/tests/gtest/moz.build b/xpcom/tests/gtest/moz.build index 2c935375af5d..cbb245c34652 100644 --- a/xpcom/tests/gtest/moz.build +++ b/xpcom/tests/gtest/moz.build @@ -37,6 +37,7 @@ UNIFIED_SOURCES += [ 'TestSynchronization.cpp', 'TestTArray.cpp', 'TestTArray2.cpp', + 'TestTaskQueue.cpp', 'TestTextFormatter.cpp', 'TestThreadPool.cpp', 'TestThreadPoolListener.cpp', From 422ffe963eaae4a6e475c212845dd79a84ae6a7b Mon Sep 17 00:00:00 2001 From: KuoE0 Date: Wed, 8 Mar 2017 15:51:40 +0800 Subject: [PATCH 25/57] Bug 1342867 - Label the runnable of ScrollOnFocusEvent. r=bevistseng,dholbert MozReview-Commit-ID: Dwk7F0gQBiz --HG-- extra : rebase_source : 325f4557be0a7fcc0c5dc7c423ed3d9246bea7fa --- layout/forms/nsTextControlFrame.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index 3ecf3f53c3c6..421ce62770c3 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -675,7 +675,9 @@ void nsTextControlFrame::SetFocus(bool aOn, bool aRepaint) } if (!(lastFocusMethod & nsIFocusManager::FLAG_BYMOUSE)) { RefPtr event = new ScrollOnFocusEvent(this); - nsresult rv = NS_DispatchToCurrentThread(event); + nsresult rv = mContent->OwnerDoc()->Dispatch("ScrollOnFocusEvent", + TaskCategory::Other, + do_AddRef(event)); if (NS_SUCCEEDED(rv)) { mScrollEvent = event; } From 7dad8534a85325679072d5242d02b67730fa7a85 Mon Sep 17 00:00:00 2001 From: Alastor Wu Date: Mon, 27 Mar 2017 10:59:04 +0800 Subject: [PATCH 26/57] Bug 1347648 - part1 : only request Android audio focus for audible media. r=snorp For non-audible media, we shouldn't request audio focus because it might interrupt other app who is playing music or podcast. MozReview-Commit-ID: 25iWJktgKUw --HG-- extra : rebase_source : ca96240967131d2d6cab00f7a39c0ef4e6f2df78 --- widget/android/AndroidBridge.cpp | 46 +++++++++++--------------------- widget/android/AndroidBridge.h | 4 +-- 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index 6d0f461d9b12..ea9422f82da4 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -728,7 +728,8 @@ NS_IMPL_ISUPPORTS(nsAndroidBridge, nsIAndroidBridge, nsIObserver) -nsAndroidBridge::nsAndroidBridge() +nsAndroidBridge::nsAndroidBridge() : + mAudibleWindowsNum(0) { if (jni::IsAvailable()) { RefPtr dispatcher = new widget::EventDispatcher(); @@ -803,45 +804,28 @@ nsAndroidBridge::Observe(nsISupports* aSubject, const char* aTopic, { if (!strcmp(aTopic, "xpcom-shutdown")) { RemoveObservers(); - } else if (!strcmp(aTopic, "media-playback")) { - ALOG_BRIDGE("nsAndroidBridge::Observe, get media-playback event."); - - nsCOMPtr wrapper = do_QueryInterface(aSubject); - if (!wrapper) { - return NS_OK; - } - - uint64_t windowId = 0; - nsresult rv = wrapper->GetData(&windowId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } + } else if (!strcmp(aTopic, "audio-playback")) { + ALOG_BRIDGE("nsAndroidBridge::Observe, get audio-playback event."); nsAutoString activeStr(aData); bool isPlaying = activeStr.EqualsLiteral("active"); - UpdateAudioPlayingWindows(windowId, isPlaying); + UpdateAudioPlayingWindows(isPlaying); } return NS_OK; } void -nsAndroidBridge::UpdateAudioPlayingWindows(uint64_t aWindowId, - bool aPlaying) +nsAndroidBridge::UpdateAudioPlayingWindows(bool aPlaying) { // Request audio focus for the first audio playing window and abandon focus // for the last audio playing window. - if (aPlaying && !mAudioPlayingWindows.Contains(aWindowId)) { - mAudioPlayingWindows.AppendElement(aWindowId); - if (mAudioPlayingWindows.Length() == 1) { - ALOG_BRIDGE("nsAndroidBridge, request audio focus."); - AudioFocusAgent::NotifyStartedPlaying(); - } - } else if (!aPlaying && mAudioPlayingWindows.Contains(aWindowId)) { - mAudioPlayingWindows.RemoveElement(aWindowId); - if (mAudioPlayingWindows.Length() == 0) { - ALOG_BRIDGE("nsAndroidBridge, abandon audio focus."); - AudioFocusAgent::NotifyStoppedPlaying(); - } + MOZ_ASSERT(mAudibleWindowsNum >= 0); + if (aPlaying && mAudibleWindowsNum++ == 0) { + ALOG_BRIDGE("nsAndroidBridge, request audio focus."); + AudioFocusAgent::NotifyStartedPlaying(); + } else if (!aPlaying && --mAudibleWindowsNum == 0) { + ALOG_BRIDGE("nsAndroidBridge, abandon audio focus."); + AudioFocusAgent::NotifyStoppedPlaying(); } } @@ -852,7 +836,7 @@ nsAndroidBridge::AddObservers() if (obs) { obs->AddObserver(this, "xpcom-shutdown", false); if (jni::IsFennec()) { // No AudioFocusAgent in non-Fennec environment. - obs->AddObserver(this, "media-playback", false); + obs->AddObserver(this, "audio-playback", false); } } } @@ -864,7 +848,7 @@ nsAndroidBridge::RemoveObservers() if (obs) { obs->RemoveObserver(this, "xpcom-shutdown"); if (jni::IsFennec()) { // No AudioFocusAgent in non-Fennec environment. - obs->RemoveObserver(this, "media-playback"); + obs->RemoveObserver(this, "audio-playback"); } } } diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index 0da2e2c2c6ea..b4f11d0ab1e1 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -405,9 +405,9 @@ private: void AddObservers(); void RemoveObservers(); - void UpdateAudioPlayingWindows(uint64_t aWindowId, bool aPlaying); + void UpdateAudioPlayingWindows(bool aPlaying); - nsTArray mAudioPlayingWindows; + int32_t mAudibleWindowsNum; nsCOMPtr mEventDispatcher; protected: From 758808ea619f2a0368e5bf49a037cd1e521345b4 Mon Sep 17 00:00:00 2001 From: Alastor Wu Date: Mon, 27 Mar 2017 10:59:07 +0800 Subject: [PATCH 27/57] Bug 1347648 - part2 : paused media element is non-audible. r=jwwang If the media element is paused, it should be non-audible. MozReview-Commit-ID: 2HjV9gNNcnV --HG-- extra : rebase_source : 39b0812788d020d3f9c1a96afa1397b32057de8c --- dom/html/HTMLMediaElement.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index c25dea3af661..8605799be0a1 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -1015,8 +1015,9 @@ private: return AudioChannelService::AudibleState::eMaybeAudible; } - // Media is suspended. - if (mSuspended != nsISuspendedTypes::NONE_SUSPENDED) { + // Suspended or paused media doesn't produce any sound. + if (mSuspended != nsISuspendedTypes::NONE_SUSPENDED || + mOwner->mPaused) { return AudioChannelService::AudibleState::eNotAudible; } From ba792d4c7e5c3e38a3a704c74d6e6285a9a14fda Mon Sep 17 00:00:00 2001 From: Alastor Wu Date: Mon, 27 Mar 2017 10:59:10 +0800 Subject: [PATCH 28/57] Bug 1347648 - part3 : only request audio focus from gecko. r=sebastian Media control would also be displayed for non-audible media, we shouldn't arbitrary request audio focus . Only request audio focus from gecko which know whether the media is audible. MozReview-Commit-ID: Ke9DCYd0Qh2 --HG-- extra : rebase_source : 6ca2f83de877495f7249ee5e7f5cf2165f6f7f6b --- .../base/java/org/mozilla/gecko/media/MediaControlService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/media/MediaControlService.java b/mobile/android/base/java/org/mozilla/gecko/media/MediaControlService.java index d76f8cb53773..1343f3498694 100644 --- a/mobile/android/base/java/org/mozilla/gecko/media/MediaControlService.java +++ b/mobile/android/base/java/org/mozilla/gecko/media/MediaControlService.java @@ -313,8 +313,6 @@ public class MediaControlService extends Service implements Tabs.OnTabsChangedLi super.onPlay(); setState(State.PLAYING); notifyObservers("MediaControl", "resumeMedia"); - // To make sure we always own audio focus during playing. - AudioFocusAgent.notifyStartedPlaying(); } @Override @@ -323,7 +321,6 @@ public class MediaControlService extends Service implements Tabs.OnTabsChangedLi super.onPause(); setState(State.PAUSED); notifyObservers("MediaControl", "mediaControlPaused"); - AudioFocusAgent.notifyStoppedPlaying(); } @Override From 192096681c671f74b11ce2a474ac5a42c13e9f54 Mon Sep 17 00:00:00 2001 From: Alastor Wu Date: Mon, 27 Mar 2017 10:59:44 +0800 Subject: [PATCH 29/57] Bug 1347648 - part4 : notify audible change after finishing set suspend and pause state. r=jwwang Since the audible state would depend on pause and suspend state, we should do the check after finishing play() or pause(). MozReview-Commit-ID: 1yhxuQDw067 --HG-- extra : rebase_source : 888bac3da52f42b75eeb1c3db1337e223d792a11 --- dom/html/HTMLMediaElement.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 8605799be0a1..e02ef59a418b 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -885,9 +885,6 @@ private: MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug, ("HTMLMediaElement::AudioChannelAgentCallback, SetAudioChannelSuspended, " "this = %p, aSuspend = %s\n", this, SuspendTypeToStr(aSuspend))); - - NotifyAudioPlaybackChanged( - AudioChannelService::AudibleChangedReasons::ePauseStateChanged); } void @@ -908,6 +905,9 @@ private: if (rv.Failed()) { NS_WARNING("Not able to resume from AudioChannel."); } + + NotifyAudioPlaybackChanged( + AudioChannelService::AudibleChangedReasons::ePauseStateChanged); } void @@ -925,6 +925,8 @@ private: return; } } + NotifyAudioPlaybackChanged( + AudioChannelService::AudibleChangedReasons::ePauseStateChanged); } void From 841c421ce81bd3d1e3a5ac4f585d7473f5c6912e Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Thu, 9 Mar 2017 19:16:24 +0800 Subject: [PATCH 30/57] Bug 1194751 - Part 1. Remove nsIScreenManager::GetNumberOfScreens. r=jimm It's not used anywhere. Remove it will make removing PScreenManager easier. MozReview-Commit-ID: 5dn8kDhTZVl --HG-- extra : rebase_source : 96b8ddb18deee94ca256bfa118b60ceacfd2d677 --- dom/ipc/ContentChild.cpp | 3 +- dom/ipc/ContentChild.h | 3 +- dom/ipc/ContentParent.cpp | 5 ++- dom/ipc/ContentParent.h | 3 +- dom/ipc/PContent.ipdl | 3 +- dom/ipc/PScreenManager.ipdl | 3 +- dom/ipc/ScreenManagerParent.cpp | 15 +++------ dom/ipc/ScreenManagerParent.h | 6 ++-- widget/PuppetWidget.cpp | 7 ---- widget/android/nsScreenManagerAndroid.cpp | 7 ---- widget/cocoa/nsScreenManagerCocoa.mm | 14 -------- widget/gonk/nsScreenManagerGonk.cpp | 7 ---- widget/gtk/nsScreenManagerGtk.cpp | 20 ----------- widget/nsIScreenManager.idl | 3 -- widget/nsScreenManagerProxy.cpp | 17 ++-------- widget/nsScreenManagerProxy.h | 1 - widget/uikit/nsScreenManager.mm | 8 ----- widget/windows/nsScreenManagerWin.cpp | 41 ----------------------- 18 files changed, 15 insertions(+), 151 deletions(-) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index adaeb4ba875d..74e3e2ed1ffb 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -1749,8 +1749,7 @@ ContentChild::DeallocPParentToChildStreamChild(PParentToChildStreamChild* aActor } PScreenManagerChild* -ContentChild::AllocPScreenManagerChild(uint32_t* aNumberOfScreens, - float* aSystemDefaultScale, +ContentChild::AllocPScreenManagerChild(float* aSystemDefaultScale, bool* aSuccess) { // The ContentParent should never attempt to allocate the diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index f2c00ebfc5b7..cc01fb8d6fd3 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -243,8 +243,7 @@ public: virtual bool DeallocPParentToChildStreamChild(PParentToChildStreamChild*) override; virtual PScreenManagerChild* - AllocPScreenManagerChild(uint32_t* aNumberOfScreens, - float* aSystemDefaultScale, + AllocPScreenManagerChild(float* aSystemDefaultScale, bool* aSuccess) override; virtual bool DeallocPScreenManagerChild(PScreenManagerChild*) override; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 23423b76ad0b..fc486199a061 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -3137,11 +3137,10 @@ ContentParent::DeallocPParentToChildStreamParent(PParentToChildStreamParent* aAc } PScreenManagerParent* -ContentParent::AllocPScreenManagerParent(uint32_t* aNumberOfScreens, - float* aSystemDefaultScale, +ContentParent::AllocPScreenManagerParent(float* aSystemDefaultScale, bool* aSuccess) { - return new ScreenManagerParent(aNumberOfScreens, aSystemDefaultScale, aSuccess); + return new ScreenManagerParent(aSystemDefaultScale, aSuccess); } bool diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 9a91ef5cd6ba..0bcf75029aec 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -447,8 +447,7 @@ public: DeallocPParentToChildStreamParent(PParentToChildStreamParent* aActor) override; virtual PScreenManagerParent* - AllocPScreenManagerParent(uint32_t* aNumberOfScreens, - float* aSystemDefaultScale, + AllocPScreenManagerParent(float* aSystemDefaultScale, bool* aSuccess) override; virtual bool diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 896309746f44..977ff8dbea49 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -712,8 +712,7 @@ parent: async PChildToParentStream(); nested(inside_sync) sync PScreenManager() - returns (uint32_t numberOfScreens, - float systemDefaultScale, + returns (float systemDefaultScale, bool success); async PSpeechSynthesis(); diff --git a/dom/ipc/PScreenManager.ipdl b/dom/ipc/PScreenManager.ipdl index e96d78eef160..ce2c441ba7f3 100644 --- a/dom/ipc/PScreenManager.ipdl +++ b/dom/ipc/PScreenManager.ipdl @@ -32,8 +32,7 @@ nested(upto inside_cpow) sync protocol PScreenManager parent: nested(inside_sync) sync Refresh() - returns (uint32_t numberOfScreens, - float systemDefaultScale, + returns (float systemDefaultScale, bool success); nested(inside_cpow) sync ScreenRefresh(uint32_t aId) diff --git a/dom/ipc/ScreenManagerParent.cpp b/dom/ipc/ScreenManagerParent.cpp index 17c4ec1248d9..b3b19c44c581 100644 --- a/dom/ipc/ScreenManagerParent.cpp +++ b/dom/ipc/ScreenManagerParent.cpp @@ -17,8 +17,7 @@ namespace dom { static const char *sScreenManagerContractID = "@mozilla.org/gfx/screenmanager;1"; -ScreenManagerParent::ScreenManagerParent(uint32_t* aNumberOfScreens, - float* aSystemDefaultScale, +ScreenManagerParent::ScreenManagerParent(float* aSystemDefaultScale, bool* aSuccess) { mScreenMgr = do_GetService(sScreenManagerContractID); @@ -26,22 +25,16 @@ ScreenManagerParent::ScreenManagerParent(uint32_t* aNumberOfScreens, MOZ_CRASH("Couldn't get nsIScreenManager from ScreenManagerParent."); } - Unused << RecvRefresh(aNumberOfScreens, aSystemDefaultScale, aSuccess); + Unused << RecvRefresh(aSystemDefaultScale, aSuccess); } mozilla::ipc::IPCResult -ScreenManagerParent::RecvRefresh(uint32_t* aNumberOfScreens, - float* aSystemDefaultScale, +ScreenManagerParent::RecvRefresh(float* aSystemDefaultScale, bool* aSuccess) { *aSuccess = false; - nsresult rv = mScreenMgr->GetNumberOfScreens(aNumberOfScreens); - if (NS_FAILED(rv)) { - return IPC_OK(); - } - - rv = mScreenMgr->GetSystemDefaultScale(aSystemDefaultScale); + nsresult rv = mScreenMgr->GetSystemDefaultScale(aSystemDefaultScale); if (NS_FAILED(rv)) { return IPC_OK(); } diff --git a/dom/ipc/ScreenManagerParent.h b/dom/ipc/ScreenManagerParent.h index 73c143584b7e..01de6d364cd9 100644 --- a/dom/ipc/ScreenManagerParent.h +++ b/dom/ipc/ScreenManagerParent.h @@ -16,13 +16,11 @@ namespace dom { class ScreenManagerParent : public PScreenManagerParent { public: - ScreenManagerParent(uint32_t* aNumberOfScreens, - float* aSystemDefaultScale, + ScreenManagerParent(float* aSystemDefaultScale, bool* aSuccess); ~ScreenManagerParent() {}; - virtual mozilla::ipc::IPCResult RecvRefresh(uint32_t* aNumberOfScreens, - float* aSystemDefaultScale, + virtual mozilla::ipc::IPCResult RecvRefresh(float* aSystemDefaultScale, bool* aSuccess) override; virtual mozilla::ipc::IPCResult RecvScreenRefresh(const uint32_t& aId, diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index be34e3bcec99..1e732cc63d9b 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -1454,13 +1454,6 @@ PuppetScreenManager::ScreenForNativeWidget(void* aWidget, return GetPrimaryScreen(outScreen); } -NS_IMETHODIMP -PuppetScreenManager::GetNumberOfScreens(uint32_t* aNumberOfScreens) -{ - *aNumberOfScreens = 1; - return NS_OK; -} - NS_IMETHODIMP PuppetScreenManager::GetSystemDefaultScale(float *aDefaultScale) { diff --git a/widget/android/nsScreenManagerAndroid.cpp b/widget/android/nsScreenManagerAndroid.cpp index 2a9739a9d2f0..734517ca6173 100644 --- a/widget/android/nsScreenManagerAndroid.cpp +++ b/widget/android/nsScreenManagerAndroid.cpp @@ -227,13 +227,6 @@ nsScreenManagerAndroid::ScreenForNativeWidget(void *aWidget, nsIScreen **outScre return GetPrimaryScreen(outScreen); } -NS_IMETHODIMP -nsScreenManagerAndroid::GetNumberOfScreens(uint32_t *aNumberOfScreens) -{ - *aNumberOfScreens = mScreens.Length(); - return NS_OK; -} - NS_IMETHODIMP nsScreenManagerAndroid::GetSystemDefaultScale(float *aDefaultScale) { diff --git a/widget/cocoa/nsScreenManagerCocoa.mm b/widget/cocoa/nsScreenManagerCocoa.mm index 9a0cbb9cc5c1..2b1605cc9bb1 100644 --- a/widget/cocoa/nsScreenManagerCocoa.mm +++ b/widget/cocoa/nsScreenManagerCocoa.mm @@ -111,20 +111,6 @@ nsScreenManagerCocoa::GetPrimaryScreen (nsIScreen **outScreen) NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } -NS_IMETHODIMP -nsScreenManagerCocoa::GetNumberOfScreens (uint32_t *aNumberOfScreens) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSArray *ss = [NSScreen screens]; - - *aNumberOfScreens = [ss count]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - NS_IMETHODIMP nsScreenManagerCocoa::GetSystemDefaultScale(float *aDefaultScale) { diff --git a/widget/gonk/nsScreenManagerGonk.cpp b/widget/gonk/nsScreenManagerGonk.cpp index 2a814eb93530..5898736819b5 100644 --- a/widget/gonk/nsScreenManagerGonk.cpp +++ b/widget/gonk/nsScreenManagerGonk.cpp @@ -885,13 +885,6 @@ nsScreenManagerGonk::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen) return NS_OK; } -NS_IMETHODIMP -nsScreenManagerGonk::GetNumberOfScreens(uint32_t *aNumberOfScreens) -{ - *aNumberOfScreens = mScreens.Length(); - return NS_OK; -} - NS_IMETHODIMP nsScreenManagerGonk::GetSystemDefaultScale(float *aDefaultScale) { diff --git a/widget/gtk/nsScreenManagerGtk.cpp b/widget/gtk/nsScreenManagerGtk.cpp index 98166cc924db..0fdfb97d04f9 100644 --- a/widget/gtk/nsScreenManagerGtk.cpp +++ b/widget/gtk/nsScreenManagerGtk.cpp @@ -304,26 +304,6 @@ nsScreenManagerGtk :: GetPrimaryScreen(nsIScreen * *aPrimaryScreen) } // GetPrimaryScreen - -// -// GetNumberOfScreens -// -// Returns how many physical screens are available. -// -NS_IMETHODIMP -nsScreenManagerGtk :: GetNumberOfScreens(uint32_t *aNumberOfScreens) -{ - nsresult rv; - rv = EnsureInit(); - if (NS_FAILED(rv)) { - NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from GetNumberOfScreens"); - return rv; - } - *aNumberOfScreens = mCachedScreenArray.Count(); - return NS_OK; - -} // GetNumberOfScreens - NS_IMETHODIMP nsScreenManagerGtk::GetSystemDefaultScale(float *aDefaultScale) { diff --git a/widget/nsIScreenManager.idl b/widget/nsIScreenManager.idl index 400b5d33b575..58695a50c661 100644 --- a/widget/nsIScreenManager.idl +++ b/widget/nsIScreenManager.idl @@ -29,9 +29,6 @@ interface nsIScreenManager : nsISupports // often. readonly attribute nsIScreen primaryScreen; - // Holds the number of screens that are available - readonly attribute unsigned long numberOfScreens; - // The default DPI scaling factor of the screen environment (number of // screen pixels corresponding to 1 CSS px, at the default zoom level). // diff --git a/widget/nsScreenManagerProxy.cpp b/widget/nsScreenManagerProxy.cpp index 18f400ff5101..e9dd2abe44a3 100644 --- a/widget/nsScreenManagerProxy.cpp +++ b/widget/nsScreenManagerProxy.cpp @@ -23,15 +23,13 @@ using namespace mozilla::widget; NS_IMPL_ISUPPORTS(nsScreenManagerProxy, nsIScreenManager) nsScreenManagerProxy::nsScreenManagerProxy() - : mNumberOfScreens(-1) - , mSystemDefaultScale(1.0) + : mSystemDefaultScale(1.0) , mCacheValid(true) , mCacheWillInvalidate(false) { bool success = false; Unused << ContentChild::GetSingleton()->SendPScreenManagerConstructor( this, - &mNumberOfScreens, &mSystemDefaultScale, &success); @@ -146,17 +144,6 @@ nsScreenManagerProxy::ScreenForNativeWidget(void* aWidget, return NS_OK; } -NS_IMETHODIMP -nsScreenManagerProxy::GetNumberOfScreens(uint32_t* aNumberOfScreens) -{ - if (!EnsureCacheIsValid()) { - return NS_ERROR_FAILURE; - } - - *aNumberOfScreens = mNumberOfScreens; - return NS_OK; -} - NS_IMETHODIMP nsScreenManagerProxy::GetSystemDefaultScale(float *aSystemDefaultScale) { @@ -178,7 +165,7 @@ nsScreenManagerProxy::EnsureCacheIsValid() bool success = false; // Kick off a synchronous IPC call to the parent to get the // most up-to-date information. - Unused << SendRefresh(&mNumberOfScreens, &mSystemDefaultScale, &success); + Unused << SendRefresh(&mSystemDefaultScale, &success); if (!success) { NS_WARNING("Refreshing nsScreenManagerProxy failed in the parent process."); return false; diff --git a/widget/nsScreenManagerProxy.h b/widget/nsScreenManagerProxy.h index bcfa387a4c19..0897921b4d5b 100644 --- a/widget/nsScreenManagerProxy.h +++ b/widget/nsScreenManagerProxy.h @@ -39,7 +39,6 @@ private: void InvalidateCacheOnNextTick(); void InvalidateCache(); - uint32_t mNumberOfScreens; float mSystemDefaultScale; bool mCacheValid; bool mCacheWillInvalidate; diff --git a/widget/uikit/nsScreenManager.mm b/widget/uikit/nsScreenManager.mm index 601c911cd928..68558c1b4c20 100644 --- a/widget/uikit/nsScreenManager.mm +++ b/widget/uikit/nsScreenManager.mm @@ -130,14 +130,6 @@ UIKitScreenManager::ScreenForNativeWidget(void* aWidget, nsIScreen** outScreen) return GetPrimaryScreen(outScreen); } -NS_IMETHODIMP -UIKitScreenManager::GetNumberOfScreens(uint32_t* aNumberOfScreens) -{ - //TODO: support multiple screens - *aNumberOfScreens = 1; - return NS_OK; -} - NS_IMETHODIMP UIKitScreenManager::GetSystemDefaultScale(float* aScale) { diff --git a/widget/windows/nsScreenManagerWin.cpp b/widget/windows/nsScreenManagerWin.cpp index 5440be7dd7a1..87d8b8516f1f 100644 --- a/widget/windows/nsScreenManagerWin.cpp +++ b/widget/windows/nsScreenManagerWin.cpp @@ -123,47 +123,6 @@ nsScreenManagerWin::GetPrimaryScreen(nsIScreen** aPrimaryScreen) } // GetPrimaryScreen - -// -// CountMonitors -// -// Will be called once for every monitor in the system. Just -// increments the parameter, which holds a ptr to a PRUin32 holding the -// count up to this point. -// -BOOL CALLBACK -CountMonitors(HMONITOR, HDC, LPRECT, LPARAM ioParam) -{ - uint32_t* countPtr = reinterpret_cast(ioParam); - ++(*countPtr); - - return TRUE; // continue the enumeration - -} // CountMonitors - - -// -// GetNumberOfScreens -// -// Returns how many physical screens are available. -// -NS_IMETHODIMP -nsScreenManagerWin::GetNumberOfScreens(uint32_t *aNumberOfScreens) -{ - if (mNumberOfScreens) - *aNumberOfScreens = mNumberOfScreens; - else { - uint32_t count = 0; - BOOL result = ::EnumDisplayMonitors(nullptr, nullptr, (MONITORENUMPROC)CountMonitors, (LPARAM)&count); - if (!result) - return NS_ERROR_FAILURE; - *aNumberOfScreens = mNumberOfScreens = count; - } - - return NS_OK; - -} // GetNumberOfScreens - NS_IMETHODIMP nsScreenManagerWin::GetSystemDefaultScale(float *aDefaultScale) { From 31ae8ff78f855cd3b71e18a93d5cb32d241b20b7 Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Thu, 9 Mar 2017 19:16:29 +0800 Subject: [PATCH 31/57] Bug 1194751 - Part 2. Remove unused nsIScreen::LockMinimumBrightness and related methods. r=snorp It's not used anywhere in gecko or addons. Remove it will make removing PScreenManager easier. MozReview-Commit-ID: K3BHnktO7wU --HG-- extra : rebase_source : 6f481759d1fb82d222ea6a92ebfd50dbb6cb63d5 --- .../java/org/mozilla/gecko/GeckoAppShell.java | 10 ----- widget/android/GeneratedJNIWrappers.cpp | 8 ---- widget/android/GeneratedJNIWrappers.h | 20 --------- widget/android/nsScreenManagerAndroid.cpp | 10 ----- widget/android/nsScreenManagerAndroid.h | 3 -- widget/nsBaseScreen.cpp | 44 ------------------- widget/nsBaseScreen.h | 36 --------------- widget/nsIScreen.idl | 27 ------------ 8 files changed, 158 deletions(-) diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java index 4d1c37d9b906..e85d675dfa1b 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java @@ -1060,16 +1060,6 @@ public class GeckoAppShell vibrator().cancel(); } - @WrapForJNI(calledFrom = "gecko") - private static void setKeepScreenOn(final boolean on) { - ThreadUtils.postToUiThread(new Runnable() { - @Override - public void run() { - // TODO - } - }); - } - @WrapForJNI(calledFrom = "gecko") private static boolean isNetworkLinkUp() { ConnectivityManager cm = (ConnectivityManager) diff --git a/widget/android/GeneratedJNIWrappers.cpp b/widget/android/GeneratedJNIWrappers.cpp index 3b858bf73abb..c497f519b3a9 100644 --- a/widget/android/GeneratedJNIWrappers.cpp +++ b/widget/android/GeneratedJNIWrappers.cpp @@ -606,14 +606,6 @@ auto GeckoAppShell::SetFullScreen(bool a0) -> void return mozilla::jni::Method::Call(GeckoAppShell::Context(), nullptr, a0); } -constexpr char GeckoAppShell::SetKeepScreenOn_t::name[]; -constexpr char GeckoAppShell::SetKeepScreenOn_t::signature[]; - -auto GeckoAppShell::SetKeepScreenOn(bool a0) -> void -{ - return mozilla::jni::Method::Call(GeckoAppShell::Context(), nullptr, a0); -} - constexpr char GeckoAppShell::SetScreenDepthOverride_t::name[]; constexpr char GeckoAppShell::SetScreenDepthOverride_t::signature[]; diff --git a/widget/android/GeneratedJNIWrappers.h b/widget/android/GeneratedJNIWrappers.h index d5dcf9893202..1988950426d0 100644 --- a/widget/android/GeneratedJNIWrappers.h +++ b/widget/android/GeneratedJNIWrappers.h @@ -1702,26 +1702,6 @@ public: static auto SetFullScreen(bool) -> void; - struct SetKeepScreenOn_t { - typedef GeckoAppShell Owner; - typedef void ReturnType; - typedef void SetterType; - typedef mozilla::jni::Args< - bool> Args; - static constexpr char name[] = "setKeepScreenOn"; - static constexpr char signature[] = - "(Z)V"; - static const bool isStatic = true; - static const mozilla::jni::ExceptionMode exceptionMode = - mozilla::jni::ExceptionMode::ABORT; - static const mozilla::jni::CallingThread callingThread = - mozilla::jni::CallingThread::GECKO; - static const mozilla::jni::DispatchTarget dispatchTarget = - mozilla::jni::DispatchTarget::CURRENT; - }; - - static auto SetKeepScreenOn(bool) -> void; - struct SetScreenDepthOverride_t { typedef GeckoAppShell Owner; typedef void ReturnType; diff --git a/widget/android/nsScreenManagerAndroid.cpp b/widget/android/nsScreenManagerAndroid.cpp index 734517ca6173..5bb234103682 100644 --- a/widget/android/nsScreenManagerAndroid.cpp +++ b/widget/android/nsScreenManagerAndroid.cpp @@ -117,16 +117,6 @@ nsScreenAndroid::GetColorDepth(int32_t *aColorDepth) return GetPixelDepth(aColorDepth); } - -void -nsScreenAndroid::ApplyMinimumBrightness(uint32_t aBrightness) -{ - if (mDisplayType == DisplayType::DISPLAY_PRIMARY && - mozilla::jni::IsAvailable()) { - java::GeckoAppShell::SetKeepScreenOn(aBrightness == BRIGHTNESS_FULL); - } -} - class nsScreenManagerAndroid::ScreenManagerHelperSupport final : public ScreenManagerHelper::Natives { diff --git a/widget/android/nsScreenManagerAndroid.h b/widget/android/nsScreenManagerAndroid.h index cf8bfb245f60..7ccc91c98d9f 100644 --- a/widget/android/nsScreenManagerAndroid.h +++ b/widget/android/nsScreenManagerAndroid.h @@ -32,9 +32,6 @@ public: void SetDensity(double aDensity) { mDensity = aDensity; } float GetDensity(); -protected: - virtual void ApplyMinimumBrightness(uint32_t aBrightness) override; - private: uint32_t mId; DisplayType mDisplayType; diff --git a/widget/nsBaseScreen.cpp b/widget/nsBaseScreen.cpp index da523853a058..dd10db0dd587 100644 --- a/widget/nsBaseScreen.cpp +++ b/widget/nsBaseScreen.cpp @@ -13,8 +13,6 @@ NS_IMPL_ISUPPORTS(nsBaseScreen, nsIScreen) nsBaseScreen::nsBaseScreen() { - for (uint32_t i = 0; i < nsIScreen::BRIGHTNESS_LEVELS; i++) - mBrightnessLocks[i] = 0; } nsBaseScreen::~nsBaseScreen() { } @@ -33,48 +31,6 @@ nsBaseScreen::GetAvailRectDisplayPix(int32_t *outLeft, int32_t *outTop, return GetAvailRect(outLeft, outTop, outWidth, outHeight); } -NS_IMETHODIMP -nsBaseScreen::LockMinimumBrightness(uint32_t aBrightness) -{ - MOZ_ASSERT(aBrightness < nsIScreen::BRIGHTNESS_LEVELS, - "Invalid brightness level to lock"); - mBrightnessLocks[aBrightness]++; - MOZ_ASSERT(mBrightnessLocks[aBrightness] > 0, - "Overflow after locking brightness level"); - - CheckMinimumBrightness(); - - return NS_OK; -} - -NS_IMETHODIMP -nsBaseScreen::UnlockMinimumBrightness(uint32_t aBrightness) -{ - MOZ_ASSERT(aBrightness < nsIScreen::BRIGHTNESS_LEVELS, - "Invalid brightness level to lock"); - MOZ_ASSERT(mBrightnessLocks[aBrightness] > 0, - "Unlocking a brightness level with no corresponding lock"); - mBrightnessLocks[aBrightness]--; - - CheckMinimumBrightness(); - - return NS_OK; -} - -void -nsBaseScreen::CheckMinimumBrightness() -{ - uint32_t brightness = nsIScreen::BRIGHTNESS_LEVELS; - for (int32_t i = nsIScreen::BRIGHTNESS_LEVELS - 1; i >=0; i--) { - if (mBrightnessLocks[i] > 0) { - brightness = i; - break; - } - } - - ApplyMinimumBrightness(brightness); -} - NS_IMETHODIMP nsBaseScreen::GetContentsScaleFactor(double* aContentsScaleFactor) { diff --git a/widget/nsBaseScreen.h b/widget/nsBaseScreen.h index b07de8a9c50a..de163c2cec85 100644 --- a/widget/nsBaseScreen.h +++ b/widget/nsBaseScreen.h @@ -28,13 +28,6 @@ public: NS_IMETHOD GetAvailRectDisplayPix(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) override; - /** - * Simple management of screen brightness locks. This abstract base class - * allows all widget implementations to share brightness locking code. - */ - NS_IMETHOD LockMinimumBrightness(uint32_t aBrightness) override; - NS_IMETHOD UnlockMinimumBrightness(uint32_t aBrightness) override; - NS_IMETHOD GetRotation(uint32_t* aRotation) override { *aRotation = nsIScreen::ROTATION_0_DEG; return NS_OK; @@ -47,35 +40,6 @@ public: protected: virtual ~nsBaseScreen(); - - /** - * Manually set the current level of brightness locking. This is called after - * we determine, based on the current active locks, what the strongest - * lock is. You should normally not call this function - it will be - * called automatically by this class. - * - * Each widget implementation should implement this in a way that - * makes sense there. This is normally the only function that - * contains widget-specific code. - * - * The default implementation does nothing. - * - * @param aBrightness The current brightness level to set. If this is - * nsIScreen::BRIGHTNESS_LEVELS - * (an impossible value for a brightness level to be), - * then that signifies that there is no current - * minimum brightness level, and the screen can shut off. - */ - virtual void ApplyMinimumBrightness(uint32_t aBrightness) { } - -private: - /** - * Checks what the minimum brightness value is, and calls - * ApplyMinimumBrightness. - */ - void CheckMinimumBrightness(); - - uint32_t mBrightnessLocks[nsIScreen::BRIGHTNESS_LEVELS]; }; #endif // nsBaseScreen_h diff --git a/widget/nsIScreen.idl b/widget/nsIScreen.idl index b1529daf7c17..4e8c50cdd2a4 100644 --- a/widget/nsIScreen.idl +++ b/widget/nsIScreen.idl @@ -20,15 +20,6 @@ enum class DisplayType: int32_t { [scriptable, uuid(826e80c8-d70f-42e2-8aa9-82c05f2a370a)] interface nsIScreen : nsISupports { - /** - * Levels of brightness for the screen, from off to full brightness. - */ - const unsigned long BRIGHTNESS_DIM = 0; - const unsigned long BRIGHTNESS_FULL = 1; - - /* The number of different brightness levels */ - const unsigned long BRIGHTNESS_LEVELS = 2; - /** * Allowable screen rotations, when the underlying widget toolkit * supports rotating the screen. @@ -58,24 +49,6 @@ interface nsIScreen : nsISupports void GetRectDisplayPix(out long left, out long top, out long width, out long height); void GetAvailRectDisplayPix(out long left, out long top, out long width, out long height); - /** - * Locks the minimum brightness of the screen, forcing it to be at - * least as bright as a certain brightness level. Each call to this - * function must eventually be followed by a corresponding call to - * unlockMinimumBrightness, with the same brightness level. - * - * @param brightness A brightness level, one of the above constants. - */ - void lockMinimumBrightness(in unsigned long brightness); - - /** - * Releases a lock on the screen brightness. This must be called - * (eventually) after a corresponding call to lockMinimumBrightness. - * - * @param brightness A brightness level, one of the above constants. - */ - void unlockMinimumBrightness(in unsigned long brightness); - readonly attribute long pixelDepth; readonly attribute long colorDepth; /** From be1eeb353b05f5b0a31396540c279735e0b8287d Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Thu, 9 Mar 2017 19:16:33 +0800 Subject: [PATCH 32/57] Bug 1194751 - Part 3. Remove unused nsIScreen::rotation attribute. r=jimm It's only used by gonk. Remove it will make removing PScreenManager easier. MozReview-Commit-ID: GCHonrz30xK --HG-- extra : rebase_source : 73fbb4263b246d42cc38dd7a30edda9014953a97 --- hal/gonk/GonkHal.cpp | 4 +- widget/PuppetWidget.cpp | 14 -- widget/PuppetWidget.h | 2 - widget/gonk/OrientationObserver.cpp | 332 ---------------------------- widget/gonk/OrientationObserver.h | 71 ------ widget/gonk/ProcessOrientation.cpp | 1 - widget/gonk/moz.build | 2 - widget/gonk/nsAppShell.cpp | 33 +-- widget/gonk/nsScreenManagerGonk.cpp | 40 ---- widget/gonk/nsScreenManagerGonk.h | 2 - widget/nsBaseScreen.h | 6 - widget/nsIScreen.idl | 16 -- 12 files changed, 4 insertions(+), 519 deletions(-) delete mode 100644 widget/gonk/OrientationObserver.cpp delete mode 100644 widget/gonk/OrientationObserver.h diff --git a/hal/gonk/GonkHal.cpp b/hal/gonk/GonkHal.cpp index 6e91db170def..58bbe6eec30a 100644 --- a/hal/gonk/GonkHal.cpp +++ b/hal/gonk/GonkHal.cpp @@ -71,7 +71,6 @@ #include "nsThreadUtils.h" #include "nsIThread.h" #include "nsXULAppAPI.h" -#include "OrientationObserver.h" #include "UeventPoller.h" #include "nsIWritablePropertyBag2.h" #include @@ -1012,13 +1011,12 @@ GetCurrentScreenConfiguration(hal::ScreenConfiguration* aScreenConfiguration) bool LockScreenOrientation(const dom::ScreenOrientationInternal& aOrientation) { - return OrientationObserver::GetInstance()->LockScreenOrientation(aOrientation); + return false; } void UnlockScreenOrientation() { - OrientationObserver::GetInstance()->UnlockScreenOrientation(); } // This thread will wait for the alarm firing by a blocking IO. diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index 1e732cc63d9b..70f4f51f6344 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -1397,20 +1397,6 @@ PuppetScreen::GetColorDepth(int32_t *aColorDepth) return NS_OK; } -NS_IMETHODIMP -PuppetScreen::GetRotation(uint32_t* aRotation) -{ - NS_WARNING("Attempt to get screen rotation through nsIScreen::GetRotation(). Nothing should know or care this in sandboxed contexts. If you want *orientation*, use hal."); - return NS_ERROR_NOT_AVAILABLE; -} - -NS_IMETHODIMP -PuppetScreen::SetRotation(uint32_t aRotation) -{ - NS_WARNING("Attempt to set screen rotation through nsIScreen::GetRotation(). Nothing should know or care this in sandboxed contexts. If you want *orientation*, use hal."); - return NS_ERROR_NOT_AVAILABLE; -} - NS_IMPL_ISUPPORTS(PuppetScreenManager, nsIScreenManager) PuppetScreenManager::PuppetScreenManager() diff --git a/widget/PuppetWidget.h b/widget/PuppetWidget.h index a06f502659d9..b7c2520e0fd6 100644 --- a/widget/PuppetWidget.h +++ b/widget/PuppetWidget.h @@ -448,8 +448,6 @@ public: NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override; NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override; NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override; - NS_IMETHOD GetRotation(uint32_t* aRotation) override; - NS_IMETHOD SetRotation(uint32_t aRotation) override; }; class PuppetScreenManager final : public nsIScreenManager diff --git a/widget/gonk/OrientationObserver.cpp b/widget/gonk/OrientationObserver.cpp deleted file mode 100644 index 9096404cfba4..000000000000 --- a/widget/gonk/OrientationObserver.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set sw=2 ts=8 et ft=cpp : */ -/* Copyright 2012 Mozilla Foundation and Mozilla contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "base/basictypes.h" -#include "mozilla/ClearOnShutdown.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/Hal.h" -#include "nsIScreen.h" -#include "nsIScreenManager.h" -#include "OrientationObserver.h" -#include "mozilla/HalSensor.h" -#include "ProcessOrientation.h" -#include "nsServiceManagerUtils.h" - -using namespace mozilla; -using namespace dom; - -namespace { - -struct OrientationMapping { - uint32_t mScreenRotation; - ScreenOrientationInternal mDomOrientation; -}; - -static OrientationMapping sOrientationMappings[] = { - {nsIScreen::ROTATION_0_DEG, eScreenOrientation_PortraitPrimary}, - {nsIScreen::ROTATION_180_DEG, eScreenOrientation_PortraitSecondary}, - {nsIScreen::ROTATION_90_DEG, eScreenOrientation_LandscapePrimary}, - {nsIScreen::ROTATION_270_DEG, eScreenOrientation_LandscapeSecondary}, -}; - -const static uint32_t sDefaultLandscape = 2; -const static uint32_t sDefaultPortrait = 0; - -static uint32_t sOrientationOffset = 0; - -static already_AddRefed -GetPrimaryScreen() -{ - nsCOMPtr screenMgr = - do_GetService("@mozilla.org/gfx/screenmanager;1"); - NS_ENSURE_TRUE(screenMgr, nullptr); - - nsCOMPtr screen; - screenMgr->GetPrimaryScreen(getter_AddRefs(screen)); - return screen.forget(); -} - -static void -DetectDefaultOrientation() -{ - nsCOMPtr screen = GetPrimaryScreen(); - if (!screen) { - return; - } - - int32_t left, top, width, height; - if (NS_FAILED(screen->GetRect(&left, &top, &width, &height))) { - return; - } - - uint32_t rotation; - if (NS_FAILED(screen->GetRotation(&rotation))) { - return; - } - - if (width < height) { - if (rotation == nsIScreen::ROTATION_0_DEG || - rotation == nsIScreen::ROTATION_180_DEG) { - sOrientationOffset = sDefaultPortrait; - } else { - sOrientationOffset = sDefaultLandscape; - } - } else { - if (rotation == nsIScreen::ROTATION_0_DEG || - rotation == nsIScreen::ROTATION_180_DEG) { - sOrientationOffset = sDefaultLandscape; - } else { - sOrientationOffset = sDefaultPortrait; - } - } -} - -/** - * Converts DOM orientation to nsIScreen rotation. Portrait and Landscape are - * treated as PortraitPrimary and LandscapePrimary, respectively, during - * conversion. - * - * @param aOrientation DOM orientation e.g. - * dom::eScreenOrientation_PortraitPrimary. - * @param aResult output nsIScreen rotation e.g. nsIScreen::ROTATION_0_DEG. - * @return NS_OK on success. NS_ILLEGAL_VALUE on failure. - */ -static nsresult -ConvertToScreenRotation(ScreenOrientationInternal aOrientation, uint32_t *aResult) -{ - for (uint32_t i = 0; i < ArrayLength(sOrientationMappings); i++) { - if (aOrientation & sOrientationMappings[i].mDomOrientation) { - // Shift the mappings in sOrientationMappings so devices with default - // landscape orientation map landscape-primary to 0 degree and so forth. - int adjusted = (i + sOrientationOffset) % - ArrayLength(sOrientationMappings); - *aResult = sOrientationMappings[adjusted].mScreenRotation; - return NS_OK; - } - } - - *aResult = nsIScreen::ROTATION_0_DEG; - return NS_ERROR_ILLEGAL_VALUE; -} - -/** - * Converts nsIScreen rotation to DOM orientation. - * - * @param aRotation nsIScreen rotation e.g. nsIScreen::ROTATION_0_DEG. - * @param aResult output DOM orientation e.g. - * dom::eScreenOrientation_PortraitPrimary. - * @return NS_OK on success. NS_ILLEGAL_VALUE on failure. - */ -nsresult -ConvertToDomOrientation(uint32_t aRotation, ScreenOrientationInternal *aResult) -{ - for (uint32_t i = 0; i < ArrayLength(sOrientationMappings); i++) { - if (aRotation == sOrientationMappings[i].mScreenRotation) { - // Shift the mappings in sOrientationMappings so devices with default - // landscape orientation map 0 degree to landscape-primary and so forth. - int adjusted = (i + sOrientationOffset) % - ArrayLength(sOrientationMappings); - *aResult = sOrientationMappings[adjusted].mDomOrientation; - return NS_OK; - } - } - - *aResult = eScreenOrientation_None; - return NS_ERROR_ILLEGAL_VALUE; -} - -// Note that all operations with sOrientationSensorObserver -// should be on the main thread. -static StaticAutoPtr sOrientationSensorObserver; - -} // namespace - -OrientationObserver* -OrientationObserver::GetInstance() -{ - if (!sOrientationSensorObserver) { - sOrientationSensorObserver = new OrientationObserver(); - ClearOnShutdown(&sOrientationSensorObserver); - } - - return sOrientationSensorObserver; -} - -OrientationObserver::OrientationObserver() - : mAutoOrientationEnabled(false) - , mAllowedOrientations(sDefaultOrientations) - , mOrientation(new mozilla::ProcessOrientation()) -{ - DetectDefaultOrientation(); - - EnableAutoOrientation(); -} - -OrientationObserver::~OrientationObserver() -{ - if (mAutoOrientationEnabled) { - DisableAutoOrientation(); - } -} - -/* static */ void -OrientationObserver::ShutDown() -{ - if (!sOrientationSensorObserver) { - return; - } - - if (sOrientationSensorObserver->mAutoOrientationEnabled) { - sOrientationSensorObserver->DisableAutoOrientation(); - } -} - -void -OrientationObserver::Notify(const hal::SensorData& aSensorData) -{ - // Sensor will call us on the main thread. - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(aSensorData.sensor() == hal::SensorType::SENSOR_ACCELERATION); - - nsCOMPtr screen = GetPrimaryScreen(); - if (!screen) { - return; - } - - uint32_t currRotation; - if(NS_FAILED(screen->GetRotation(&currRotation))) { - return; - } - - int rotation = mOrientation->OnSensorChanged(aSensorData, static_cast(currRotation)); - if (rotation < 0 || uint32_t(rotation) == currRotation) { - return; - } - - ScreenOrientationInternal orientation; - if (NS_FAILED(ConvertToDomOrientation(rotation, &orientation))) { - return; - } - - if ((mAllowedOrientations & orientation) == eScreenOrientation_None) { - // The orientation from sensor is not allowed. - return; - } - - if (NS_FAILED(screen->SetRotation(static_cast(rotation)))) { - // Don't notify dom on rotation failure. - return; - } -} - -/** - * Register the observer. Note that the observer shouldn't be registered. - */ -void -OrientationObserver::EnableAutoOrientation() -{ - MOZ_ASSERT(NS_IsMainThread() && !mAutoOrientationEnabled); - - mOrientation->Reset(); - hal::RegisterSensorObserver(hal::SENSOR_ACCELERATION, this); - mAutoOrientationEnabled = true; -} - -/** - * Unregister the observer. Note that the observer should already be registered. - */ -void -OrientationObserver::DisableAutoOrientation() -{ - MOZ_ASSERT(NS_IsMainThread() && mAutoOrientationEnabled); - - hal::UnregisterSensorObserver(hal::SENSOR_ACCELERATION, this); - mAutoOrientationEnabled = false; -} - -bool -OrientationObserver::LockScreenOrientation(ScreenOrientationInternal aOrientation) -{ - MOZ_ASSERT(aOrientation | (eScreenOrientation_PortraitPrimary | - eScreenOrientation_PortraitSecondary | - eScreenOrientation_LandscapePrimary | - eScreenOrientation_LandscapeSecondary | - eScreenOrientation_Default)); - - if (aOrientation == eScreenOrientation_Default) { - aOrientation = (sOrientationOffset == sDefaultPortrait) ? - eScreenOrientation_PortraitPrimary : - eScreenOrientation_LandscapePrimary; - } - - // If there are multiple orientations allowed, we should enable the - // auto-rotation. - if (aOrientation != eScreenOrientation_LandscapePrimary && - aOrientation != eScreenOrientation_LandscapeSecondary && - aOrientation != eScreenOrientation_PortraitPrimary && - aOrientation != eScreenOrientation_PortraitSecondary) { - if (!mAutoOrientationEnabled) { - EnableAutoOrientation(); - } - } else if (mAutoOrientationEnabled) { - DisableAutoOrientation(); - } - - mAllowedOrientations = aOrientation; - - nsCOMPtr screen = GetPrimaryScreen(); - NS_ENSURE_TRUE(screen, false); - - uint32_t currRotation; - nsresult rv = screen->GetRotation(&currRotation); - NS_ENSURE_SUCCESS(rv, false); - - ScreenOrientationInternal currOrientation = eScreenOrientation_None; - rv = ConvertToDomOrientation(currRotation, &currOrientation); - NS_ENSURE_SUCCESS(rv, false); - - // Don't rotate if the current orientation matches one of the - // requested orientations. - if (currOrientation & aOrientation) { - return true; - } - - // Return false on invalid orientation value. - uint32_t rotation; - rv = ConvertToScreenRotation(aOrientation, &rotation); - NS_ENSURE_SUCCESS(rv, false); - - rv = screen->SetRotation(rotation); - NS_ENSURE_SUCCESS(rv, false); - - // This conversion will disambiguate aOrientation. - ScreenOrientationInternal orientation; - rv = ConvertToDomOrientation(rotation, &orientation); - NS_ENSURE_SUCCESS(rv, false); - - return true; -} - -void -OrientationObserver::UnlockScreenOrientation() -{ - if (!mAutoOrientationEnabled) { - EnableAutoOrientation(); - } - - mAllowedOrientations = sDefaultOrientations; -} diff --git a/widget/gonk/OrientationObserver.h b/widget/gonk/OrientationObserver.h deleted file mode 100644 index c841ea8781cc..000000000000 --- a/widget/gonk/OrientationObserver.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set sw=2 ts=8 et ft=cpp : */ -/* Copyright 2012 Mozilla Foundation and Mozilla contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OrientationObserver_h -#define OrientationObserver_h - -#include "mozilla/Observer.h" -#include "mozilla/dom/ScreenOrientation.h" -#include "mozilla/UniquePtr.h" - -namespace mozilla { -class ProcessOrientation; -namespace hal { -class SensorData; -typedef mozilla::Observer ISensorObserver; -} // namespace hal -} // namespace mozilla - -using mozilla::hal::ISensorObserver; -using mozilla::hal::SensorData; -using mozilla::dom::ScreenOrientationInternal; - -class OrientationObserver : public ISensorObserver { -public: - OrientationObserver(); - ~OrientationObserver(); - - // Call DisableAutoOrientation on the existing OrientatiOnobserver singleton, - // if it exists. If no OrientationObserver exists, do nothing. - static void ShutDown(); - - // Notification from sensor. - void Notify(const SensorData& aSensorData); - - // Methods to enable/disable automatic orientation. - void EnableAutoOrientation(); - void DisableAutoOrientation(); - - // Methods called by methods in hal_impl namespace. - bool LockScreenOrientation(ScreenOrientationInternal aOrientation); - void UnlockScreenOrientation(); - - static OrientationObserver* GetInstance(); - -private: - bool mAutoOrientationEnabled; - uint32_t mAllowedOrientations; - mozilla::UniquePtr mOrientation; - - static const uint32_t sDefaultOrientations = - mozilla::dom::eScreenOrientation_PortraitPrimary | - mozilla::dom::eScreenOrientation_PortraitSecondary | - mozilla::dom::eScreenOrientation_LandscapePrimary | - mozilla::dom::eScreenOrientation_LandscapeSecondary; -}; - -#endif diff --git a/widget/gonk/ProcessOrientation.cpp b/widget/gonk/ProcessOrientation.cpp index bbdcface8ac9..8cef5262dd95 100644 --- a/widget/gonk/ProcessOrientation.cpp +++ b/widget/gonk/ProcessOrientation.cpp @@ -21,7 +21,6 @@ #include "mozilla/Unused.h" #include "nsIScreen.h" #include "nsIScreenManager.h" -#include "OrientationObserver.h" #include "ProcessOrientation.h" #include "mozilla/HalSensor.h" #include "math.h" diff --git a/widget/gonk/moz.build b/widget/gonk/moz.build index d539dd9a08e9..5ae518e17ab3 100644 --- a/widget/gonk/moz.build +++ b/widget/gonk/moz.build @@ -17,7 +17,6 @@ EXPORTS += [ 'GeckoTouchDispatcher.h', 'GonkPermission.h', - 'OrientationObserver.h', ] DIRS += ['libdisplay', 'nativewindow'] @@ -66,7 +65,6 @@ SOURCES += [ 'nsScreenManagerGonk.cpp', 'nsWidgetFactory.cpp', 'nsWindow.cpp', - 'OrientationObserver.cpp', 'ProcessOrientation.cpp', 'WidgetTraceEvent.cpp' ] diff --git a/widget/gonk/nsAppShell.cpp b/widget/gonk/nsAppShell.cpp index 775e80976648..7be27722f594 100644 --- a/widget/gonk/nsAppShell.cpp +++ b/widget/gonk/nsAppShell.cpp @@ -55,7 +55,6 @@ #include "nsScreenManagerGonk.h" #include "nsThreadUtils.h" #include "nsWindow.h" -#include "OrientationObserver.h" #include "GonkMemoryPressureMonitoring.h" #include "android/log.h" @@ -557,39 +556,17 @@ private: void GeckoInputReaderPolicy::setDisplayInfo() { - static_assert(static_cast(nsIScreen::ROTATION_0_DEG) == - static_cast(DISPLAY_ORIENTATION_0), - "Orientation enums not matched!"); - static_assert(static_cast(nsIScreen::ROTATION_90_DEG) == - static_cast(DISPLAY_ORIENTATION_90), - "Orientation enums not matched!"); - static_assert(static_cast(nsIScreen::ROTATION_180_DEG) == - static_cast(DISPLAY_ORIENTATION_180), - "Orientation enums not matched!"); - static_assert(static_cast(nsIScreen::ROTATION_270_DEG) == - static_cast(DISPLAY_ORIENTATION_270), - "Orientation enums not matched!"); - RefPtr screen = nsScreenManagerGonk::GetPrimaryScreen(); - uint32_t rotation = nsIScreen::ROTATION_0_DEG; - DebugOnly rv = screen->GetRotation(&rotation); - MOZ_ASSERT(NS_SUCCEEDED(rv)); LayoutDeviceIntRect screenBounds = screen->GetNaturalBounds(); DisplayViewport viewport; viewport.displayId = 0; - viewport.orientation = rotation; + viewport.orientation = DISPLAY_ORIENTATION_0; viewport.physicalRight = viewport.deviceWidth = screenBounds.width; viewport.physicalBottom = viewport.deviceHeight = screenBounds.height; - if (viewport.orientation == DISPLAY_ORIENTATION_90 || - viewport.orientation == DISPLAY_ORIENTATION_270) { - viewport.logicalRight = screenBounds.height; - viewport.logicalBottom = screenBounds.width; - } else { - viewport.logicalRight = screenBounds.width; - viewport.logicalBottom = screenBounds.height; - } + viewport.logicalRight = screenBounds.width; + viewport.logicalBottom = screenBounds.height; mConfig.setDisplayInfo(false, viewport); } @@ -966,7 +943,6 @@ nsAppShell::Observe(nsISupports* aSubject, NS_IMETHODIMP nsAppShell::Exit() { - OrientationObserver::ShutDown(); nsCOMPtr obsServ = GetObserverService(); if (obsServ) { obsServ->RemoveObserver(this, "browser-ui-startup-complete"); @@ -1070,9 +1046,6 @@ nsAppShell::NotifyNativeEvent() nsAppShell::NotifyScreenInitialized() { gAppShell->InitInputDevices(); - - // Getting the instance of OrientationObserver to initialize it. - OrientationObserver::GetInstance(); } /* static */ void diff --git a/widget/gonk/nsScreenManagerGonk.cpp b/widget/gonk/nsScreenManagerGonk.cpp index 5898736819b5..ce11cbdc8e13 100644 --- a/widget/gonk/nsScreenManagerGonk.cpp +++ b/widget/gonk/nsScreenManagerGonk.cpp @@ -238,13 +238,6 @@ nsScreenGonk::GetColorDepth(int32_t *aColorDepth) return NS_OK; } -NS_IMETHODIMP -nsScreenGonk::GetRotation(uint32_t* aRotation) -{ - *aRotation = mScreenRotation; - return NS_OK; -} - float nsScreenGonk::GetDpi() { @@ -263,39 +256,6 @@ nsScreenGonk::GetNativeWindow() return mNativeWindow.get(); } -NS_IMETHODIMP -nsScreenGonk::SetRotation(uint32_t aRotation) -{ - if (!(aRotation <= ROTATION_270_DEG)) { - return NS_ERROR_ILLEGAL_VALUE; - } - - if (mScreenRotation == aRotation) { - return NS_OK; - } - - mScreenRotation = aRotation; - uint32_t rotation = EffectiveScreenRotation(); - if (rotation == nsIScreen::ROTATION_90_DEG || - rotation == nsIScreen::ROTATION_270_DEG) { - mVirtualBounds = LayoutDeviceIntRect(0, 0, - mNaturalBounds.height, - mNaturalBounds.width); - } else { - mVirtualBounds = mNaturalBounds; - } - - nsAppShell::NotifyScreenRotation(); - - for (unsigned int i = 0; i < mTopWindows.Length(); i++) { - mTopWindows[i]->Resize(mVirtualBounds.width, - mVirtualBounds.height, - true); - } - - return NS_OK; -} - LayoutDeviceIntRect nsScreenGonk::GetNaturalBounds() { diff --git a/widget/gonk/nsScreenManagerGonk.h b/widget/gonk/nsScreenManagerGonk.h index 33ef5edb8927..968620c349af 100644 --- a/widget/gonk/nsScreenManagerGonk.h +++ b/widget/gonk/nsScreenManagerGonk.h @@ -75,8 +75,6 @@ public: NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth); NS_IMETHOD GetColorDepth(int32_t* aColorDepth); - NS_IMETHOD GetRotation(uint32_t* aRotation); - NS_IMETHOD SetRotation(uint32_t aRotation); uint32_t GetId(); NotifyDisplayChangedEvent GetEventVisibility(); diff --git a/widget/nsBaseScreen.h b/widget/nsBaseScreen.h index de163c2cec85..cbd860df8e5b 100644 --- a/widget/nsBaseScreen.h +++ b/widget/nsBaseScreen.h @@ -28,12 +28,6 @@ public: NS_IMETHOD GetAvailRectDisplayPix(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) override; - NS_IMETHOD GetRotation(uint32_t* aRotation) override { - *aRotation = nsIScreen::ROTATION_0_DEG; - return NS_OK; - } - NS_IMETHOD SetRotation(uint32_t aRotation) override { return NS_ERROR_NOT_AVAILABLE; } - NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) override; NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) override; diff --git a/widget/nsIScreen.idl b/widget/nsIScreen.idl index 4e8c50cdd2a4..7f5bb17a846b 100644 --- a/widget/nsIScreen.idl +++ b/widget/nsIScreen.idl @@ -20,17 +20,6 @@ enum class DisplayType: int32_t { [scriptable, uuid(826e80c8-d70f-42e2-8aa9-82c05f2a370a)] interface nsIScreen : nsISupports { - /** - * Allowable screen rotations, when the underlying widget toolkit - * supports rotating the screen. - * - * ROTATION_0_DEG is the default, unrotated configuration. - */ - const unsigned long ROTATION_0_DEG = 0; - const unsigned long ROTATION_90_DEG = 1; - const unsigned long ROTATION_180_DEG = 2; - const unsigned long ROTATION_270_DEG = 3; - /** * A unique identifier for this device, useful for requerying * for it via nsIScreenManager. @@ -51,11 +40,6 @@ interface nsIScreen : nsISupports readonly attribute long pixelDepth; readonly attribute long colorDepth; - /** - * Get/set the screen rotation, on platforms that support changing - * screen rotation. - */ - attribute unsigned long rotation; /** * The number of device pixels per desktop pixel for this screen (for From 53ad814f857cf0fbf9f2389e7f608b1b92fea5e6 Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Tue, 14 Mar 2017 18:44:54 +0800 Subject: [PATCH 33/57] Bug 1194751 - Part 4. Add ScreenManager and Screen classes. r=jimm,karlt,mconley ScreenManager takes the common parts of ScreenManagerWin, ScreenManagerGtk and ScreenManagerCocoa. It caches all screen information in the new Screen class. The cache are updated when the OS notifies there is a monitor config change; all changes will be pushed to content processes via PContent (patch part 6.) Screen is a pure data object. All platform dependent logic will be in widget specific helper classes. Each process will have a singleton ScreenManager object. Widget specific helper object is held alive by the ScreenManager when necessary, for example to receive updates from the OS. The change to to VsyncDispatcher.cpp is due to unified-build bustage. ScreenManager::ScreenForNativeWidget is not implemented because it will be removed in patch part 6. MozReview-Commit-ID: 5ezytAXSqHp *** fixup MozReview-Commit-ID: DQtq3UVZytA --HG-- extra : rebase_source : c1a5aac713de783586e93109fe3e197ffdc1a3ca --- widget/Screen.cpp | 133 +++++++++++++++++++++++++++++ widget/Screen.h | 47 ++++++++++ widget/ScreenManager.cpp | 171 +++++++++++++++++++++++++++++++++++++ widget/ScreenManager.h | 52 +++++++++++ widget/VsyncDispatcher.cpp | 2 + widget/moz.build | 4 + 6 files changed, 409 insertions(+) create mode 100644 widget/Screen.cpp create mode 100644 widget/Screen.h create mode 100644 widget/ScreenManager.cpp create mode 100644 widget/ScreenManager.h diff --git a/widget/Screen.cpp b/widget/Screen.cpp new file mode 100644 index 000000000000..10c2eb84ed92 --- /dev/null +++ b/widget/Screen.cpp @@ -0,0 +1,133 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */ +/* vim: set sw=4 ts=8 et tw=80 : */ +/* 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/. */ + +#include "Screen.h" + +namespace mozilla { +namespace widget { + +NS_IMPL_ISUPPORTS(Screen, nsIScreen) + +static uint32_t sScreenId = 0; + +Screen::Screen(LayoutDeviceIntRect aRect, LayoutDeviceIntRect aAvailRect, + uint32_t aPixelDepth, uint32_t aColorDepth, + DesktopToLayoutDeviceScale aContentsScale, + CSSToLayoutDeviceScale aDefaultCssScale) + : mRect(aRect) + , mAvailRect(aAvailRect) + , mRectDisplayPix(RoundedToInt(aRect / aContentsScale)) + , mAvailRectDisplayPix(RoundedToInt(aAvailRect / aContentsScale)) + , mPixelDepth(aPixelDepth) + , mColorDepth(aColorDepth) + , mContentsScale(aContentsScale) + , mDefaultCssScale(aDefaultCssScale) + , mId(++sScreenId) +{ +} + +Screen::Screen(const Screen& aOther) + : mRect(aOther.mRect) + , mAvailRect(aOther.mAvailRect) + , mRectDisplayPix(aOther.mRectDisplayPix) + , mAvailRectDisplayPix(aOther.mAvailRectDisplayPix) + , mPixelDepth(aOther.mPixelDepth) + , mColorDepth(aOther.mColorDepth) + , mContentsScale(aOther.mContentsScale) + , mDefaultCssScale(aOther.mDefaultCssScale) + , mId(aOther.mId) +{ +} + +NS_IMETHODIMP +Screen::GetId(uint32_t* aOutId) +{ + *aOutId = mId; + return NS_OK; +} + +NS_IMETHODIMP +Screen::GetRect(int32_t* aOutLeft, + int32_t* aOutTop, + int32_t* aOutWidth, + int32_t* aOutHeight) +{ + *aOutLeft = mRect.x; + *aOutTop = mRect.y; + *aOutWidth = mRect.width; + *aOutHeight = mRect.height; + return NS_OK; +} + +NS_IMETHODIMP +Screen::GetRectDisplayPix(int32_t* aOutLeft, + int32_t* aOutTop, + int32_t* aOutWidth, + int32_t* aOutHeight) +{ + *aOutLeft = mRectDisplayPix.x; + *aOutTop = mRectDisplayPix.y; + *aOutWidth = mRectDisplayPix.width; + *aOutHeight = mRectDisplayPix.height; + return NS_OK; +} + +NS_IMETHODIMP +Screen::GetAvailRect(int32_t* aOutLeft, + int32_t* aOutTop, + int32_t* aOutWidth, + int32_t* aOutHeight) +{ + *aOutLeft = mAvailRect.x; + *aOutTop = mAvailRect.y; + *aOutWidth = mAvailRect.width; + *aOutHeight = mAvailRect.height; + return NS_OK; +} + +NS_IMETHODIMP +Screen::GetAvailRectDisplayPix(int32_t* aOutLeft, + int32_t* aOutTop, + int32_t* aOutWidth, + int32_t* aOutHeight) +{ + *aOutLeft = mAvailRectDisplayPix.x; + *aOutTop = mAvailRectDisplayPix.y; + *aOutWidth = mAvailRectDisplayPix.width; + *aOutHeight = mAvailRectDisplayPix.height; + return NS_OK; +} + +NS_IMETHODIMP +Screen::GetPixelDepth(int32_t* aPixelDepth) +{ + *aPixelDepth = mPixelDepth; + return NS_OK; +} + +NS_IMETHODIMP +Screen::GetColorDepth(int32_t* aColorDepth) +{ + *aColorDepth = mColorDepth; + return NS_OK; +} + +NS_IMETHODIMP +Screen::GetContentsScaleFactor(double *aOutScale) +{ + *aOutScale = mContentsScale.scale; + return NS_OK; +} + +NS_IMETHODIMP +Screen::GetDefaultCSSScaleFactor(double *aOutScale) +{ + *aOutScale = mDefaultCssScale.scale; + return NS_OK; +} + +} // namespace widget +} // namespace mozilla diff --git a/widget/Screen.h b/widget/Screen.h new file mode 100644 index 000000000000..267bf153a68a --- /dev/null +++ b/widget/Screen.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_widget_Screen_h +#define mozilla_widget_Screen_h + +#include "nsIScreen.h" + +#include "Units.h" + +namespace mozilla { +namespace widget { + +class Screen final : public nsIScreen +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSISCREEN + + Screen(LayoutDeviceIntRect aRect, LayoutDeviceIntRect aAvailRect, + uint32_t aPixelDepth, uint32_t aColorDepth, + DesktopToLayoutDeviceScale aContentsScale, + CSSToLayoutDeviceScale aDefaultCssScale); + Screen(const Screen& aOther); + +private: + virtual ~Screen() {} + + LayoutDeviceIntRect mRect; + LayoutDeviceIntRect mAvailRect; + DesktopIntRect mRectDisplayPix; + DesktopIntRect mAvailRectDisplayPix; + uint32_t mPixelDepth; + uint32_t mColorDepth; + DesktopToLayoutDeviceScale mContentsScale; + CSSToLayoutDeviceScale mDefaultCssScale; + uint32_t mId; +}; + +} // namespace widget +} // namespace mozilla + +#endif + diff --git a/widget/ScreenManager.cpp b/widget/ScreenManager.cpp new file mode 100644 index 000000000000..1a2e078d30bd --- /dev/null +++ b/widget/ScreenManager.cpp @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "ScreenManager.h" + +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/Logging.h" +#include "mozilla/StaticPtr.h" + +static LazyLogModule sScreenLog("WidgetScreen"); + +NS_IMPL_ISUPPORTS(ScreenManager, nsIScreenManager) + +namespace mozilla { +namespace widget { + +ScreenManager::ScreenManager() +{ +} + +ScreenManager::~ScreenManager() +{ +} + +static StaticRefPtr sSingleton; + +ScreenManager& +ScreenManager::GetSingleton() +{ + if (!sSingleton) { + sSingleton = new ScreenManager(); + ClearOnShutdown(&sSingleton); + } + return *sSingleton; +} + +already_AddRefed +ScreenManager::GetAddRefedSingleton() +{ + RefPtr sm = &GetSingleton(); + return sm.forget(); +} + +void +ScreenManager::SetHelper(UniquePtr aHelper) +{ + mHelper = Move(aHelper); +} + +void +ScreenManager::Refresh(nsTArray>&& aScreens) +{ + mScreenList = Move(aScreens); +} + +NS_IMETHODIMP +ScreenManager::ScreenForId(uint32_t aId, nsIScreen** aOutScreen) +{ + *aOutScreen = nullptr; + + nsresult rv; + for (auto& screen : mScreenList) { + uint32_t id; + rv = screen->GetId(&id); + if (NS_SUCCEEDED(rv) && id == aId) { + RefPtr ret = screen; + ret.forget(aOutScreen); + return NS_OK; + } + } + + return NS_ERROR_FAILURE; +} + +// Returns the screen that contains the rectangle. If the rect overlaps +// multiple screens, it picks the screen with the greatest area of intersection. +// +// The coordinates are in desktop pixels. +// +NS_IMETHODIMP +ScreenManager::ScreenForRect(int32_t aX, int32_t aY, + int32_t aWidth, int32_t aHeight, + nsIScreen** aOutScreen) +{ + if (mScreenList.IsEmpty()) { + MOZ_LOG(sScreenLog, LogLevel::Warning, + ("No screen available. This can happen in xpcshell.")); + RefPtr ret = new Screen(LayoutDeviceIntRect(), LayoutDeviceIntRect(), + 0, 0, + DesktopToLayoutDeviceScale(), + CSSToLayoutDeviceScale()); + ret.forget(aOutScreen); + return NS_OK; + } + + // Optimize for the common case. If the number of screens is only + // one then just return the primary screen. + if (mScreenList.Length() == 1) { + return GetPrimaryScreen(aOutScreen); + } + + // which screen should we return? + Screen* which = mScreenList[0].get(); + + // walk the list of screens and find the one that has the most + // surface area. + uint32_t area = 0; + DesktopIntRect windowRect(aX, aY, aWidth, aHeight); + for (auto& screen : mScreenList) { + int32_t x, y, width, height; + x = y = width = height = 0; + screen->GetRectDisplayPix(&x, &y, &width, &height); + // calculate the surface area + DesktopIntRect screenRect(x, y, width, height); + screenRect.IntersectRect(screenRect, windowRect); + uint32_t tempArea = screenRect.width * screenRect.height; + if (tempArea >= area) { + which = screen.get(); + area = tempArea; + } + } + + RefPtr ret = which; + ret.forget(aOutScreen); + return NS_OK; +} + +// The screen with the menubar/taskbar. This shouldn't be needed very +// often. +// +NS_IMETHODIMP +ScreenManager::GetPrimaryScreen(nsIScreen** aPrimaryScreen) +{ + if (mScreenList.IsEmpty()) { + MOZ_LOG(sScreenLog, LogLevel::Warning, + ("No screen available. This can happen in xpcshell.")); + RefPtr ret = new Screen(LayoutDeviceIntRect(), LayoutDeviceIntRect(), + 0, 0, + DesktopToLayoutDeviceScale(), + CSSToLayoutDeviceScale()); + ret.forget(aPrimaryScreen); + return NS_OK; + } + + RefPtr ret = mScreenList[0]; + ret.forget(aPrimaryScreen); + return NS_OK; +} + +NS_IMETHODIMP +ScreenManager::GetSystemDefaultScale(float* aDefaultScale) +{ + if (mHelper) { + *aDefaultScale = mHelper->GetSystemDefaultScale(); + return NS_OK; + } + *aDefaultScale = 1; + return NS_OK; +} + +NS_IMETHODIMP +ScreenManager::ScreenForNativeWidget(void* aWidget, nsIScreen** aOutScreen) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +} // namespace widget +} // namespace mozilla diff --git a/widget/ScreenManager.h b/widget/ScreenManager.h new file mode 100644 index 000000000000..4b76577ebf97 --- /dev/null +++ b/widget/ScreenManager.h @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_widget_ScreenManager_h +#define mozilla_widget_ScreenManager_h + +#include "nsIScreenManager.h" + +#include "mozilla/RefPtr.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/widget/Screen.h" +#include "nsTArray.h" + +namespace mozilla { +namespace widget { + +class ScreenManager final : public nsIScreenManager +{ +public: + class Helper + { + public: + virtual float GetSystemDefaultScale() = 0; + virtual ~Helper() {}; + }; + +public: + NS_DECL_ISUPPORTS + NS_DECL_NSISCREENMANAGER + + static ScreenManager& GetSingleton(); + static already_AddRefed GetAddRefedSingleton(); + + void SetHelper(UniquePtr aHelper); + void Refresh(nsTArray>&& aScreens); + +private: + ScreenManager(); + virtual ~ScreenManager(); + + AutoTArray, 4> mScreenList; + UniquePtr mHelper; +}; + + +} // namespace widget +} // namespace mozilla + +#endif // mozilla_widget_ScreenManager_h diff --git a/widget/VsyncDispatcher.cpp b/widget/VsyncDispatcher.cpp index 336d48e84b0a..eb3e716f547c 100644 --- a/widget/VsyncDispatcher.cpp +++ b/widget/VsyncDispatcher.cpp @@ -16,6 +16,8 @@ #include "ProfilerMarkers.h" #endif +using namespace mozilla::layers; + namespace mozilla { CompositorVsyncDispatcher::CompositorVsyncDispatcher() diff --git a/widget/moz.build b/widget/moz.build index 5e92e72bbb15..271c23c00e0b 100644 --- a/widget/moz.build +++ b/widget/moz.build @@ -130,6 +130,8 @@ EXPORTS.mozilla.widget += [ 'InProcessCompositorWidget.h', 'nsAutoRollup.h', 'PuppetBidiKeyboard.h', + 'Screen.h', + 'ScreenManager.h', 'WidgetMessageUtils.h', 'WindowSurface.h' ] @@ -162,6 +164,8 @@ UNIFIED_SOURCES += [ 'nsXPLookAndFeel.cpp', 'PuppetBidiKeyboard.cpp', 'PuppetWidget.cpp', + 'Screen.cpp', + 'ScreenManager.cpp', 'ScreenProxy.cpp', 'SharedWidgetUtils.cpp', 'TextEventDispatcher.cpp', From 824adc93544c6829dcb1f278d7e8191f176ec1dc Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Thu, 9 Mar 2017 19:29:44 +0800 Subject: [PATCH 34/57] Bug 1194751 - Part 5. Implement ScreenHelperGTK and delete old nsScreenManagerGtk/nsScreenGtk. r=karlt ScreenHelperGTK is the platform dependent part of the original nsScreenManagerGtk and nsScreenGtk. It registers monitors-changed event listener from gtk and pushes updates to ScreenManager. See patch part 4. for how ScreenManager works. MozReview-Commit-ID: KBo7ZLFTjM3 --HG-- rename : widget/gtk/nsScreenManagerGtk.cpp => widget/gtk/ScreenHelperGTK.cpp rename : widget/gtk/nsScreenManagerGtk.h => widget/gtk/ScreenHelperGTK.h extra : rebase_source : 5607e31b62c928934cc45df7b2212428fbfd79c1 --- gfx/thebes/gfxXlibSurface.h | 14 +- widget/gtk/ScreenHelperGTK.cpp | 338 +++++++++++++++++++++++++++++ widget/gtk/ScreenHelperGTK.h | 49 +++++ widget/gtk/moz.build | 3 +- widget/gtk/nsAppShell.cpp | 9 + widget/gtk/nsDragService.cpp | 8 +- widget/gtk/nsLookAndFeel.cpp | 4 +- widget/gtk/nsNativeThemeGTK.cpp | 12 +- widget/gtk/nsScreenGtk.cpp | 207 ------------------ widget/gtk/nsScreenGtk.h | 57 ----- widget/gtk/nsScreenManagerGtk.cpp | 346 ------------------------------ widget/gtk/nsScreenManagerGtk.h | 52 ----- widget/gtk/nsWidgetFactory.cpp | 6 +- widget/gtk/nsWindow.cpp | 4 +- 14 files changed, 421 insertions(+), 688 deletions(-) create mode 100644 widget/gtk/ScreenHelperGTK.cpp create mode 100644 widget/gtk/ScreenHelperGTK.h delete mode 100644 widget/gtk/nsScreenGtk.cpp delete mode 100644 widget/gtk/nsScreenGtk.h delete mode 100644 widget/gtk/nsScreenManagerGtk.cpp delete mode 100644 widget/gtk/nsScreenManagerGtk.h diff --git a/gfx/thebes/gfxXlibSurface.h b/gfx/thebes/gfxXlibSurface.h index 499bc5e966b7..c7ae9b3eac0d 100644 --- a/gfx/thebes/gfxXlibSurface.h +++ b/gfx/thebes/gfxXlibSurface.h @@ -36,7 +36,7 @@ public: // construct a wrapper around the specified drawable with dpy/format, // and known width/height. - gfxXlibSurface(Screen *screen, Drawable drawable, XRenderPictFormat *format, + gfxXlibSurface(::Screen *screen, Drawable drawable, XRenderPictFormat *format, const mozilla::gfx::IntSize& size); explicit gfxXlibSurface(cairo_surface_t *csurf); @@ -46,13 +46,13 @@ public: // the pixmap should be in video or system memory. It must be on // |screen| (if specified). static already_AddRefed - Create(Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size, + Create(::Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size, Drawable relatedDrawable = X11None); static cairo_surface_t * - CreateCairoSurface(Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size, + CreateCairoSurface(::Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size, Drawable relatedDrawable = X11None); static already_AddRefed - Create(Screen* screen, XRenderPictFormat *format, const mozilla::gfx::IntSize& size, + Create(::Screen* screen, XRenderPictFormat *format, const mozilla::gfx::IntSize& size, Drawable relatedDrawable = X11None); virtual ~gfxXlibSurface(); @@ -65,12 +65,12 @@ public: virtual const mozilla::gfx::IntSize GetSize() const override; Display* XDisplay() { return mDisplay; } - Screen* XScreen(); + ::Screen* XScreen(); Drawable XDrawable() { return mDrawable; } XRenderPictFormat* XRenderFormat(); - static int DepthOfVisual(const Screen* screen, const Visual* visual); - static Visual* FindVisual(Screen* screen, gfxImageFormat format); + static int DepthOfVisual(const ::Screen* screen, const Visual* visual); + static Visual* FindVisual(::Screen* screen, gfxImageFormat format); static XRenderPictFormat *FindRenderFormat(Display *dpy, gfxImageFormat format); static bool GetColormapAndVisual(cairo_surface_t* aXlibSurface, Colormap* colormap, Visual **visual); diff --git a/widget/gtk/ScreenHelperGTK.cpp b/widget/gtk/ScreenHelperGTK.cpp new file mode 100644 index 000000000000..6eafb6c51bff --- /dev/null +++ b/widget/gtk/ScreenHelperGTK.cpp @@ -0,0 +1,338 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "ScreenHelperGTK.h" + +#ifdef MOZ_X11 +#include +#include +// from Xinerama.h +typedef struct { + int screen_number; + short x_org; + short y_org; + short width; + short height; +} XineramaScreenInfo; +// prototypes from Xinerama.h +typedef Bool (*_XnrmIsActive_fn)(Display *dpy); +typedef XineramaScreenInfo* (*_XnrmQueryScreens_fn)(Display *dpy, int *number); +#endif +#include +#include + +#include "gfxPlatformGtk.h" +#include "mozilla/Logging.h" +#include "nsGtkUtils.h" +#include "nsTArray.h" + +#define SCREEN_MANAGER_LIBRARY_LOAD_FAILED ((PRLibrary*)1) + +namespace mozilla { +namespace widget { + +static LazyLogModule sScreenLog("WidgetScreen"); + +static void +monitors_changed(GdkScreen* aScreen, gpointer aClosure) +{ + MOZ_LOG(sScreenLog, LogLevel::Debug, ("Received monitors-changed event")); + ScreenHelperGTK* self = static_cast(aClosure); + self->RefreshScreens(); +} + +static GdkFilterReturn +root_window_event_filter(GdkXEvent* aGdkXEvent, GdkEvent* aGdkEvent, + gpointer aClosure) +{ +#ifdef MOZ_X11 + ScreenHelperGTK* self = static_cast(aClosure); + XEvent *xevent = static_cast(aGdkXEvent); + + switch (xevent->type) { + case PropertyNotify: + { + XPropertyEvent *propertyEvent = &xevent->xproperty; + if (propertyEvent->atom == self->NetWorkareaAtom()) { + MOZ_LOG(sScreenLog, LogLevel::Debug, ("Work area size changed")); + self->RefreshScreens(); + } + } + break; + default: + break; + } +#endif + + return GDK_FILTER_CONTINUE; +} + +ScreenHelperGTK::ScreenHelperGTK() + : mXineramalib(nullptr) + , mRootWindow(nullptr) + , mNetWorkareaAtom(0) +{ + MOZ_LOG(sScreenLog, LogLevel::Debug, ("ScreenHelperGTK created")); + mRootWindow = gdk_get_default_root_window(); + if (!mRootWindow) { + // Sometimes we don't initial X (e.g., xpcshell) + MOZ_LOG(sScreenLog, LogLevel::Debug, ("mRootWindow is nullptr, running headless")); + return; + } + + g_object_ref(mRootWindow); + + // GDK_PROPERTY_CHANGE_MASK ==> PropertyChangeMask, for PropertyNotify + gdk_window_set_events(mRootWindow, + GdkEventMask(gdk_window_get_events(mRootWindow) | + GDK_PROPERTY_CHANGE_MASK)); + + g_signal_connect(gdk_screen_get_default(), "monitors-changed", + G_CALLBACK(monitors_changed), this); +#ifdef MOZ_X11 + gdk_window_add_filter(mRootWindow, root_window_event_filter, this); + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) { + mNetWorkareaAtom = + XInternAtom(GDK_WINDOW_XDISPLAY(mRootWindow), "_NET_WORKAREA", False); + } +#endif + RefreshScreens(); +} + +ScreenHelperGTK::~ScreenHelperGTK() +{ + g_signal_handlers_disconnect_by_func(gdk_screen_get_default(), + FuncToGpointer(monitors_changed), + this); + + if (mRootWindow) { + gdk_window_remove_filter(mRootWindow, root_window_event_filter, this); + g_object_unref(mRootWindow); + mRootWindow = nullptr; + } + + /* XineramaIsActive() registers a callback function close_display() + * in X, which is to be called in XCloseDisplay(). This is the case + * if Xinerama is active, even if only with one screen. + * + * We can't unload libXinerama.so.1 here because this will make + * the address of close_display() registered in X to be invalid and + * it will crash when XCloseDisplay() is called later. */ +} + +gint +ScreenHelperGTK::GetGTKMonitorScaleFactor() +{ +#if (MOZ_WIDGET_GTK >= 3) + // Since GDK 3.10 + static auto sGdkScreenGetMonitorScaleFactorPtr = (gint (*)(GdkScreen*, gint)) + dlsym(RTLD_DEFAULT, "gdk_screen_get_monitor_scale_factor"); + if (sGdkScreenGetMonitorScaleFactorPtr) { + // FIXME: In the future, we'll want to fix this for GTK on Wayland which + // supports a variable scale factor per display. + GdkScreen *screen = gdk_screen_get_default(); + return sGdkScreenGetMonitorScaleFactorPtr(screen, 0); + } +#endif + return 1; +} + +static float +GetDefaultCssScale() +{ + double scale = nsIWidget::DefaultScaleOverride(); + if (scale <= 0.0) { + scale = ScreenHelperGTK::GetGTKMonitorScaleFactor() * gfxPlatformGtk::GetDPIScale(); + } + return scale; +} + +float +ScreenHelperGTK::GetSystemDefaultScale() +{ + return GetDefaultCssScale(); +} + +static uint32_t +GetGTKPixelDepth() +{ + GdkVisual * visual = gdk_screen_get_system_visual(gdk_screen_get_default()); + return gdk_visual_get_depth(visual); +} + +static already_AddRefed +MakeScreen(GdkWindow* aRootWindow) +{ + RefPtr screen; + + gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor(); + gint width = gdk_screen_width() * scale; + gint height = gdk_screen_height() * scale; + uint32_t pixelDepth = GetGTKPixelDepth(); + DesktopToLayoutDeviceScale contentsScale(1.0); + CSSToLayoutDeviceScale defaultCssScale(GetDefaultCssScale()); + + LayoutDeviceIntRect rect; + LayoutDeviceIntRect availRect; + rect = availRect = LayoutDeviceIntRect(0, 0, width, height); + +#ifdef MOZ_X11 + // We need to account for the taskbar, etc in the available rect. + // See http://freedesktop.org/Standards/wm-spec/index.html#id2767771 + + // XXX do we care about _NET_WM_STRUT_PARTIAL? That will + // add much more complexity to the code here (our screen + // could have a non-rectangular shape), but should + // lead to greater accuracy. + + long *workareas; + GdkAtom type_returned; + int format_returned; + int length_returned; + + GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL); + + gdk_error_trap_push(); + + // gdk_property_get uses (length + 3) / 4, hence G_MAXLONG - 3 here. + if (!gdk_property_get(aRootWindow, + gdk_atom_intern ("_NET_WORKAREA", FALSE), + cardinal_atom, + 0, G_MAXLONG - 3, FALSE, + &type_returned, + &format_returned, + &length_returned, + (guchar **) &workareas)) { + // This window manager doesn't support the freedesktop standard. + // Nothing we can do about it, so assume full screen size. + MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f]", + rect.x, rect.y, rect.width, rect.height, + pixelDepth, defaultCssScale.scale)); + screen = new Screen(rect, availRect, + pixelDepth, pixelDepth, + contentsScale, defaultCssScale); + return screen.forget(); + } + + // Flush the X queue to catch errors now. + gdk_flush(); + + if (!gdk_error_trap_pop() && + type_returned == cardinal_atom && + length_returned && (length_returned % 4) == 0 && + format_returned == 32) { + int num_items = length_returned / sizeof(long); + + for (int i = 0; i < num_items; i += 4) { + LayoutDeviceIntRect workarea(workareas[i], workareas[i + 1], + workareas[i + 2], workareas[i + 3]); + if (!rect.Contains(workarea)) { + // Note that we hit this when processing screen size changes, + // since we'll get the configure event before the toolbars have + // been moved. We'll end up cleaning this up when we get the + // change notification to the _NET_WORKAREA property. However, + // we still want to listen to both, so we'll handle changes + // properly for desktop environments that don't set the + // _NET_WORKAREA property. + NS_WARNING("Invalid bounds"); + continue; + } + + availRect.IntersectRect(availRect, workarea); + } + } + g_free(workareas); +#endif + MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f]", + rect.x, rect.y, rect.width, rect.height, + pixelDepth, defaultCssScale.scale)); + screen = new Screen(rect, availRect, + pixelDepth, pixelDepth, + contentsScale, defaultCssScale); + return screen.forget(); +} + +static already_AddRefed +MakeScreen(const XineramaScreenInfo& aScreenInfo) +{ + LayoutDeviceIntRect xineRect(aScreenInfo.x_org, aScreenInfo.y_org, + aScreenInfo.width, aScreenInfo.height); + uint32_t pixelDepth = GetGTKPixelDepth(); + DesktopToLayoutDeviceScale contentsScale(1.0); + CSSToLayoutDeviceScale defaultCssScale(GetDefaultCssScale()); + + MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f]", + xineRect.x, xineRect.y, + xineRect.width, xineRect.height, + pixelDepth, defaultCssScale.scale)); + RefPtr screen = new Screen(xineRect, xineRect, + pixelDepth, pixelDepth, + contentsScale, defaultCssScale); + return screen.forget(); +} + +void +ScreenHelperGTK::RefreshScreens() +{ + MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refreshing screens")); + AutoTArray, 4> screenList; +#ifdef MOZ_X11 + XineramaScreenInfo *screenInfo = nullptr; + int numScreens; + + bool useXinerama = GDK_IS_X11_DISPLAY(gdk_display_get_default()); + + if (useXinerama && !mXineramalib) { + mXineramalib = PR_LoadLibrary("libXinerama.so.1"); + if (!mXineramalib) { + mXineramalib = SCREEN_MANAGER_LIBRARY_LOAD_FAILED; + } + } + if (mXineramalib && mXineramalib != SCREEN_MANAGER_LIBRARY_LOAD_FAILED) { + _XnrmIsActive_fn _XnrmIsActive = (_XnrmIsActive_fn) + PR_FindFunctionSymbol(mXineramalib, "XineramaIsActive"); + + _XnrmQueryScreens_fn _XnrmQueryScreens = (_XnrmQueryScreens_fn) + PR_FindFunctionSymbol(mXineramalib, "XineramaQueryScreens"); + + // get the number of screens via xinerama + Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + if (_XnrmIsActive && _XnrmQueryScreens && _XnrmIsActive(display)) { + screenInfo = _XnrmQueryScreens(display, &numScreens); + } + } + + // screenInfo == nullptr if either Xinerama couldn't be loaded or + // isn't running on the current display + if (!screenInfo || numScreens == 1) { + numScreens = 1; +#endif + MOZ_LOG(sScreenLog, LogLevel::Debug, ("Find only one screen available")); + // Get primary screen + screenList.AppendElement(MakeScreen(mRootWindow)); +#ifdef MOZ_X11 + } + // If Xinerama is enabled and there's more than one screen, fill + // in the info for all of the screens. If that's not the case + // then defaults to the screen width + height + else { + MOZ_LOG(sScreenLog, LogLevel::Debug, + ("Xinerama enabled for %d screens", numScreens)); + for (int i = 0; i < numScreens; ++i) { + screenList.AppendElement(MakeScreen(screenInfo[i])); + } + } + + if (screenInfo) { + XFree(screenInfo); + } +#endif + ScreenManager& screenManager = ScreenManager::GetSingleton(); + screenManager.Refresh(Move(screenList)); +} + +} // namespace widget +} // namespace mozilla diff --git a/widget/gtk/ScreenHelperGTK.h b/widget/gtk/ScreenHelperGTK.h new file mode 100644 index 000000000000..bd100214dc5f --- /dev/null +++ b/widget/gtk/ScreenHelperGTK.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_widget_gtk_ScreenHelperGTK_h +#define mozilla_widget_gtk_ScreenHelperGTK_h + +#include "mozilla/widget/ScreenManager.h" + +#include "prlink.h" +#include "gdk/gdk.h" +#ifdef MOZ_X11 +#include +#endif + +namespace mozilla { +namespace widget { + +class ScreenHelperGTK final : public ScreenManager::Helper +{ +public: + ScreenHelperGTK(); + ~ScreenHelperGTK() override; + + float GetSystemDefaultScale() override; + + static gint GetGTKMonitorScaleFactor(); + +#ifdef MOZ_X11 + Atom NetWorkareaAtom() { return mNetWorkareaAtom; } +#endif + + // For internal use from signal callback functions + void RefreshScreens(); + +private: + PRLibrary* mXineramalib; + GdkWindow* mRootWindow; +#ifdef MOZ_X11 + Atom mNetWorkareaAtom; +#endif +}; + +} // namespace widget +} // namespace mozilla + +#endif // mozilla_widget_gtk_ScreenHelperGTK_h diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build index fcac41c320ea..7d7ce0262813 100644 --- a/widget/gtk/moz.build +++ b/widget/gtk/moz.build @@ -29,11 +29,10 @@ UNIFIED_SOURCES += [ 'nsImageToPixbuf.cpp', 'nsLookAndFeel.cpp', 'nsNativeThemeGTK.cpp', - 'nsScreenGtk.cpp', - 'nsScreenManagerGtk.cpp', 'nsSound.cpp', 'nsToolkit.cpp', 'nsWidgetFactory.cpp', + 'ScreenHelperGTK.cpp', 'WakeLockListener.cpp', 'WidgetTraceEvent.cpp', 'WidgetUtilsGtk.cpp', diff --git a/widget/gtk/nsAppShell.cpp b/widget/gtk/nsAppShell.cpp index 75ad9999e14f..324f356756a0 100644 --- a/widget/gtk/nsAppShell.cpp +++ b/widget/gtk/nsAppShell.cpp @@ -21,8 +21,12 @@ #ifdef MOZ_ENABLE_DBUS #include "WakeLockListener.h" #endif +#include "ScreenHelperGTK.h" +#include "mozilla/widget/ScreenManager.h" using mozilla::Unused; +using mozilla::widget::ScreenHelperGTK; +using mozilla::widget::ScreenManager; #define NOTIFY_TOKEN 0xFA @@ -164,6 +168,11 @@ nsAppShell::Init() g_main_context_set_poll_func(nullptr, &PollWrapper); } + if (XRE_IsParentProcess()) { + ScreenManager& screenManager = ScreenManager::GetSingleton(); + screenManager.SetHelper(mozilla::MakeUnique()); + } + #if MOZ_WIDGET_GTK == 3 if (!sReal_gtk_window_check_resize && gtk_check_version(3,8,0) != nullptr) { // GTK 3.0 to GTK 3.6. diff --git a/widget/gtk/nsDragService.cpp b/widget/gtk/nsDragService.cpp index 7c6b6c8569b1..c6d34bca71e1 100644 --- a/widget/gtk/nsDragService.cpp +++ b/widget/gtk/nsDragService.cpp @@ -40,7 +40,7 @@ #include "nsGtkKeyUtils.h" #include "mozilla/gfx/2D.h" #include "gfxPlatform.h" -#include "nsScreenGtk.h" +#include "ScreenHelperGTK.h" #include "nsArrayUtils.h" using namespace mozilla; @@ -239,7 +239,7 @@ OnSourceGrabEventAfter(GtkWidget *widget, GdkEvent *event, gpointer user_data) // Update the cursor position. The last of these recorded gets used for // the eDragEnd event. nsDragService *dragService = static_cast(user_data); - gint scale = nsScreenGtk::GetGtkMonitorScaleFactor(); + gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor(); auto p = LayoutDeviceIntPoint::Round(event->motion.x_root * scale, event->motion.y_root * scale); dragService->SetDragEndPoint(p); @@ -505,7 +505,7 @@ nsDragService::SetAlphaPixmap(SourceSurface *aSurface, (void (*)(cairo_surface_t*,double,double)) dlsym(RTLD_DEFAULT, "cairo_surface_set_device_scale"); if (sCairoSurfaceSetDeviceScalePtr) { - gint scale = nsScreenGtk::GetGtkMonitorScaleFactor(); + gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor(); sCairoSurfaceSetDeviceScalePtr(surf, scale, scale); } @@ -1417,7 +1417,7 @@ nsDragService::SourceEndDragSession(GdkDragContext *aContext, gint x, y; GdkDisplay* display = gdk_display_get_default(); if (display) { - gint scale = nsScreenGtk::GetGtkMonitorScaleFactor(); + gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor(); gdk_display_get_pointer(display, nullptr, &x, &y, nullptr); SetDragEndPoint(LayoutDeviceIntPoint(x * scale, y * scale)); } diff --git a/widget/gtk/nsLookAndFeel.cpp b/widget/gtk/nsLookAndFeel.cpp index 8868f3363233..46f94a61dd2e 100644 --- a/widget/gtk/nsLookAndFeel.cpp +++ b/widget/gtk/nsLookAndFeel.cpp @@ -18,7 +18,7 @@ #include #include "gfxPlatformGtk.h" -#include "nsScreenGtk.h" +#include "ScreenHelperGTK.h" #include "gtkdrawing.h" #include "nsStyleConsts.h" @@ -925,7 +925,7 @@ GetSystemFontInfo(GtkWidget *aWidget, // Scale fonts up on HiDPI displays. // This would be done automatically with cairo, but we manually manage // the display scale for platform consistency. - size *= nsScreenGtk::GetGtkMonitorScaleFactor(); + size *= ScreenHelperGTK::GetGTKMonitorScaleFactor(); // |size| is now pixels diff --git a/widget/gtk/nsNativeThemeGTK.cpp b/widget/gtk/nsNativeThemeGTK.cpp index 8b06eb5be9a3..7361bd8e0f80 100644 --- a/widget/gtk/nsNativeThemeGTK.cpp +++ b/widget/gtk/nsNativeThemeGTK.cpp @@ -6,7 +6,7 @@ #include "nsNativeThemeGTK.h" #include "nsThemeConstants.h" #include "gtkdrawing.h" -#include "nsScreenGtk.h" +#include "ScreenHelperGTK.h" #include "gfx2DGlue.h" #include "nsIObserverService.h" @@ -1090,7 +1090,7 @@ nsNativeThemeGTK::GetExtraSizeForWidget(nsIFrame* aFrame, uint8_t aWidgetType, default: return false; } - gint scale = nsScreenGtk::GetGtkMonitorScaleFactor(); + gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor(); aExtra->top *= scale; aExtra->right *= scale; aExtra->bottom *= scale; @@ -1118,7 +1118,7 @@ nsNativeThemeGTK::DrawWidgetBackground(nsRenderingContext* aContext, gfxRect rect = presContext->AppUnitsToGfxUnits(aRect); gfxRect dirtyRect = presContext->AppUnitsToGfxUnits(aDirtyRect); - gint scaleFactor = nsScreenGtk::GetGtkMonitorScaleFactor(); + gint scaleFactor = ScreenHelperGTK::GetGTKMonitorScaleFactor(); // Align to device pixels where sensible // to provide crisper and faster drawing. @@ -1344,7 +1344,7 @@ nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame, } } - gint scale = nsScreenGtk::GetGtkMonitorScaleFactor(); + gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor(); aResult->top *= scale; aResult->right *= scale; aResult->bottom *= scale; @@ -1404,7 +1404,7 @@ nsNativeThemeGTK::GetWidgetPadding(nsDeviceContext* aContext, aResult->left += horizontal_padding; aResult->right += horizontal_padding; - gint scale = nsScreenGtk::GetGtkMonitorScaleFactor(); + gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor(); aResult->top *= scale; aResult->right *= scale; aResult->bottom *= scale; @@ -1681,7 +1681,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, break; } - *aResult = *aResult * nsScreenGtk::GetGtkMonitorScaleFactor(); + *aResult = *aResult * ScreenHelperGTK::GetGTKMonitorScaleFactor(); return NS_OK; } diff --git a/widget/gtk/nsScreenGtk.cpp b/widget/gtk/nsScreenGtk.cpp deleted file mode 100644 index 61e6605b76b9..000000000000 --- a/widget/gtk/nsScreenGtk.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "nsScreenGtk.h" - -#include "nsIWidget.h" - -#include -#ifdef MOZ_X11 -#include -#include -#endif -#include -#include -#include "gfxPlatformGtk.h" - -static uint32_t sScreenId = 0; - - -nsScreenGtk :: nsScreenGtk ( ) - : mScreenNum(0), - mRect(0, 0, 0, 0), - mAvailRect(0, 0, 0, 0), - mId(++sScreenId) -{ -} - - -nsScreenGtk :: ~nsScreenGtk() -{ -} - - -NS_IMETHODIMP -nsScreenGtk :: GetId(uint32_t *aId) -{ - *aId = mId; - return NS_OK; -} // GetId - - -NS_IMETHODIMP -nsScreenGtk :: GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) -{ - *outLeft = mRect.x; - *outTop = mRect.y; - *outWidth = mRect.width; - *outHeight = mRect.height; - - return NS_OK; - -} // GetRect - - -NS_IMETHODIMP -nsScreenGtk :: GetAvailRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) -{ - *outLeft = mAvailRect.x; - *outTop = mAvailRect.y; - *outWidth = mAvailRect.width; - *outHeight = mAvailRect.height; - - return NS_OK; - -} // GetAvailRect - -gint -nsScreenGtk :: GetGtkMonitorScaleFactor() -{ -#if (MOZ_WIDGET_GTK >= 3) - // Since GDK 3.10 - static auto sGdkScreenGetMonitorScaleFactorPtr = (gint (*)(GdkScreen*, gint)) - dlsym(RTLD_DEFAULT, "gdk_screen_get_monitor_scale_factor"); - if (sGdkScreenGetMonitorScaleFactorPtr) { - // FIXME: In the future, we'll want to fix this for GTK on Wayland which - // supports a variable scale factor per display. - GdkScreen *screen = gdk_screen_get_default(); - return sGdkScreenGetMonitorScaleFactorPtr(screen, 0); - } -#endif - return 1; -} - -double -nsScreenGtk :: GetDPIScale() -{ - double dpiScale = nsIWidget::DefaultScaleOverride(); - if (dpiScale <= 0.0) { - dpiScale = GetGtkMonitorScaleFactor() * gfxPlatformGtk::GetDPIScale(); - } - return dpiScale; -} - -NS_IMETHODIMP -nsScreenGtk :: GetPixelDepth(int32_t *aPixelDepth) -{ - GdkVisual * visual = gdk_screen_get_system_visual(gdk_screen_get_default()); - *aPixelDepth = gdk_visual_get_depth(visual); - - return NS_OK; - -} // GetPixelDepth - -NS_IMETHODIMP -nsScreenGtk :: GetColorDepth(int32_t *aColorDepth) -{ - return GetPixelDepth ( aColorDepth ); - -} // GetColorDepth - -NS_IMETHODIMP -nsScreenGtk::GetDefaultCSSScaleFactor(double* aScaleFactor) -{ - *aScaleFactor = GetDPIScale(); - return NS_OK; -} - -void -nsScreenGtk :: Init (GdkWindow *aRootWindow) -{ - gint scale = nsScreenGtk::GetGtkMonitorScaleFactor(); - gint width = gdk_screen_width()*scale; - gint height = gdk_screen_height()*scale; - - // We listen for configure events on the root window to pick up - // changes to this rect. We could listen for "size_changed" signals - // on the default screen to do this, except that doesn't work with - // versions of GDK predating the GdkScreen object. See bug 256646. - mAvailRect = mRect = nsIntRect(0, 0, width, height); - -#ifdef MOZ_X11 - // We need to account for the taskbar, etc in the available rect. - // See http://freedesktop.org/Standards/wm-spec/index.html#id2767771 - - // XXX do we care about _NET_WM_STRUT_PARTIAL? That will - // add much more complexity to the code here (our screen - // could have a non-rectangular shape), but should - // lead to greater accuracy. - - long *workareas; - GdkAtom type_returned; - int format_returned; - int length_returned; - - GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL); - - gdk_error_trap_push(); - - // gdk_property_get uses (length + 3) / 4, hence G_MAXLONG - 3 here. - if (!gdk_property_get(aRootWindow, - gdk_atom_intern ("_NET_WORKAREA", FALSE), - cardinal_atom, - 0, G_MAXLONG - 3, FALSE, - &type_returned, - &format_returned, - &length_returned, - (guchar **) &workareas)) { - // This window manager doesn't support the freedesktop standard. - // Nothing we can do about it, so assume full screen size. - return; - } - - // Flush the X queue to catch errors now. - gdk_flush(); - - if (!gdk_error_trap_pop() && - type_returned == cardinal_atom && - length_returned && (length_returned % 4) == 0 && - format_returned == 32) { - int num_items = length_returned / sizeof(long); - - for (int i = 0; i < num_items; i += 4) { - nsIntRect workarea(workareas[i], workareas[i + 1], - workareas[i + 2], workareas[i + 3]); - if (!mRect.Contains(workarea)) { - // Note that we hit this when processing screen size changes, - // since we'll get the configure event before the toolbars have - // been moved. We'll end up cleaning this up when we get the - // change notification to the _NET_WORKAREA property. However, - // we still want to listen to both, so we'll handle changes - // properly for desktop environments that don't set the - // _NET_WORKAREA property. - NS_WARNING("Invalid bounds"); - continue; - } - - mAvailRect.IntersectRect(mAvailRect, workarea); - } - } - g_free (workareas); -#endif -} - -#ifdef MOZ_X11 -void -nsScreenGtk :: Init (XineramaScreenInfo *aScreenInfo) -{ - nsIntRect xineRect(aScreenInfo->x_org, aScreenInfo->y_org, - aScreenInfo->width, aScreenInfo->height); - - mScreenNum = aScreenInfo->screen_number; - - mAvailRect = mRect = xineRect; -} -#endif diff --git a/widget/gtk/nsScreenGtk.h b/widget/gtk/nsScreenGtk.h deleted file mode 100644 index d58ea4b1e20e..000000000000 --- a/widget/gtk/nsScreenGtk.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef nsScreenGtk_h___ -#define nsScreenGtk_h___ - -#include "nsBaseScreen.h" -#include "nsRect.h" -#include "gdk/gdk.h" -#ifdef MOZ_X11 -#include - -// from Xinerama.h -typedef struct { - int screen_number; - short x_org; - short y_org; - short width; - short height; -} XineramaScreenInfo; -#endif /* MOZ_X11 */ - -//------------------------------------------------------------------------ - -class nsScreenGtk : public nsBaseScreen -{ -public: - nsScreenGtk(); - ~nsScreenGtk(); - - NS_IMETHOD GetId(uint32_t* aId) override; - NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, - int32_t* aWidth, int32_t* aHeight) override; - NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, - int32_t* aWidth, int32_t* aHeight) override; - NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override; - NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override; - NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) override; - - void Init(GdkWindow *aRootWindow); -#ifdef MOZ_X11 - void Init(XineramaScreenInfo *aScreenInfo); -#endif /* MOZ_X11 */ - - static gint GetGtkMonitorScaleFactor(); - static double GetDPIScale(); - -private: - uint32_t mScreenNum; - nsIntRect mRect; - nsIntRect mAvailRect; - uint32_t mId; -}; - -#endif // nsScreenGtk_h___ diff --git a/widget/gtk/nsScreenManagerGtk.cpp b/widget/gtk/nsScreenManagerGtk.cpp deleted file mode 100644 index 0fdfb97d04f9..000000000000 --- a/widget/gtk/nsScreenManagerGtk.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "nsScreenManagerGtk.h" - -#include "mozilla/RefPtr.h" -#include "nsScreenGtk.h" -#include "nsIComponentManager.h" -#include "nsRect.h" -#include "nsGtkUtils.h" - -#define SCREEN_MANAGER_LIBRARY_LOAD_FAILED ((PRLibrary*)1) - -#ifdef MOZ_X11 -#include -// prototypes from Xinerama.h -typedef Bool (*_XnrmIsActive_fn)(Display *dpy); -typedef XineramaScreenInfo* (*_XnrmQueryScreens_fn)(Display *dpy, int *number); -#endif - -#include - -void -monitors_changed(GdkScreen* aScreen, gpointer aClosure) -{ - nsScreenManagerGtk *manager = static_cast(aClosure); - manager->Init(); -} - -static GdkFilterReturn -root_window_event_filter(GdkXEvent *aGdkXEvent, GdkEvent *aGdkEvent, - gpointer aClosure) -{ - nsScreenManagerGtk *manager = static_cast(aClosure); -#ifdef MOZ_X11 - XEvent *xevent = static_cast(aGdkXEvent); - - // See comments in nsScreenGtk::Init below. - switch (xevent->type) { - case PropertyNotify: - { - XPropertyEvent *propertyEvent = &xevent->xproperty; - if (propertyEvent->atom == manager->NetWorkareaAtom()) { - manager->Init(); - } - } - break; - default: - break; - } -#endif - - return GDK_FILTER_CONTINUE; -} - -nsScreenManagerGtk :: nsScreenManagerGtk ( ) - : mXineramalib(nullptr) - , mRootWindow(nullptr) - , mNetWorkareaAtom(0) -{ - // nothing else to do. I guess we could cache a bunch of information - // here, but we want to ask the device at runtime in case anything - // has changed. -} - - -nsScreenManagerGtk :: ~nsScreenManagerGtk() -{ - g_signal_handlers_disconnect_by_func(gdk_screen_get_default(), - FuncToGpointer(monitors_changed), - this); - - if (mRootWindow) { - gdk_window_remove_filter(mRootWindow, root_window_event_filter, this); - g_object_unref(mRootWindow); - mRootWindow = nullptr; - } - - /* XineramaIsActive() registers a callback function close_display() - * in X, which is to be called in XCloseDisplay(). This is the case - * if Xinerama is active, even if only with one screen. - * - * We can't unload libXinerama.so.1 here because this will make - * the address of close_display() registered in X to be invalid and - * it will crash when XCloseDisplay() is called later. */ -} - - -// addref, release, QI -NS_IMPL_ISUPPORTS(nsScreenManagerGtk, nsIScreenManager) - - -// this function will make sure that everything has been initialized. -nsresult -nsScreenManagerGtk :: EnsureInit() -{ - if (mCachedScreenArray.Count() > 0) - return NS_OK; - - mRootWindow = gdk_get_default_root_window(); - if (!mRootWindow) { - // Sometimes we don't initial X (e.g., xpcshell) - return NS_OK; - } - - g_object_ref(mRootWindow); - - // GDK_PROPERTY_CHANGE_MASK ==> PropertyChangeMask, for PropertyNotify - gdk_window_set_events(mRootWindow, - GdkEventMask(gdk_window_get_events(mRootWindow) | - GDK_PROPERTY_CHANGE_MASK)); - - g_signal_connect(gdk_screen_get_default(), "monitors-changed", - G_CALLBACK(monitors_changed), this); -#ifdef MOZ_X11 - gdk_window_add_filter(mRootWindow, root_window_event_filter, this); - if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) - mNetWorkareaAtom = - XInternAtom(GDK_WINDOW_XDISPLAY(mRootWindow), "_NET_WORKAREA", False); -#endif - - return Init(); -} - -nsresult -nsScreenManagerGtk :: Init() -{ -#ifdef MOZ_X11 - XineramaScreenInfo *screenInfo = nullptr; - int numScreens; - - bool useXinerama = GDK_IS_X11_DISPLAY(gdk_display_get_default()); - - if (useXinerama && !mXineramalib) { - mXineramalib = PR_LoadLibrary("libXinerama.so.1"); - if (!mXineramalib) { - mXineramalib = SCREEN_MANAGER_LIBRARY_LOAD_FAILED; - } - } - if (mXineramalib && mXineramalib != SCREEN_MANAGER_LIBRARY_LOAD_FAILED) { - _XnrmIsActive_fn _XnrmIsActive = (_XnrmIsActive_fn) - PR_FindFunctionSymbol(mXineramalib, "XineramaIsActive"); - - _XnrmQueryScreens_fn _XnrmQueryScreens = (_XnrmQueryScreens_fn) - PR_FindFunctionSymbol(mXineramalib, "XineramaQueryScreens"); - - // get the number of screens via xinerama - Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); - if (_XnrmIsActive && _XnrmQueryScreens && _XnrmIsActive(display)) { - screenInfo = _XnrmQueryScreens(display, &numScreens); - } - } - - // screenInfo == nullptr if either Xinerama couldn't be loaded or - // isn't running on the current display - if (!screenInfo || numScreens == 1) { - numScreens = 1; -#endif - RefPtr screen; - - if (mCachedScreenArray.Count() > 0) { - screen = static_cast(mCachedScreenArray[0]); - } else { - screen = new nsScreenGtk(); - if (!screen || !mCachedScreenArray.AppendObject(screen)) { - return NS_ERROR_OUT_OF_MEMORY; - } - } - - screen->Init(mRootWindow); -#ifdef MOZ_X11 - } - // If Xinerama is enabled and there's more than one screen, fill - // in the info for all of the screens. If that's not the case - // then nsScreenGTK() defaults to the screen width + height - else { -#ifdef DEBUG - printf("Xinerama superpowers activated for %d screens!\n", numScreens); -#endif - for (int i = 0; i < numScreens; ++i) { - RefPtr screen; - if (mCachedScreenArray.Count() > i) { - screen = static_cast(mCachedScreenArray[i]); - } else { - screen = new nsScreenGtk(); - if (!screen || !mCachedScreenArray.AppendObject(screen)) { - return NS_ERROR_OUT_OF_MEMORY; - } - } - - // initialize this screen object - screen->Init(&screenInfo[i]); - } - } - // Remove any screens that are no longer present. - while (mCachedScreenArray.Count() > numScreens) { - mCachedScreenArray.RemoveObjectAt(mCachedScreenArray.Count() - 1); - } - - if (screenInfo) { - XFree(screenInfo); - } -#endif - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenManagerGtk :: ScreenForId ( uint32_t aId, nsIScreen **outScreen ) -{ - *outScreen = nullptr; - - nsresult rv; - rv = EnsureInit(); - if (NS_FAILED(rv)) { - NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from ScreenForId"); - return rv; - } - - for (int32_t i = 0, i_end = mCachedScreenArray.Count(); i < i_end; ++i) { - uint32_t id; - rv = mCachedScreenArray[i]->GetId(&id); - if (NS_SUCCEEDED(rv) && id == aId) { - NS_IF_ADDREF(*outScreen = mCachedScreenArray[i]); - return NS_OK; - } - } - - return NS_ERROR_FAILURE; -} - - -// -// ScreenForRect -// -// Returns the screen that contains the rectangle. If the rect overlaps -// multiple screens, it picks the screen with the greatest area of intersection. -// -// The coordinates are in desktop pixels. -// -NS_IMETHODIMP -nsScreenManagerGtk::ScreenForRect(int32_t aX, int32_t aY, - int32_t aWidth, int32_t aHeight, - nsIScreen **aOutScreen) -{ - nsresult rv; - rv = EnsureInit(); - if (NS_FAILED(rv)) { - NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from ScreenForRect"); - return rv; - } - - // which screen ( index from zero ) should we return? - uint32_t which = 0; - // Optimize for the common case. If the number of screens is only - // one then this will fall through with which == 0 and will get the - // primary screen. - if (mCachedScreenArray.Count() > 1) { - // walk the list of screens and find the one that has the most - // surface area. - uint32_t area = 0; - nsIntRect windowRect(aX, aY, aWidth, aHeight); - for (int32_t i = 0, i_end = mCachedScreenArray.Count(); i < i_end; ++i) { - int32_t x, y, width, height; - x = y = width = height = 0; - mCachedScreenArray[i]->GetRect(&x, &y, &width, &height); - // calculate the surface area - nsIntRect screenRect(x, y, width, height); - screenRect.IntersectRect(screenRect, windowRect); - uint32_t tempArea = screenRect.width * screenRect.height; - if (tempArea >= area) { - which = i; - area = tempArea; - } - } - } - *aOutScreen = mCachedScreenArray.SafeObjectAt(which); - NS_IF_ADDREF(*aOutScreen); - return NS_OK; - -} // ScreenForRect - - -// -// GetPrimaryScreen -// -// The screen with the menubar/taskbar. This shouldn't be needed very -// often. -// -NS_IMETHODIMP -nsScreenManagerGtk :: GetPrimaryScreen(nsIScreen * *aPrimaryScreen) -{ - nsresult rv; - rv = EnsureInit(); - if (NS_FAILED(rv)) { - NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from GetPrimaryScreen"); - return rv; - } - *aPrimaryScreen = mCachedScreenArray.SafeObjectAt(0); - NS_IF_ADDREF(*aPrimaryScreen); - return NS_OK; - -} // GetPrimaryScreen - -NS_IMETHODIMP -nsScreenManagerGtk::GetSystemDefaultScale(float *aDefaultScale) -{ - *aDefaultScale = nsScreenGtk::GetDPIScale(); - return NS_OK; -} - -NS_IMETHODIMP -nsScreenManagerGtk :: ScreenForNativeWidget (void *aWidget, nsIScreen **outScreen) -{ - nsresult rv; - rv = EnsureInit(); - if (NS_FAILED(rv)) { - NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from ScreenForNativeWidget"); - return rv; - } - - if (mCachedScreenArray.Count() > 1) { - // I don't know how to go from GtkWindow to nsIScreen, especially - // given xinerama and stuff, so let's just do this - gint x, y, width, height; -#if (MOZ_WIDGET_GTK == 2) - gint depth; -#endif - x = y = width = height = 0; - -#if (MOZ_WIDGET_GTK == 2) - gdk_window_get_geometry(GDK_WINDOW(aWidget), &x, &y, &width, &height, - &depth); -#else - gdk_window_get_geometry(GDK_WINDOW(aWidget), &x, &y, &width, &height); -#endif - gdk_window_get_origin(GDK_WINDOW(aWidget), &x, &y); - rv = ScreenForRect(x, y, width, height, outScreen); - } else { - rv = GetPrimaryScreen(outScreen); - } - - return rv; -} diff --git a/widget/gtk/nsScreenManagerGtk.h b/widget/gtk/nsScreenManagerGtk.h deleted file mode 100644 index 9afb3bf2219e..000000000000 --- a/widget/gtk/nsScreenManagerGtk.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef nsScreenManagerGtk_h___ -#define nsScreenManagerGtk_h___ - -#include "nsIScreenManager.h" -#include "nsIScreen.h" -#include "nsCOMPtr.h" -#include "nsCOMArray.h" -#include "prlink.h" -#include "gdk/gdk.h" -#ifdef MOZ_X11 -#include -#endif - -//------------------------------------------------------------------------ - -class nsScreenManagerGtk : public nsIScreenManager -{ -public: - nsScreenManagerGtk ( ); - - NS_DECL_ISUPPORTS - NS_DECL_NSISCREENMANAGER - -#ifdef MOZ_X11 - Atom NetWorkareaAtom() { return mNetWorkareaAtom; } -#endif - - // For internal use, or reinitialization from change notification. - nsresult Init(); - -private: - virtual ~nsScreenManagerGtk(); - - nsresult EnsureInit(); - - // Cached screen array. Its length is the number of screens we have. - nsCOMArray mCachedScreenArray; - - PRLibrary *mXineramalib; - - GdkWindow *mRootWindow; -#ifdef MOZ_X11 - Atom mNetWorkareaAtom; -#endif -}; - -#endif // nsScreenManagerGtk_h___ diff --git a/widget/gtk/nsWidgetFactory.cpp b/widget/gtk/nsWidgetFactory.cpp index 7e4274377d50..fe7e6e9e7e98 100644 --- a/widget/gtk/nsWidgetFactory.cpp +++ b/widget/gtk/nsWidgetFactory.cpp @@ -29,7 +29,6 @@ #include "nsFilePicker.h" #include "nsSound.h" #include "nsBidiKeyboard.h" -#include "nsScreenManagerGtk.h" #include "nsGTKToolkit.h" #include "WakeLockListener.h" @@ -54,6 +53,7 @@ #include "nsIComponentRegistrar.h" #include "nsComponentManagerUtils.h" #include "mozilla/gfx/2D.h" +#include "mozilla/widget/ScreenManager.h" #include using namespace mozilla; @@ -77,7 +77,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsClipboard, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService) #endif NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerGtk) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton) NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageToPixbuf) @@ -243,7 +243,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { #endif { &kNS_HTMLFORMATCONVERTER_CID, false, nullptr, nsHTMLFormatConverterConstructor }, { &kNS_BIDIKEYBOARD_CID, false, nullptr, nsBidiKeyboardConstructor }, - { &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerGtkConstructor, + { &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor, Module::MAIN_PROCESS_ONLY }, { &kNS_THEMERENDERER_CID, false, nullptr, nsNativeThemeGTKConstructor }, #ifdef NS_PRINTING diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index 6d0182b303ed..f59b67980ff0 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -34,7 +34,7 @@ #include "nsGtkKeyUtils.h" #include "nsGtkCursors.h" -#include "nsScreenGtk.h" +#include "ScreenHelperGTK.h" #include #if (MOZ_WIDGET_GTK == 3) @@ -6439,7 +6439,7 @@ nsWindow::GdkScaleFactor() if (sGdkWindowGetScaleFactorPtr && mGdkWindow) return (*sGdkWindowGetScaleFactorPtr)(mGdkWindow); #endif - return nsScreenGtk::GetGtkMonitorScaleFactor(); + return ScreenHelperGTK::GetGTKMonitorScaleFactor(); } From 8ba424eabbf0007e6210bbb74ae9d45f563da0a5 Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Thu, 9 Mar 2017 19:30:26 +0800 Subject: [PATCH 35/57] Bug 1194751 - Part 6. Use mozilla::widget::ScreenManager in content process. r=mconley This is the most important part of the patch series. It removes the PScreenManager protocol and use ScreenManager directly in the content processes. Initial and subsequent updates are sent via PContent::RefreshScreens. struct ScreenDetails are kept to serialize Screen over IPC. nsIScreenManager::ScreenForNativeWidget is removed because nsIWidget::GetWidgetScreen can replace it. nsIScreen::GetId is removed because it's not useful for the more general Screen class. MozReview-Commit-ID: 5dJO3isgBuQ --HG-- extra : rebase_source : 06aa4e4fd56e2b2af1e7483aee7c0cc7f35bdb97 --- dom/ipc/ContentChild.cpp | 30 +-- dom/ipc/ContentChild.h | 9 +- dom/ipc/ContentParent.cpp | 19 +- dom/ipc/ContentParent.h | 7 - dom/ipc/DOMTypes.ipdlh | 16 ++ dom/ipc/PBrowser.ipdl | 1 - dom/ipc/PContent.ipdl | 8 +- dom/ipc/PScreenManager.ipdl | 62 ------ dom/ipc/ScreenManagerParent.cpp | 227 --------------------- dom/ipc/ScreenManagerParent.h | 54 ----- dom/ipc/moz.build | 2 - dom/plugins/base/nsPluginInstanceOwner.cpp | 7 +- gfx/src/nsDeviceContext.cpp | 17 +- ipc/ipdl/sync-messages.ini | 12 -- widget/PuppetWidget.cpp | 22 -- widget/PuppetWidget.h | 1 - widget/Screen.cpp | 27 ++- widget/Screen.h | 10 +- widget/ScreenManager.cpp | 70 +++++-- widget/ScreenManager.h | 13 ++ widget/ScreenProxy.cpp | 213 ------------------- widget/ScreenProxy.h | 75 ------- widget/android/nsScreenManagerAndroid.cpp | 7 - widget/cocoa/nsScreenManagerCocoa.mm | 19 -- widget/gonk/nsScreenManagerGonk.cpp | 14 -- widget/moz.build | 2 - widget/nsContentProcessWidgetFactory.cpp | 10 +- widget/nsIScreen.idl | 6 - widget/nsIScreenManager.idl | 17 -- widget/nsScreenManagerProxy.cpp | 205 ------------------- widget/nsScreenManagerProxy.h | 66 ------ widget/uikit/nsScreenManager.mm | 13 -- widget/windows/nsScreenManagerWin.cpp | 8 - 33 files changed, 133 insertions(+), 1136 deletions(-) delete mode 100644 dom/ipc/PScreenManager.ipdl delete mode 100644 dom/ipc/ScreenManagerParent.cpp delete mode 100644 dom/ipc/ScreenManagerParent.h delete mode 100644 widget/ScreenProxy.cpp delete mode 100644 widget/ScreenProxy.h delete mode 100644 widget/nsScreenManagerProxy.cpp delete mode 100644 widget/nsScreenManagerProxy.h diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 74e3e2ed1ffb..1c766d2291aa 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -61,6 +61,7 @@ #include "mozilla/net/CaptivePortalService.h" #include "mozilla/plugins/PluginInstanceParent.h" #include "mozilla/plugins/PluginModuleParent.h" +#include "mozilla/widget/ScreenManager.h" #include "mozilla/widget/WidgetMessageUtils.h" #include "nsBaseDragService.h" #include "mozilla/media/MediaChild.h" @@ -99,7 +100,6 @@ #include "nsIMutable.h" #include "nsIObserverService.h" #include "nsIScriptSecurityManager.h" -#include "nsScreenManagerProxy.h" #include "nsMemoryInfoDumper.h" #include "nsServiceManagerUtils.h" #include "nsStyleSheetService.h" @@ -1748,27 +1748,6 @@ ContentChild::DeallocPParentToChildStreamChild(PParentToChildStreamChild* aActor return nsIContentChild::DeallocPParentToChildStreamChild(aActor); } -PScreenManagerChild* -ContentChild::AllocPScreenManagerChild(float* aSystemDefaultScale, - bool* aSuccess) -{ - // The ContentParent should never attempt to allocate the - // nsScreenManagerProxy. Instead, the nsScreenManagerProxy - // service is requested and instantiated via XPCOM, and the - // constructor of nsScreenManagerProxy sets up the IPC connection. - MOZ_CRASH("Should never get here!"); - return nullptr; -} - -bool -ContentChild::DeallocPScreenManagerChild(PScreenManagerChild* aService) -{ - // nsScreenManagerProxy is AddRef'd in its constructor. - nsScreenManagerProxy *child = static_cast(aService); - child->Release(); - return true; -} - PPSMContentDownloaderChild* ContentChild::AllocPPSMContentDownloaderChild(const uint32_t& aCertType) { @@ -3267,7 +3246,14 @@ ContentChild::RecvSetPermissionsWithKey(const nsCString& aPermissionKey, nsCOMPtr permissionManager = services::GetPermissionManager(); permissionManager->SetPermissionsWithKey(aPermissionKey, aPerms); + return IPC_OK(); +} +mozilla::ipc::IPCResult +ContentChild::RecvRefreshScreens(nsTArray&& aScreens) +{ + ScreenManager& screenManager = ScreenManager::GetSingleton(); + screenManager.Refresh(Move(aScreens)); return IPC_OK(); } diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index cc01fb8d6fd3..0f5d27c4b652 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -242,12 +242,6 @@ public: virtual PParentToChildStreamChild* AllocPParentToChildStreamChild() override; virtual bool DeallocPParentToChildStreamChild(PParentToChildStreamChild*) override; - virtual PScreenManagerChild* - AllocPScreenManagerChild(float* aSystemDefaultScale, - bool* aSuccess) override; - - virtual bool DeallocPScreenManagerChild(PScreenManagerChild*) override; - virtual PPSMContentDownloaderChild* AllocPPSMContentDownloaderChild( const uint32_t& aCertType) override; @@ -476,6 +470,9 @@ public: virtual mozilla::ipc::IPCResult RecvParentActivated(PBrowserChild* aTab, const bool& aActivated) override; + mozilla::ipc::IPCResult + RecvRefreshScreens(nsTArray&& aScreens) override; + // Get the directory for IndexedDB files. We query the parent for this and // cache the value nsString &GetIndexedDBPath(); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index fc486199a061..09e88712c201 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -97,6 +97,7 @@ #include "mozilla/Telemetry.h" #include "mozilla/TelemetryIPC.h" #include "mozilla/WebBrowserPersistDocumentParent.h" +#include "mozilla/widget/ScreenManager.h" #include "mozilla/Unused.h" #include "nsAnonymousTemporaryFile.h" #include "nsAppRunner.h" @@ -162,7 +163,6 @@ #include "PreallocatedProcessManager.h" #include "ProcessPriorityManager.h" #include "SandboxHal.h" -#include "ScreenManagerParent.h" #include "SourceSurfaceRawData.h" #include "TabParent.h" #include "URIUtils.h" @@ -2233,6 +2233,9 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority, storage->GetAll(&entry.items()); xpcomInit.dataStorage().AppendElement(Move(entry)); } + // Must send screen info before send initialData + ScreenManager& screenManager = ScreenManager::GetSingleton(); + screenManager.CopyScreensToRemote(this); Unused << SendSetXPCOMProcessAttributes(xpcomInit, initialData, lnfCache); @@ -3136,20 +3139,6 @@ ContentParent::DeallocPParentToChildStreamParent(PParentToChildStreamParent* aAc return nsIContentParent::DeallocPParentToChildStreamParent(aActor); } -PScreenManagerParent* -ContentParent::AllocPScreenManagerParent(float* aSystemDefaultScale, - bool* aSuccess) -{ - return new ScreenManagerParent(aSystemDefaultScale, aSuccess); -} - -bool -ContentParent::DeallocPScreenManagerParent(PScreenManagerParent* aActor) -{ - delete aActor; - return true; -} - PPSMContentDownloaderParent* ContentParent::AllocPPSMContentDownloaderParent(const uint32_t& aCertType) { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 0bcf75029aec..c5c99336b512 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -446,13 +446,6 @@ public: virtual bool DeallocPParentToChildStreamParent(PParentToChildStreamParent* aActor) override; - virtual PScreenManagerParent* - AllocPScreenManagerParent(float* aSystemDefaultScale, - bool* aSuccess) override; - - virtual bool - DeallocPScreenManagerParent(PScreenManagerParent* aActor) override; - virtual PHalParent* AllocPHalParent() override; virtual mozilla::ipc::IPCResult RecvPHalConstructor(PHalParent* aActor) override diff --git a/dom/ipc/DOMTypes.ipdlh b/dom/ipc/DOMTypes.ipdlh index f1e954db7680..92dd88fd990d 100644 --- a/dom/ipc/DOMTypes.ipdlh +++ b/dom/ipc/DOMTypes.ipdlh @@ -16,6 +16,11 @@ using struct mozilla::void_t using struct mozilla::SerializedStructuredCloneBuffer from "ipc/IPCMessageUtils.h"; +using LayoutDeviceIntRect from "Units.h"; +using DesktopIntRect from "Units.h"; +using DesktopToLayoutDeviceScale from "Units.h"; +using CSSToLayoutDeviceScale from "Units.h"; + namespace mozilla { namespace dom { @@ -178,5 +183,16 @@ struct IPCDataTransfer IPCDataTransferItem[] items; }; +struct ScreenDetails { + LayoutDeviceIntRect rect; + DesktopIntRect rectDisplayPix; + LayoutDeviceIntRect availRect; + DesktopIntRect availRectDisplayPix; + int32_t pixelDepth; + int32_t colorDepth; + DesktopToLayoutDeviceScale contentsScaleFactor; + CSSToLayoutDeviceScale defaultCSSScaleFactor; +}; + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 16e3b3f14994..222b41201594 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -28,7 +28,6 @@ using class mozilla::gfx::Matrix from "mozilla/gfx/Matrix.h"; using struct gfxSize from "gfxPoint.h"; using CSSRect from "Units.h"; using CSSSize from "Units.h"; -using mozilla::LayoutDeviceIntRect from "Units.h"; using mozilla::LayoutDeviceIntPoint from "Units.h"; using mozilla::LayoutDevicePoint from "Units.h"; using mozilla::ScreenIntPoint from "Units.h"; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 977ff8dbea49..322a3c053fd4 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -30,7 +30,6 @@ include protocol PChildToParentStream; include protocol PParentToChildStream; include protocol POfflineCacheUpdate; include protocol PRenderFrame; -include protocol PScreenManager; include protocol PSpeechSynthesis; include protocol PStorage; include protocol PTestShell; @@ -289,7 +288,6 @@ nested(upto inside_cpow) sync protocol PContent manages PPrinting; manages PChildToParentStream; manages PParentToChildStream; - manages PScreenManager; manages PSpeechSynthesis; manages PStorage; manages PTestShell; @@ -595,6 +593,8 @@ child: async SetPermissionsWithKey(nsCString aPermissionKey, Permission[] aPermissions); + async RefreshScreens(ScreenDetails[] aScreens); + parent: async InitBackground(Endpoint aEndpoint); @@ -711,10 +711,6 @@ parent: async PChildToParentStream(); - nested(inside_sync) sync PScreenManager() - returns (float systemDefaultScale, - bool success); - async PSpeechSynthesis(); nested(inside_cpow) async PStorage(); diff --git a/dom/ipc/PScreenManager.ipdl b/dom/ipc/PScreenManager.ipdl deleted file mode 100644 index ce2c441ba7f3..000000000000 --- a/dom/ipc/PScreenManager.ipdl +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */ -/* 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/. */ - -include protocol PBrowser; -include protocol PContent; - -include "mozilla/GfxMessageUtils.h"; - -using nsIntRect from "nsRect.h"; -using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h"; - -namespace mozilla { -namespace dom { - -struct ScreenDetails { - uint32_t id; - nsIntRect rect; - nsIntRect rectDisplayPix; - nsIntRect availRect; - nsIntRect availRectDisplayPix; - int32_t pixelDepth; - int32_t colorDepth; - double contentsScaleFactor; - double defaultCSSScaleFactor; -}; - -nested(upto inside_cpow) sync protocol PScreenManager -{ - manager PContent; - -parent: - nested(inside_sync) sync Refresh() - returns (float systemDefaultScale, - bool success); - - nested(inside_cpow) sync ScreenRefresh(uint32_t aId) - returns (ScreenDetails screen, - bool success); - - nested(inside_sync) sync GetPrimaryScreen() - returns (ScreenDetails screen, - bool success); - - nested(inside_sync) sync ScreenForRect(int32_t aLeft, - int32_t aTop, - int32_t aWidth, - int32_t aHeight) - returns (ScreenDetails screen, - bool success); - - nested(inside_cpow) sync ScreenForBrowser(TabId aTabId) - returns (ScreenDetails screen, - bool success); - -child: - async __delete__(); -}; - -} // namespace dom -} // namespace mozilla diff --git a/dom/ipc/ScreenManagerParent.cpp b/dom/ipc/ScreenManagerParent.cpp deleted file mode 100644 index b3b19c44c581..000000000000 --- a/dom/ipc/ScreenManagerParent.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#include "mozilla/dom/ContentParent.h" -#include "mozilla/dom/TabParent.h" -#include "mozilla/Unused.h" -#include "nsIWidget.h" -#include "nsServiceManagerUtils.h" -#include "ScreenManagerParent.h" -#include "ContentProcessManager.h" - -namespace mozilla { -namespace dom { - -static const char *sScreenManagerContractID = "@mozilla.org/gfx/screenmanager;1"; - -ScreenManagerParent::ScreenManagerParent(float* aSystemDefaultScale, - bool* aSuccess) -{ - mScreenMgr = do_GetService(sScreenManagerContractID); - if (!mScreenMgr) { - MOZ_CRASH("Couldn't get nsIScreenManager from ScreenManagerParent."); - } - - Unused << RecvRefresh(aSystemDefaultScale, aSuccess); -} - -mozilla::ipc::IPCResult -ScreenManagerParent::RecvRefresh(float* aSystemDefaultScale, - bool* aSuccess) -{ - *aSuccess = false; - - nsresult rv = mScreenMgr->GetSystemDefaultScale(aSystemDefaultScale); - if (NS_FAILED(rv)) { - return IPC_OK(); - } - - *aSuccess = true; - return IPC_OK(); -} - -mozilla::ipc::IPCResult -ScreenManagerParent::RecvScreenRefresh(const uint32_t& aId, - ScreenDetails* aRetVal, - bool* aSuccess) -{ - *aSuccess = false; - - nsCOMPtr screen; - nsresult rv = mScreenMgr->ScreenForId(aId, getter_AddRefs(screen)); - if (NS_FAILED(rv)) { - return IPC_OK(); - } - - ScreenDetails details; - Unused << ExtractScreenDetails(screen, details); - - *aRetVal = details; - *aSuccess = true; - return IPC_OK(); -} - -mozilla::ipc::IPCResult -ScreenManagerParent::RecvGetPrimaryScreen(ScreenDetails* aRetVal, - bool* aSuccess) -{ - *aSuccess = false; - - nsCOMPtr screen; - nsresult rv = mScreenMgr->GetPrimaryScreen(getter_AddRefs(screen)); - - NS_ENSURE_SUCCESS(rv, IPC_OK()); - - ScreenDetails details; - if (!ExtractScreenDetails(screen, details)) { - return IPC_OK(); - } - - *aRetVal = details; - *aSuccess = true; - return IPC_OK(); -} - -mozilla::ipc::IPCResult -ScreenManagerParent::RecvScreenForRect(const int32_t& aLeft, - const int32_t& aTop, - const int32_t& aWidth, - const int32_t& aHeight, - ScreenDetails* aRetVal, - bool* aSuccess) -{ - *aSuccess = false; - - nsCOMPtr screen; - nsresult rv = mScreenMgr->ScreenForRect(aLeft, aTop, aWidth, aHeight, getter_AddRefs(screen)); - - NS_ENSURE_SUCCESS(rv, IPC_OK()); - - ScreenDetails details; - if (!ExtractScreenDetails(screen, details)) { - return IPC_OK(); - } - - *aRetVal = details; - *aSuccess = true; - return IPC_OK(); -} - -mozilla::ipc::IPCResult -ScreenManagerParent::RecvScreenForBrowser(const TabId& aTabId, - ScreenDetails* aRetVal, - bool* aSuccess) -{ - *aSuccess = false; -#ifdef MOZ_VALGRIND - // Zero this so that Valgrind doesn't complain when we send it to another - // process. - memset(aRetVal, 0, sizeof(ScreenDetails)); -#endif - - // Find the mWidget associated with the tabparent, and then return - // the nsIScreen it's on. - ContentParent* cp = static_cast(this->Manager()); - ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - RefPtr tabParent = - cpm->GetTopLevelTabParentByProcessAndTabId(cp->ChildID(), aTabId); - if(!tabParent){ - return IPC_FAIL_NO_REASON(this); - } - - nsCOMPtr widget = tabParent->GetWidget(); - - nsCOMPtr screen; - if (widget && widget->GetNativeData(NS_NATIVE_WINDOW)) { - mScreenMgr->ScreenForNativeWidget(widget->GetNativeData(NS_NATIVE_WINDOW), - getter_AddRefs(screen)); - } else { - nsresult rv = mScreenMgr->GetPrimaryScreen(getter_AddRefs(screen)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return IPC_OK(); - } - } - - NS_ENSURE_TRUE(screen, IPC_OK()); - - ScreenDetails details; - if (!ExtractScreenDetails(screen, details)) { - return IPC_OK(); - } - - *aRetVal = details; - *aSuccess = true; - return IPC_OK(); -} - -bool -ScreenManagerParent::ExtractScreenDetails(nsIScreen* aScreen, ScreenDetails &aDetails) -{ - if (!aScreen) { - return false; - } - - uint32_t id; - nsresult rv = aScreen->GetId(&id); - NS_ENSURE_SUCCESS(rv, false); - aDetails.id() = id; - - nsIntRect rect; - rv = aScreen->GetRect(&rect.x, &rect.y, &rect.width, &rect.height); - NS_ENSURE_SUCCESS(rv, false); - aDetails.rect() = rect; - - nsIntRect rectDisplayPix; - rv = aScreen->GetRectDisplayPix(&rectDisplayPix.x, &rectDisplayPix.y, - &rectDisplayPix.width, &rectDisplayPix.height); - NS_ENSURE_SUCCESS(rv, false); - aDetails.rectDisplayPix() = rectDisplayPix; - - nsIntRect availRect; - rv = aScreen->GetAvailRect(&availRect.x, &availRect.y, &availRect.width, - &availRect.height); - NS_ENSURE_SUCCESS(rv, false); - aDetails.availRect() = availRect; - - nsIntRect availRectDisplayPix; - rv = aScreen->GetAvailRectDisplayPix(&availRectDisplayPix.x, - &availRectDisplayPix.y, - &availRectDisplayPix.width, - &availRectDisplayPix.height); - NS_ENSURE_SUCCESS(rv, false); - aDetails.availRectDisplayPix() = availRectDisplayPix; - - int32_t pixelDepth = 0; - rv = aScreen->GetPixelDepth(&pixelDepth); - NS_ENSURE_SUCCESS(rv, false); - aDetails.pixelDepth() = pixelDepth; - - int32_t colorDepth = 0; - rv = aScreen->GetColorDepth(&colorDepth); - NS_ENSURE_SUCCESS(rv, false); - aDetails.colorDepth() = colorDepth; - - double contentsScaleFactor = 1.0; - rv = aScreen->GetContentsScaleFactor(&contentsScaleFactor); - NS_ENSURE_SUCCESS(rv, false); - aDetails.contentsScaleFactor() = contentsScaleFactor; - - double defaultCSSScaleFactor = 1.0; - rv = aScreen->GetDefaultCSSScaleFactor(&defaultCSSScaleFactor); - NS_ENSURE_SUCCESS(rv, false); - aDetails.defaultCSSScaleFactor() = defaultCSSScaleFactor; - - return true; -} - -void -ScreenManagerParent::ActorDestroy(ActorDestroyReason why) -{ -} - -} // namespace dom -} // namespace mozilla - diff --git a/dom/ipc/ScreenManagerParent.h b/dom/ipc/ScreenManagerParent.h deleted file mode 100644 index 01de6d364cd9..000000000000 --- a/dom/ipc/ScreenManagerParent.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#ifndef mozilla_dom_ScreenManagerParent_h -#define mozilla_dom_ScreenManagerParent_h - -#include "mozilla/dom/PScreenManagerParent.h" -#include "nsIScreenManager.h" - -namespace mozilla { -namespace dom { - -class ScreenManagerParent : public PScreenManagerParent -{ - public: - ScreenManagerParent(float* aSystemDefaultScale, - bool* aSuccess); - ~ScreenManagerParent() {}; - - virtual mozilla::ipc::IPCResult RecvRefresh(float* aSystemDefaultScale, - bool* aSuccess) override; - - virtual mozilla::ipc::IPCResult RecvScreenRefresh(const uint32_t& aId, - ScreenDetails* aRetVal, - bool* aSuccess) override; - - virtual void ActorDestroy(ActorDestroyReason aWhy) override; - - virtual mozilla::ipc::IPCResult RecvGetPrimaryScreen(ScreenDetails* aRetVal, - bool* aSuccess) override; - - virtual mozilla::ipc::IPCResult RecvScreenForRect(const int32_t& aLeft, - const int32_t& aTop, - const int32_t& aWidth, - const int32_t& aHeight, - ScreenDetails* aRetVal, - bool* aSuccess) override; - - virtual mozilla::ipc::IPCResult RecvScreenForBrowser(const TabId& aTabId, - ScreenDetails* aRetVal, - bool* aSuccess) override; - - private: - bool ExtractScreenDetails(nsIScreen* aScreen, ScreenDetails &aDetails); - nsCOMPtr mScreenMgr; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_ScreenManagerParent_h diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index e7f33e40e774..2cdda565153c 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -65,7 +65,6 @@ UNIFIED_SOURCES += [ 'PermissionMessageUtils.cpp', 'PreallocatedProcessManager.cpp', 'ProcessPriorityManager.cpp', - 'ScreenManagerParent.cpp', 'StructuredCloneData.cpp', 'TabChild.cpp', 'TabContext.cpp', @@ -97,7 +96,6 @@ IPDL_SOURCES += [ 'PFilePicker.ipdl', 'PPluginWidget.ipdl', 'PProcessHangMonitor.ipdl', - 'PScreenManager.ipdl', 'PTabContext.ipdlh', 'PURLClassifier.ipdl', 'PURLClassifierInfo.ipdlh', diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index 0d8b6b0d7805..8e82e8ca6c9f 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -1172,12 +1172,7 @@ NPBool nsPluginInstanceOwner::ConvertPointNoPuppet(nsIWidget *widget, double scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/ presContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom(); - nsCOMPtr screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1"); - if (!screenMgr) { - return false; - } - nsCOMPtr screen; - screenMgr->ScreenForNativeWidget(widget->GetNativeData(NS_NATIVE_WINDOW), getter_AddRefs(screen)); + nsCOMPtr screen = widget->GetWidgetScreen(); if (!screen) { return false; } diff --git a/gfx/src/nsDeviceContext.cpp b/gfx/src/nsDeviceContext.cpp index a0ee2d309464..79bd864e5196 100644 --- a/gfx/src/nsDeviceContext.cpp +++ b/gfx/src/nsDeviceContext.cpp @@ -609,21 +609,8 @@ nsDeviceContext::FindScreen(nsIScreen** outScreen) CheckDPIChange(); - if (mWidget->GetOwningTabChild()) { - mScreenManager->ScreenForNativeWidget((void *)mWidget->GetOwningTabChild(), - outScreen); - } - else if (mWidget->GetNativeData(NS_NATIVE_WINDOW)) { - mScreenManager->ScreenForNativeWidget(mWidget->GetNativeData(NS_NATIVE_WINDOW), - outScreen); - } - -#ifdef MOZ_WIDGET_ANDROID - if (!(*outScreen)) { - nsCOMPtr screen = mWidget->GetWidgetScreen(); - screen.forget(outScreen); - } -#endif + nsCOMPtr screen = mWidget->GetWidgetScreen(); + screen.forget(outScreen); if (!(*outScreen)) { mScreenManager->GetPrimaryScreen(outScreen); diff --git a/ipc/ipdl/sync-messages.ini b/ipc/ipdl/sync-messages.ini index 6b2236cb0a84..9502f445fe07 100644 --- a/ipc/ipdl/sync-messages.ini +++ b/ipc/ipdl/sync-messages.ini @@ -884,8 +884,6 @@ description = description = [PContent::IsSecureURI] description = -[PContent::PScreenManager] -description = [PContent::PURLClassifier] description = [PContent::ClassifyLocal] @@ -934,16 +932,6 @@ description = description = [PContentBridge::SyncMessage] description = -[PScreenManager::Refresh] -description = -[PScreenManager::ScreenRefresh] -description = -[PScreenManager::GetPrimaryScreen] -description = -[PScreenManager::ScreenForRect] -description = -[PScreenManager::ScreenForBrowser] -description = [PGMP::StartPlugin] description = [PGMPService::LaunchGMP] diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index 70f4f51f6344..5c36b4b26139 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -1357,13 +1357,6 @@ PuppetWidget::GetScreenDimensions() return nsIntSize(r.width, r.height); } -NS_IMETHODIMP -PuppetScreen::GetId(uint32_t *outId) -{ - *outId = 1; - return NS_OK; -} - NS_IMETHODIMP PuppetScreen::GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) @@ -1408,14 +1401,6 @@ PuppetScreenManager::~PuppetScreenManager() { } -NS_IMETHODIMP -PuppetScreenManager::ScreenForId(uint32_t aId, - nsIScreen** outScreen) -{ - NS_IF_ADDREF(*outScreen = mOneScreen.get()); - return NS_OK; -} - NS_IMETHODIMP PuppetScreenManager::GetPrimaryScreen(nsIScreen** outScreen) { @@ -1433,13 +1418,6 @@ PuppetScreenManager::ScreenForRect(int32_t inLeft, return GetPrimaryScreen(outScreen); } -NS_IMETHODIMP -PuppetScreenManager::ScreenForNativeWidget(void* aWidget, - nsIScreen** outScreen) -{ - return GetPrimaryScreen(outScreen); -} - NS_IMETHODIMP PuppetScreenManager::GetSystemDefaultScale(float *aDefaultScale) { diff --git a/widget/PuppetWidget.h b/widget/PuppetWidget.h index b7c2520e0fd6..4a326b59b16d 100644 --- a/widget/PuppetWidget.h +++ b/widget/PuppetWidget.h @@ -443,7 +443,6 @@ public: explicit PuppetScreen(void* nativeScreen); ~PuppetScreen(); - NS_IMETHOD GetId(uint32_t* aId) override; NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override; NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override; NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override; diff --git a/widget/Screen.cpp b/widget/Screen.cpp index 10c2eb84ed92..7ed3203cfc78 100644 --- a/widget/Screen.cpp +++ b/widget/Screen.cpp @@ -6,13 +6,13 @@ #include "Screen.h" +#include "mozilla/dom/DOMTypes.h" + namespace mozilla { namespace widget { NS_IMPL_ISUPPORTS(Screen, nsIScreen) -static uint32_t sScreenId = 0; - Screen::Screen(LayoutDeviceIntRect aRect, LayoutDeviceIntRect aAvailRect, uint32_t aPixelDepth, uint32_t aColorDepth, DesktopToLayoutDeviceScale aContentsScale, @@ -25,7 +25,18 @@ Screen::Screen(LayoutDeviceIntRect aRect, LayoutDeviceIntRect aAvailRect, , mColorDepth(aColorDepth) , mContentsScale(aContentsScale) , mDefaultCssScale(aDefaultCssScale) - , mId(++sScreenId) +{ +} + +Screen::Screen(const mozilla::dom::ScreenDetails& aScreen) + : mRect(aScreen.rect()) + , mAvailRect(aScreen.availRect()) + , mRectDisplayPix(aScreen.rectDisplayPix()) + , mAvailRectDisplayPix(aScreen.availRectDisplayPix()) + , mPixelDepth(aScreen.pixelDepth()) + , mColorDepth(aScreen.colorDepth()) + , mContentsScale(aScreen.contentsScaleFactor()) + , mDefaultCssScale(aScreen.defaultCSSScaleFactor()) { } @@ -38,15 +49,15 @@ Screen::Screen(const Screen& aOther) , mColorDepth(aOther.mColorDepth) , mContentsScale(aOther.mContentsScale) , mDefaultCssScale(aOther.mDefaultCssScale) - , mId(aOther.mId) { } -NS_IMETHODIMP -Screen::GetId(uint32_t* aOutId) +mozilla::dom::ScreenDetails +Screen::ToScreenDetails() { - *aOutId = mId; - return NS_OK; + return mozilla::dom::ScreenDetails( + mRect, mRectDisplayPix, mAvailRect, mAvailRectDisplayPix, + mPixelDepth, mColorDepth, mContentsScale, mDefaultCssScale); } NS_IMETHODIMP diff --git a/widget/Screen.h b/widget/Screen.h index 267bf153a68a..44357d5d5cdb 100644 --- a/widget/Screen.h +++ b/widget/Screen.h @@ -11,6 +11,12 @@ #include "Units.h" +namespace mozilla { +namespace dom { +class ScreenDetails; +} // namespace dom +} // namespace mozilla + namespace mozilla { namespace widget { @@ -24,8 +30,11 @@ public: uint32_t aPixelDepth, uint32_t aColorDepth, DesktopToLayoutDeviceScale aContentsScale, CSSToLayoutDeviceScale aDefaultCssScale); + explicit Screen(const mozilla::dom::ScreenDetails& aScreenDetails); Screen(const Screen& aOther); + mozilla::dom::ScreenDetails ToScreenDetails(); + private: virtual ~Screen() {} @@ -37,7 +46,6 @@ private: uint32_t mColorDepth; DesktopToLayoutDeviceScale mContentsScale; CSSToLayoutDeviceScale mDefaultCssScale; - uint32_t mId; }; } // namespace widget diff --git a/widget/ScreenManager.cpp b/widget/ScreenManager.cpp index 1a2e078d30bd..5acc12bc8347 100644 --- a/widget/ScreenManager.cpp +++ b/widget/ScreenManager.cpp @@ -7,6 +7,7 @@ #include "ScreenManager.h" #include "mozilla/ClearOnShutdown.h" +#include "mozilla/dom/ContentParent.h" #include "mozilla/Logging.h" #include "mozilla/StaticPtr.h" @@ -53,26 +54,63 @@ ScreenManager::SetHelper(UniquePtr aHelper) void ScreenManager::Refresh(nsTArray>&& aScreens) { + MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refresh screens")); + mScreenList = Move(aScreens); + + CopyScreensToAllRemotesIfIsParent(); } -NS_IMETHODIMP -ScreenManager::ScreenForId(uint32_t aId, nsIScreen** aOutScreen) +void +ScreenManager::Refresh(nsTArray&& aScreens) { - *aOutScreen = nullptr; + MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refresh screens from IPC")); - nsresult rv; - for (auto& screen : mScreenList) { - uint32_t id; - rv = screen->GetId(&id); - if (NS_SUCCEEDED(rv) && id == aId) { - RefPtr ret = screen; - ret.forget(aOutScreen); - return NS_OK; - } + mScreenList.Clear(); + for (auto& screen : aScreens) { + mScreenList.AppendElement(new Screen(screen)); } - return NS_ERROR_FAILURE; + CopyScreensToAllRemotesIfIsParent(); +} + +template +void +ScreenManager::CopyScreensToRemoteRange(Range aRemoteRange) +{ + AutoTArray screens; + for (auto& screen : mScreenList) { + screens.AppendElement(screen->ToScreenDetails()); + } + for (auto cp : aRemoteRange) { + MOZ_LOG(sScreenLog, LogLevel::Debug, ("Send screens to [Pid %d]", cp->Pid())); + if (!cp->SendRefreshScreens(screens)) { + MOZ_LOG(sScreenLog, LogLevel::Error, + ("SendRefreshScreens to [Pid %d] failed", cp->Pid())); + } + } +} + +void +ScreenManager::CopyScreensToRemote(ContentParent* aContentParent) +{ + MOZ_ASSERT(aContentParent); + MOZ_ASSERT(XRE_IsParentProcess()); + + auto range = { aContentParent }; + CopyScreensToRemoteRange(range); +} + +void +ScreenManager::CopyScreensToAllRemotesIfIsParent() +{ + if (XRE_IsContentProcess()) { + return; + } + + MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refreshing all ContentParents")); + + CopyScreensToRemoteRange(ContentParent::AllProcesses(ContentParent::eLive)); } // Returns the screen that contains the rectangle. If the rect overlaps @@ -161,11 +199,5 @@ ScreenManager::GetSystemDefaultScale(float* aDefaultScale) return NS_OK; } -NS_IMETHODIMP -ScreenManager::ScreenForNativeWidget(void* aWidget, nsIScreen** aOutScreen) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - } // namespace widget } // namespace mozilla diff --git a/widget/ScreenManager.h b/widget/ScreenManager.h index 4b76577ebf97..4b2e774d92fe 100644 --- a/widget/ScreenManager.h +++ b/widget/ScreenManager.h @@ -14,6 +14,13 @@ #include "mozilla/widget/Screen.h" #include "nsTArray.h" +namespace mozilla { +namespace dom { +class ContentParent; +class ScreenDetails; +} +} + namespace mozilla { namespace widget { @@ -36,11 +43,17 @@ public: void SetHelper(UniquePtr aHelper); void Refresh(nsTArray>&& aScreens); + void Refresh(nsTArray&& aScreens); + void CopyScreensToRemote(mozilla::dom::ContentParent* aContentParent); private: ScreenManager(); virtual ~ScreenManager(); + template + void CopyScreensToRemoteRange(Range aRemoteRange); + void CopyScreensToAllRemotesIfIsParent(); + AutoTArray, 4> mScreenList; UniquePtr mHelper; }; diff --git a/widget/ScreenProxy.cpp b/widget/ScreenProxy.cpp deleted file mode 100644 index 6986cac86306..000000000000 --- a/widget/ScreenProxy.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */ -/* vim: set sw=4 ts=8 et tw=80 : */ -/* 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/. */ - -#include "mozilla/Unused.h" -#include "nsContentUtils.h" -#include "nsIAppShell.h" -#include "nsScreenManagerProxy.h" -#include "nsServiceManagerUtils.h" -#include "nsWidgetsCID.h" -#include "ScreenProxy.h" - -namespace mozilla { -namespace widget { - -using namespace mozilla::dom; - -static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); - -ScreenProxy::ScreenProxy(nsScreenManagerProxy* aScreenManager, ScreenDetails aDetails) - : mContentsScaleFactor(0) - , mDefaultCSSScaleFactor(0) - , mScreenManager(aScreenManager) - , mId(0) - , mPixelDepth(0) - , mColorDepth(0) - , mCacheValid(false) - , mCacheWillInvalidate(false) -{ - PopulateByDetails(aDetails); -} - -NS_IMETHODIMP -ScreenProxy::GetId(uint32_t *outId) -{ - *outId = mId; - return NS_OK; -} - -NS_IMETHODIMP -ScreenProxy::GetRect(int32_t *outLeft, - int32_t *outTop, - int32_t *outWidth, - int32_t *outHeight) -{ - if (!EnsureCacheIsValid()) { - return NS_ERROR_FAILURE; - } - - *outLeft = mRect.x; - *outTop = mRect.y; - *outWidth = mRect.width; - *outHeight = mRect.height; - return NS_OK; -} - -NS_IMETHODIMP -ScreenProxy::GetRectDisplayPix(int32_t *outLeft, - int32_t *outTop, - int32_t *outWidth, - int32_t *outHeight) -{ - if (!EnsureCacheIsValid()) { - return NS_ERROR_FAILURE; - } - - *outLeft = mRectDisplayPix.x; - *outTop = mRectDisplayPix.y; - *outWidth = mRectDisplayPix.width; - *outHeight = mRectDisplayPix.height; - return NS_OK; -} - -NS_IMETHODIMP -ScreenProxy::GetAvailRect(int32_t *outLeft, - int32_t *outTop, - int32_t *outWidth, - int32_t *outHeight) -{ - if (!EnsureCacheIsValid()) { - return NS_ERROR_FAILURE; - } - - *outLeft = mAvailRect.x; - *outTop = mAvailRect.y; - *outWidth = mAvailRect.width; - *outHeight = mAvailRect.height; - return NS_OK; -} - -NS_IMETHODIMP -ScreenProxy::GetAvailRectDisplayPix(int32_t *outLeft, - int32_t *outTop, - int32_t *outWidth, - int32_t *outHeight) -{ - if (!EnsureCacheIsValid()) { - return NS_ERROR_FAILURE; - } - - *outLeft = mAvailRectDisplayPix.x; - *outTop = mAvailRectDisplayPix.y; - *outWidth = mAvailRectDisplayPix.width; - *outHeight = mAvailRectDisplayPix.height; - return NS_OK; -} - -NS_IMETHODIMP -ScreenProxy::GetPixelDepth(int32_t *aPixelDepth) -{ - if (!EnsureCacheIsValid()) { - return NS_ERROR_FAILURE; - } - - *aPixelDepth = mPixelDepth; - return NS_OK; -} - -NS_IMETHODIMP -ScreenProxy::GetColorDepth(int32_t *aColorDepth) -{ - if (!EnsureCacheIsValid()) { - return NS_ERROR_FAILURE; - } - - *aColorDepth = mColorDepth; - return NS_OK; -} - -NS_IMETHODIMP -ScreenProxy::GetContentsScaleFactor(double* aContentsScaleFactor) -{ - if (!EnsureCacheIsValid()) { - return NS_ERROR_FAILURE; - } - - *aContentsScaleFactor = mContentsScaleFactor; - return NS_OK; -} - -NS_IMETHODIMP -ScreenProxy::GetDefaultCSSScaleFactor(double* aScaleFactor) -{ - if (!EnsureCacheIsValid()) { - return NS_ERROR_FAILURE; - } - - *aScaleFactor = mDefaultCSSScaleFactor; - return NS_OK; -} - -void -ScreenProxy::PopulateByDetails(ScreenDetails aDetails) -{ - mId = aDetails.id(); - mRect = nsIntRect(aDetails.rect()); - mRectDisplayPix = nsIntRect(aDetails.rectDisplayPix()); - mAvailRect = nsIntRect(aDetails.availRect()); - mAvailRectDisplayPix = nsIntRect(aDetails.availRectDisplayPix()); - mPixelDepth = aDetails.pixelDepth(); - mColorDepth = aDetails.colorDepth(); - mContentsScaleFactor = aDetails.contentsScaleFactor(); - mDefaultCSSScaleFactor = aDetails.defaultCSSScaleFactor(); -} - -bool -ScreenProxy::EnsureCacheIsValid() -{ - if (mCacheValid) { - return true; - } - - bool success = false; - // Kick off a synchronous IPC call to the parent to get the - // most up-to-date information. - ScreenDetails details; - Unused << mScreenManager->SendScreenRefresh(mId, &details, &success); - if (!success) { - NS_WARNING("Updating a ScreenProxy in the child process failed on parent side."); - return false; - } - - PopulateByDetails(details); - mCacheValid = true; - - InvalidateCacheOnNextTick(); - return true; -} - -void -ScreenProxy::InvalidateCacheOnNextTick() -{ - if (mCacheWillInvalidate) { - return; - } - - mCacheWillInvalidate = true; - - nsContentUtils::RunInStableState(NewRunnableMethod(this, &ScreenProxy::InvalidateCache)); -} - -void -ScreenProxy::InvalidateCache() -{ - mCacheValid = false; - mCacheWillInvalidate = false; -} - -} // namespace widget -} // namespace mozilla - diff --git a/widget/ScreenProxy.h b/widget/ScreenProxy.h deleted file mode 100644 index 1cd65d9e8c83..000000000000 --- a/widget/ScreenProxy.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */ -/* vim: set sw=4 ts=8 et tw=80 : */ -/* 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/. */ - -#ifndef mozilla_widget_ScreenProxy_h -#define mozilla_widget_ScreenProxy_h - -#include "nsBaseScreen.h" -#include "mozilla/dom/PScreenManagerChild.h" -#include "mozilla/dom/TabChild.h" - -class nsScreenManagerProxy; - -namespace mozilla { -namespace widget { - -class ScreenProxy : public nsBaseScreen -{ -public: - ScreenProxy(nsScreenManagerProxy* aScreenManager, - mozilla::dom::ScreenDetails aDetails); - ~ScreenProxy() {}; - - NS_IMETHOD GetId(uint32_t* aId) override; - - NS_IMETHOD GetRect(int32_t* aLeft, - int32_t* aTop, - int32_t* aWidth, - int32_t* aHeight) override; - NS_IMETHOD GetRectDisplayPix(int32_t* aLeft, - int32_t* aTop, - int32_t* aWidth, - int32_t* aHeight) override; - NS_IMETHOD GetAvailRect(int32_t* aLeft, - int32_t* aTop, - int32_t* aWidth, - int32_t* aHeight) override; - NS_IMETHOD GetAvailRectDisplayPix(int32_t* aLeft, - int32_t* aTop, - int32_t* aWidth, - int32_t* aHeight) override; - NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override; - NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override; - - NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) override; - NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) override; - -private: - - void PopulateByDetails(mozilla::dom::ScreenDetails aDetails); - bool EnsureCacheIsValid(); - void InvalidateCacheOnNextTick(); - void InvalidateCache(); - - double mContentsScaleFactor; - double mDefaultCSSScaleFactor; - RefPtr mScreenManager; - uint32_t mId; - int32_t mPixelDepth; - int32_t mColorDepth; - nsIntRect mRect; - nsIntRect mRectDisplayPix; - nsIntRect mAvailRect; - nsIntRect mAvailRectDisplayPix; - bool mCacheValid; - bool mCacheWillInvalidate; -}; - -} // namespace widget -} // namespace mozilla - -#endif - diff --git a/widget/android/nsScreenManagerAndroid.cpp b/widget/android/nsScreenManagerAndroid.cpp index 5bb234103682..f5a62271aa17 100644 --- a/widget/android/nsScreenManagerAndroid.cpp +++ b/widget/android/nsScreenManagerAndroid.cpp @@ -210,13 +210,6 @@ nsScreenManagerAndroid::ScreenForRect(int32_t inLeft, return GetPrimaryScreen(outScreen); } -NS_IMETHODIMP -nsScreenManagerAndroid::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen) -{ - // Not support to query non-primary screen with native widget. - return GetPrimaryScreen(outScreen); -} - NS_IMETHODIMP nsScreenManagerAndroid::GetSystemDefaultScale(float *aDefaultScale) { diff --git a/widget/cocoa/nsScreenManagerCocoa.mm b/widget/cocoa/nsScreenManagerCocoa.mm index 2b1605cc9bb1..5f627f5663ee 100644 --- a/widget/cocoa/nsScreenManagerCocoa.mm +++ b/widget/cocoa/nsScreenManagerCocoa.mm @@ -117,22 +117,3 @@ nsScreenManagerCocoa::GetSystemDefaultScale(float *aDefaultScale) *aDefaultScale = 1.0f; return NS_OK; } - -NS_IMETHODIMP -nsScreenManagerCocoa::ScreenForNativeWidget (void *nativeWidget, nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSWindow *window = static_cast(nativeWidget); - if (window) { - nsIScreen *screen = ScreenForCocoaScreen([window screen]); - *outScreen = screen; - NS_ADDREF(*outScreen); - return NS_OK; - } - - *outScreen = nullptr; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/gonk/nsScreenManagerGonk.cpp b/widget/gonk/nsScreenManagerGonk.cpp index ce11cbdc8e13..50e454599a32 100644 --- a/widget/gonk/nsScreenManagerGonk.cpp +++ b/widget/gonk/nsScreenManagerGonk.cpp @@ -831,20 +831,6 @@ nsScreenManagerGonk::ScreenForRect(int32_t inLeft, return GetPrimaryScreen(outScreen); } -NS_IMETHODIMP -nsScreenManagerGonk::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen) -{ - for (size_t i = 0; i < mScreens.Length(); i++) { - if (aWidget == mScreens[i]->GetNativeWindow()) { - NS_IF_ADDREF(*outScreen = mScreens[i].get()); - return NS_OK; - } - } - - *outScreen = nullptr; - return NS_OK; -} - NS_IMETHODIMP nsScreenManagerGonk::GetSystemDefaultScale(float *aDefaultScale) { diff --git a/widget/moz.build b/widget/moz.build index 271c23c00e0b..d503b0e95c49 100644 --- a/widget/moz.build +++ b/widget/moz.build @@ -159,14 +159,12 @@ UNIFIED_SOURCES += [ 'nsIWidgetListener.cpp', 'nsPrimitiveHelpers.cpp', 'nsPrintSettingsImpl.cpp', - 'nsScreenManagerProxy.cpp', 'nsTransferable.cpp', 'nsXPLookAndFeel.cpp', 'PuppetBidiKeyboard.cpp', 'PuppetWidget.cpp', 'Screen.cpp', 'ScreenManager.cpp', - 'ScreenProxy.cpp', 'SharedWidgetUtils.cpp', 'TextEventDispatcher.cpp', 'VsyncDispatcher.cpp', diff --git a/widget/nsContentProcessWidgetFactory.cpp b/widget/nsContentProcessWidgetFactory.cpp index 2f00f1c832ee..0e3bb06df252 100644 --- a/widget/nsContentProcessWidgetFactory.cpp +++ b/widget/nsContentProcessWidgetFactory.cpp @@ -11,8 +11,8 @@ #include "nsColorPickerProxy.h" #include "nsDragServiceProxy.h" #include "nsFilePickerProxy.h" -#include "nsScreenManagerProxy.h" #include "mozilla/widget/PuppetBidiKeyboard.h" +#include "mozilla/widget/ScreenManager.h" using namespace mozilla; using namespace mozilla::widget; @@ -23,8 +23,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPickerProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragServiceProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePickerProxy) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(PuppetBidiKeyboard) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton) NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID); NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID); @@ -42,10 +42,10 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { Module::CONTENT_PROCESS_ONLY }, { &kNS_FILEPICKER_CID, false, nullptr, nsFilePickerProxyConstructor, Module::CONTENT_PROCESS_ONLY }, - { &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerProxyConstructor, - Module::CONTENT_PROCESS_ONLY }, { &kPUPPETBIDIKEYBOARD_CID, false, NULL, PuppetBidiKeyboardConstructor, - mozilla::Module::CONTENT_PROCESS_ONLY }, + Module::CONTENT_PROCESS_ONLY }, + { &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor, + Module::CONTENT_PROCESS_ONLY }, { nullptr } }; diff --git a/widget/nsIScreen.idl b/widget/nsIScreen.idl index 7f5bb17a846b..f99e30fbea61 100644 --- a/widget/nsIScreen.idl +++ b/widget/nsIScreen.idl @@ -20,12 +20,6 @@ enum class DisplayType: int32_t { [scriptable, uuid(826e80c8-d70f-42e2-8aa9-82c05f2a370a)] interface nsIScreen : nsISupports { - /** - * A unique identifier for this device, useful for requerying - * for it via nsIScreenManager. - */ - readonly attribute unsigned long id; - /** * These report screen dimensions in (screen-specific) device pixels */ diff --git a/widget/nsIScreenManager.idl b/widget/nsIScreenManager.idl index 58695a50c661..6b7c7637b97e 100644 --- a/widget/nsIScreenManager.idl +++ b/widget/nsIScreenManager.idl @@ -18,13 +18,6 @@ interface nsIScreenManager : nsISupports // nsIScreen screenForRect ( in long left, in long top, in long width, in long height ) ; - // - // Returns the screen corresponding to the id. If no such screen exists, - // this will throw NS_ERROR_FAILURE. The id is a unique numeric value - // assigned to each screen, and is an attribute available on the nsIScreen - // interface. - nsIScreen screenForId ( in unsigned long id ) ; - // The screen with the menubar/taskbar. This shouldn't be needed very // often. readonly attribute nsIScreen primaryScreen; @@ -48,14 +41,4 @@ interface nsIScreenManager : nsISupports // to the system-wide (X11 or Gtk2) DPI value, as Firefox does not yet // honor these settings. See bug 798362 and bug 712898. readonly attribute float systemDefaultScale; - - // Returns the nsIScreen instance for the given native widget pointer; - // the pointer is specific to the particular widget implementation, - // and is generally of the same type that NS_NATIVE_WINDOW is. - [noscript] nsIScreen screenForNativeWidget ( in voidPtr nativeWidget ); }; - - -%{ C++ - -%} diff --git a/widget/nsScreenManagerProxy.cpp b/widget/nsScreenManagerProxy.cpp deleted file mode 100644 index e9dd2abe44a3..000000000000 --- a/widget/nsScreenManagerProxy.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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/. */ - -#include "mozilla/Unused.h" -#include "mozilla/dom/ContentChild.h" -#include "nsScreenManagerProxy.h" -#include "nsServiceManagerUtils.h" -#include "nsContentUtils.h" -#include "nsIAppShell.h" -#include "nsIScreen.h" -#include "nsIScreenManager.h" -#include "nsWidgetsCID.h" - -static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); - -using namespace mozilla; -using namespace mozilla::dom; -using namespace mozilla::widget; - -NS_IMPL_ISUPPORTS(nsScreenManagerProxy, nsIScreenManager) - -nsScreenManagerProxy::nsScreenManagerProxy() - : mSystemDefaultScale(1.0) - , mCacheValid(true) - , mCacheWillInvalidate(false) -{ - bool success = false; - Unused << ContentChild::GetSingleton()->SendPScreenManagerConstructor( - this, - &mSystemDefaultScale, - &success); - - if (!success) { - // We're in bad shape. We'll return the default values, but we'll basically - // be lying. - NS_WARNING("Setting up communications with the parent nsIScreenManager failed."); - } - - InvalidateCacheOnNextTick(); - - // nsScreenManagerProxy is a service, which will always have a reference - // held to it by the Component Manager once the service is requested. - // However, nsScreenManagerProxy also implements PScreenManagerChild, and - // that means that the manager of the PScreenManager protocol (PContent - // in this case) needs to know how to deallocate this actor. We AddRef here - // so that in the event that PContent tries to deallocate us either before - // or after process shutdown, we don't try to do a double-free. - AddRef(); -} - -/** - * nsIScreenManager - **/ - -NS_IMETHODIMP -nsScreenManagerProxy::GetPrimaryScreen(nsIScreen** outScreen) -{ - InvalidateCacheOnNextTick(); - - if (!mPrimaryScreen) { - ScreenDetails details; - bool success = false; - Unused << SendGetPrimaryScreen(&details, &success); - if (!success) { - return NS_ERROR_FAILURE; - } - - mPrimaryScreen = new ScreenProxy(this, details); - } - NS_ADDREF(*outScreen = mPrimaryScreen); - return NS_OK; -} - -NS_IMETHODIMP -nsScreenManagerProxy::ScreenForId(uint32_t aId, nsIScreen** outScreen) -{ - // At this time, there's no need for child processes to query for - // screens by ID. - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -nsScreenManagerProxy::ScreenForRect(int32_t inLeft, - int32_t inTop, - int32_t inWidth, - int32_t inHeight, - nsIScreen** outScreen) -{ - bool success = false; - ScreenDetails details; - Unused << SendScreenForRect(inLeft, inTop, inWidth, inHeight, &details, &success); - if (!success) { - return NS_ERROR_FAILURE; - } - - RefPtr screen = new ScreenProxy(this, details); - NS_ADDREF(*outScreen = screen); - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenManagerProxy::ScreenForNativeWidget(void* aWidget, - nsIScreen** outScreen) -{ - // Because ScreenForNativeWidget can be called numerous times - // indirectly from content via the DOM Screen API, we cache the - // results for this tick of the event loop. - TabChild* tabChild = static_cast(aWidget); - - // Enumerate the cached screen array, looking for one that has - // the TabChild that we're looking for... - for (uint32_t i = 0; i < mScreenCache.Length(); ++i) { - ScreenCacheEntry& curr = mScreenCache[i]; - if (curr.mTabChild == aWidget) { - NS_ADDREF(*outScreen = static_cast(curr.mScreenProxy)); - return NS_OK; - } - } - - // Never cached this screen, so we have to ask the parent process - // for it. - bool success = false; - ScreenDetails details; - Unused << SendScreenForBrowser(tabChild->GetTabId(), &details, &success); - if (!success) { - return NS_ERROR_FAILURE; - } - - ScreenCacheEntry newEntry; - RefPtr screen = new ScreenProxy(this, details); - - newEntry.mScreenProxy = screen; - newEntry.mTabChild = tabChild; - - mScreenCache.AppendElement(newEntry); - - NS_ADDREF(*outScreen = screen); - - InvalidateCacheOnNextTick(); - return NS_OK; -} - -NS_IMETHODIMP -nsScreenManagerProxy::GetSystemDefaultScale(float *aSystemDefaultScale) -{ - if (!EnsureCacheIsValid()) { - return NS_ERROR_FAILURE; - } - - *aSystemDefaultScale = mSystemDefaultScale; - return NS_OK; -} - -bool -nsScreenManagerProxy::EnsureCacheIsValid() -{ - if (mCacheValid) { - return true; - } - - bool success = false; - // Kick off a synchronous IPC call to the parent to get the - // most up-to-date information. - Unused << SendRefresh(&mSystemDefaultScale, &success); - if (!success) { - NS_WARNING("Refreshing nsScreenManagerProxy failed in the parent process."); - return false; - } - - mCacheValid = true; - - InvalidateCacheOnNextTick(); - return true; -} - -void -nsScreenManagerProxy::InvalidateCacheOnNextTick() -{ - if (mCacheWillInvalidate) { - return; - } - - mCacheWillInvalidate = true; - - nsContentUtils::RunInStableState(NewRunnableMethod(this, &nsScreenManagerProxy::InvalidateCache)); -} - -void -nsScreenManagerProxy::InvalidateCache() -{ - mCacheValid = false; - mCacheWillInvalidate = false; - - if (mPrimaryScreen) { - mPrimaryScreen = nullptr; - } - for (int32_t i = mScreenCache.Length() - 1; i >= 0; --i) { - mScreenCache.RemoveElementAt(i); - } -} - diff --git a/widget/nsScreenManagerProxy.h b/widget/nsScreenManagerProxy.h deleted file mode 100644 index 0897921b4d5b..000000000000 --- a/widget/nsScreenManagerProxy.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef nsScreenManagerProxy_h -#define nsScreenManagerProxy_h - -#include "nsIScreenManager.h" -#include "mozilla/dom/PScreenManagerChild.h" -#include "mozilla/dom/TabChild.h" -#include "ScreenProxy.h" - -/** - * The nsScreenManagerProxy is used by the content process to get - * information about system screens. It uses the PScreenManager protocol - * to communicate with a PScreenManagerParent to get this information, - * and also caches the information it gets back. - * - * We cache both the system screen information that nsIScreenManagers - * provide, as well as the nsIScreens that callers can query for. - * - * Both of these caches are invalidated on the next tick of the event - * loop. - */ -class nsScreenManagerProxy final : public nsIScreenManager, - public mozilla::dom::PScreenManagerChild -{ -public: - nsScreenManagerProxy(); - - NS_DECL_ISUPPORTS - NS_DECL_NSISCREENMANAGER - -private: - ~nsScreenManagerProxy() {}; - - bool EnsureCacheIsValid(); - void InvalidateCacheOnNextTick(); - void InvalidateCache(); - - float mSystemDefaultScale; - bool mCacheValid; - bool mCacheWillInvalidate; - - RefPtr mPrimaryScreen; - - // nsScreenManagerProxy caches the results to repeated calls to - // ScreenForNativeWidget, which can be triggered indirectly by - // web content using the DOM Screen API. This allows us to bypass - // a lot of IPC traffic. - // - // The cache stores ScreenProxy's mapped to the TabChild that - // asked for the ScreenForNativeWidget was called with via - // ScreenCacheEntry's. The cache is cleared on the next tick of - // the event loop. - struct ScreenCacheEntry - { - RefPtr mScreenProxy; - RefPtr mTabChild; - }; - - nsTArray mScreenCache; -}; - -#endif // nsScreenManagerProxy_h diff --git a/widget/uikit/nsScreenManager.mm b/widget/uikit/nsScreenManager.mm index 68558c1b4c20..83e3345c396e 100644 --- a/widget/uikit/nsScreenManager.mm +++ b/widget/uikit/nsScreenManager.mm @@ -117,19 +117,6 @@ UIKitScreenManager::ScreenForRect(int32_t inLeft, return GetPrimaryScreen(outScreen); } -NS_IMETHODIMP -UIKitScreenManager::ScreenForId(uint32_t id, - nsIScreen** outScreen) -{ - return GetPrimaryScreen(outScreen); -} - -NS_IMETHODIMP -UIKitScreenManager::ScreenForNativeWidget(void* aWidget, nsIScreen** outScreen) -{ - return GetPrimaryScreen(outScreen); -} - NS_IMETHODIMP UIKitScreenManager::GetSystemDefaultScale(float* aScale) { diff --git a/widget/windows/nsScreenManagerWin.cpp b/widget/windows/nsScreenManagerWin.cpp index 87d8b8516f1f..953ceea3c3b1 100644 --- a/widget/windows/nsScreenManagerWin.cpp +++ b/widget/windows/nsScreenManagerWin.cpp @@ -130,11 +130,3 @@ nsScreenManagerWin::GetSystemDefaultScale(float *aDefaultScale) *aDefaultScale = float(widget::WinUtils::LogToPhysFactor(primary)); return NS_OK; } - -NS_IMETHODIMP -nsScreenManagerWin::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen) -{ - HMONITOR mon = MonitorFromWindow((HWND) aWidget, MONITOR_DEFAULTTOPRIMARY); - *outScreen = CreateNewScreenObject(mon); - return NS_OK; -} From 1e8d2f14b91d341416c0922609ef8c5ceed5db4a Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Thu, 9 Mar 2017 19:30:53 +0800 Subject: [PATCH 36/57] Bug 1194751 - Part 6.1 change nsScreenManagerAndroid::ScreenForId to a concrete method. r=snorp nsIScreen::GetId and nsIScreenManager::ScreenForId is removed in patch part 6. These methods are still used by Fennec on Android to implement Presentation API support so I changed them to concrete methods in nsScreenAndroid and nsScreenManagerAndroid. nsScreenAndroid and nsScreenManagerAndroid does not use the generic Screen and ScreenManager class because its implementation is quite different. MozReview-Commit-ID: 4rxxIgvNxMb --HG-- extra : rebase_source : 1f8a437f6a9465bd79ce9be37c9e3de6f6d7b2fd --- widget/android/nsScreenManagerAndroid.cpp | 25 ++++++++--------------- widget/android/nsScreenManagerAndroid.h | 2 +- widget/android/nsWindow.cpp | 7 +++---- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/widget/android/nsScreenManagerAndroid.cpp b/widget/android/nsScreenManagerAndroid.cpp index f5a62271aa17..13ccbdb3d3e4 100644 --- a/widget/android/nsScreenManagerAndroid.cpp +++ b/widget/android/nsScreenManagerAndroid.cpp @@ -54,13 +54,6 @@ nsScreenAndroid::GetDensity() { return 1.0; } -NS_IMETHODIMP -nsScreenAndroid::GetId(uint32_t *outId) -{ - *outId = mId; - return NS_OK; -} - NS_IMETHODIMP nsScreenAndroid::GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) { @@ -179,24 +172,24 @@ nsScreenManagerAndroid::~nsScreenManagerAndroid() NS_IMETHODIMP nsScreenManagerAndroid::GetPrimaryScreen(nsIScreen **outScreen) { - ScreenForId(PRIMARY_SCREEN_ID, outScreen); + RefPtr screen = ScreenForId(PRIMARY_SCREEN_ID); + if (screen) { + screen.forget(outScreen); + } return NS_OK; } -NS_IMETHODIMP -nsScreenManagerAndroid::ScreenForId(uint32_t aId, - nsIScreen **outScreen) +already_AddRefed +nsScreenManagerAndroid::ScreenForId(uint32_t aId) { for (size_t i = 0; i < mScreens.Length(); ++i) { if (aId == mScreens[i]->GetId()) { - nsCOMPtr screen = (nsIScreen*) mScreens[i]; - screen.forget(outScreen); - return NS_OK; + RefPtr screen = mScreens[i]; + return screen.forget(); } } - *outScreen = nullptr; - return NS_OK; + return nullptr; } NS_IMETHODIMP diff --git a/widget/android/nsScreenManagerAndroid.h b/widget/android/nsScreenManagerAndroid.h index 7ccc91c98d9f..f462af2ea9ee 100644 --- a/widget/android/nsScreenManagerAndroid.h +++ b/widget/android/nsScreenManagerAndroid.h @@ -20,7 +20,6 @@ public: nsScreenAndroid(DisplayType aDisplayType, nsIntRect aRect); ~nsScreenAndroid(); - NS_IMETHOD GetId(uint32_t* aId) override; NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override; NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override; NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override; @@ -52,6 +51,7 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSISCREENMANAGER + already_AddRefed ScreenForId(uint32_t aId); already_AddRefed AddScreen(DisplayType aDisplayType, nsIntRect aRect = nsIntRect()); void RemoveScreen(uint32_t aScreenId); diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index c2ec68bd568b..a5f63bdc45e3 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -2342,10 +2342,9 @@ nsWindow::GetWidgetScreen() do_GetService("@mozilla.org/gfx/screenmanager;1"); MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager"); - nsCOMPtr screen; - screenMgr->ScreenForId(mScreenId, getter_AddRefs(screen)); - - return screen.forget(); + RefPtr screenMgrAndroid = + (nsScreenManagerAndroid*) screenMgr.get(); + return screenMgrAndroid->ScreenForId(mScreenId); } jni::DependentRef From e2a9b2f533973a9c0516e2e9f13a379ab4564e73 Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Thu, 9 Mar 2017 19:32:31 +0800 Subject: [PATCH 37/57] Bug 1194751 - Part 7. Implement ScreenHelperWin and delete old nsScreenManagerWin/nsScreenWin. r=jimm ScreenHelperWin is the platform dependent part of the original nsScreenManagerWin and nsScreenWin. It listens the WM_DISPLAYCHANGE message and pushes updates to ScreenManager. See patch part 4. for how ScreenManager works. MozReview-Commit-ID: 20A3ZQKmH9a --HG-- rename : widget/windows/nsScreenManagerWin.cpp => widget/windows/ScreenHelperWin.cpp rename : widget/windows/nsScreenManagerWin.h => widget/windows/ScreenHelperWin.h extra : rebase_source : a3058c237d38f72103251802ab5f5bbd672e9b70 --- widget/windows/ScreenHelperWin.cpp | 90 ++++++++++++ widget/windows/ScreenHelperWin.h | 28 ++++ widget/windows/moz.build | 3 +- widget/windows/nsAppShell.cpp | 8 ++ widget/windows/nsScreenManagerWin.cpp | 132 ----------------- widget/windows/nsScreenManagerWin.h | 50 ------- widget/windows/nsScreenWin.cpp | 199 -------------------------- widget/windows/nsScreenWin.h | 45 ------ widget/windows/nsWidgetFactory.cpp | 6 +- widget/windows/nsWindow.cpp | 7 + 10 files changed, 137 insertions(+), 431 deletions(-) create mode 100644 widget/windows/ScreenHelperWin.cpp create mode 100644 widget/windows/ScreenHelperWin.h delete mode 100644 widget/windows/nsScreenManagerWin.cpp delete mode 100644 widget/windows/nsScreenManagerWin.h delete mode 100644 widget/windows/nsScreenWin.cpp delete mode 100644 widget/windows/nsScreenWin.h diff --git a/widget/windows/ScreenHelperWin.cpp b/widget/windows/ScreenHelperWin.cpp new file mode 100644 index 000000000000..d5e322f51a96 --- /dev/null +++ b/widget/windows/ScreenHelperWin.cpp @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "ScreenHelperWin.h" + +#include "mozilla/Logging.h" +#include "nsTArray.h" +#include "WinUtils.h" + +static LazyLogModule sScreenLog("WidgetScreen"); + +namespace mozilla { +namespace widget { + +BOOL CALLBACK +CollectMonitors(HMONITOR aMon, HDC, LPRECT, LPARAM ioParam) +{ + auto screens = reinterpret_cast>*>(ioParam); + BOOL success = FALSE; + MONITORINFO info; + info.cbSize = sizeof(MONITORINFO); + success = ::GetMonitorInfoW(aMon, &info); + if (!success) { + MOZ_LOG(sScreenLog, LogLevel::Error, ("GetMonitorInfoW failed")); + return TRUE; // continue the enumeration + } + DesktopToLayoutDeviceScale contentsScaleFactor; + if (WinUtils::IsPerMonitorDPIAware()) { + contentsScaleFactor.scale = 1.0; + } else { + contentsScaleFactor.scale = WinUtils::LogToPhysFactor(aMon); + } + CSSToLayoutDeviceScale defaultCssScaleFactor(nsIWidget::DefaultScaleOverride()); + if (defaultCssScaleFactor.scale <= 0.0) { + defaultCssScaleFactor.scale = contentsScaleFactor.scale; + } + LayoutDeviceIntRect rect(info.rcMonitor.left, info.rcMonitor.top, + info.rcMonitor.right - info.rcMonitor.left, + info.rcMonitor.bottom - info.rcMonitor.top); + LayoutDeviceIntRect availRect(info.rcWork.left, info.rcWork.top, + info.rcWork.right - info.rcWork.left, + info.rcWork.bottom - info.rcWork.top); + //XXX not sure how to get this info for multiple monitors, this might be ok... + HDC hDCScreen = ::GetDC(nullptr); + NS_ASSERTION(hDCScreen,"GetDC Failure"); + uint32_t pixelDepth = ::GetDeviceCaps(hDCScreen, BITSPIXEL); + ::ReleaseDC(nullptr, hDCScreen); + if (pixelDepth == 32) { + // If a device uses 32 bits per pixel, it's still only using 8 bits + // per color component, which is what our callers want to know. + // (Some devices report 32 and some devices report 24.) + pixelDepth = 24; + } + MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f]", + rect.x, rect.y, rect.width, rect.height, + pixelDepth, defaultCssScaleFactor.scale)); + screens->AppendElement(new Screen(rect, availRect, + pixelDepth, pixelDepth, + contentsScaleFactor, defaultCssScaleFactor)); + return TRUE; +} + +float +ScreenHelperWin::GetSystemDefaultScale() +{ + HMONITOR primary = widget::WinUtils::GetPrimaryMonitor(); + return float(widget::WinUtils::LogToPhysFactor(primary)); +} + +void +ScreenHelperWin::RefreshScreens() +{ + MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refreshing screens")); + + AutoTArray, 4> screens; + BOOL result = ::EnumDisplayMonitors(nullptr, nullptr, + (MONITORENUMPROC)CollectMonitors, + (LPARAM)&screens); + if (!result) { + NS_WARNING("Unable to EnumDisplayMonitors"); + } + ScreenManager& screenManager = ScreenManager::GetSingleton(); + screenManager.Refresh(Move(screens)); +} + +} // namespace widget +} // namespace mozilla diff --git a/widget/windows/ScreenHelperWin.h b/widget/windows/ScreenHelperWin.h new file mode 100644 index 000000000000..e946c898d6ca --- /dev/null +++ b/widget/windows/ScreenHelperWin.h @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_widget_windows_ScreenHelperWin_h +#define mozilla_widget_windows_ScreenHelperWin_h + +#include "mozilla/widget/ScreenManager.h" + +namespace mozilla { +namespace widget { + +class ScreenHelperWin final : public ScreenManager::Helper +{ +public: + ScreenHelperWin() {}; + ~ScreenHelperWin() override {} + float GetSystemDefaultScale() override; + + static void RefreshScreens(); +}; + +} // namespace widget +} // namespace mozilla + +#endif // mozilla_widget_windows_ScreenHelperWin_h diff --git a/widget/windows/moz.build b/widget/windows/moz.build index 0d44c4623294..d1619f3f4e90 100644 --- a/widget/windows/moz.build +++ b/widget/windows/moz.build @@ -46,8 +46,6 @@ UNIFIED_SOURCES += [ 'nsNativeDragSource.cpp', 'nsNativeDragTarget.cpp', 'nsNativeThemeWin.cpp', - 'nsScreenManagerWin.cpp', - 'nsScreenWin.cpp', 'nsSound.cpp', 'nsToolkit.cpp', 'nsUXThemeData.cpp', @@ -56,6 +54,7 @@ UNIFIED_SOURCES += [ 'nsWindowDbg.cpp', 'nsWindowGfx.cpp', 'nsWinGesture.cpp', + 'ScreenHelperWin.cpp', 'TaskbarPreview.cpp', 'TaskbarPreviewButton.cpp', 'TaskbarTabPreview.cpp', diff --git a/widget/windows/nsAppShell.cpp b/widget/windows/nsAppShell.cpp index f345aac74518..5ff6450856bc 100644 --- a/widget/windows/nsAppShell.cpp +++ b/widget/windows/nsAppShell.cpp @@ -24,6 +24,8 @@ #include "GeckoProfiler.h" #include "nsComponentManagerUtils.h" #include "nsITimer.h" +#include "ScreenHelperWin.h" +#include "mozilla/widget/ScreenManager.h" // These are two messages that the code in winspool.drv on Windows 7 explicitly // waits for while it is pumping other Windows messages, during display of the @@ -247,6 +249,12 @@ nsAppShell::Init() nullptr); NS_ENSURE_STATE(mEventWnd); + if (XRE_IsParentProcess()) { + ScreenManager& screenManager = ScreenManager::GetSingleton(); + screenManager.SetHelper(mozilla::MakeUnique()); + ScreenHelperWin::RefreshScreens(); + } + return nsBaseAppShell::Init(); } diff --git a/widget/windows/nsScreenManagerWin.cpp b/widget/windows/nsScreenManagerWin.cpp deleted file mode 100644 index 953ceea3c3b1..000000000000 --- a/widget/windows/nsScreenManagerWin.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "nsScreenManagerWin.h" -#include "mozilla/gfx/2D.h" -#include "nsScreenWin.h" -#include "gfxWindowsPlatform.h" -#include "nsIWidget.h" -#include "WinUtils.h" - -using namespace mozilla; - -BOOL CALLBACK CountMonitors(HMONITOR, HDC, LPRECT, LPARAM ioCount); - -nsScreenManagerWin::nsScreenManagerWin() - : mNumberOfScreens(0) -{ - // nothing to do. I guess we could cache a bunch of information - // here, but we want to ask the device at runtime in case anything - // has changed. -} - - -nsScreenManagerWin::~nsScreenManagerWin() -{ -} - - -// addref, release, QI -NS_IMPL_ISUPPORTS(nsScreenManagerWin, nsIScreenManager) - - -// -// CreateNewScreenObject -// -// Utility routine. Creates a new screen object from the given device handle -// -// NOTE: For this "single-monitor" impl, we just always return the cached primary -// screen. This should change when a multi-monitor impl is done. -// -nsIScreen* -nsScreenManagerWin::CreateNewScreenObject(HMONITOR inScreen) -{ - nsIScreen* retScreen = nullptr; - - // look through our screen list, hoping to find it. If it's not there, - // add it and return the new one. - for (unsigned i = 0; i < mScreenList.Length(); ++i) { - ScreenListItem& curr = mScreenList[i]; - if (inScreen == curr.mMon) { - NS_IF_ADDREF(retScreen = curr.mScreen.get()); - return retScreen; - } - } // for each screen. - - retScreen = new nsScreenWin(inScreen); - mScreenList.AppendElement(ScreenListItem(inScreen, retScreen)); - - NS_IF_ADDREF(retScreen); - return retScreen; -} - -NS_IMETHODIMP -nsScreenManagerWin::ScreenForId(uint32_t aId, nsIScreen **outScreen) -{ - *outScreen = nullptr; - - for (unsigned i = 0; i < mScreenList.Length(); ++i) { - ScreenListItem& curr = mScreenList[i]; - uint32_t id; - nsresult rv = curr.mScreen->GetId(&id); - if (NS_SUCCEEDED(rv) && id == aId) { - NS_IF_ADDREF(*outScreen = curr.mScreen.get()); - return NS_OK; - } - } - - return NS_ERROR_FAILURE; -} - -// -// ScreenForRect -// -// Returns the screen that contains the rectangle. If the rect overlaps -// multiple screens, it picks the screen with the greatest area of intersection. -// -// The coordinates are in pixels (not twips) and in logical screen coordinates. -// -NS_IMETHODIMP -nsScreenManagerWin::ScreenForRect(int32_t inLeft, int32_t inTop, - int32_t inWidth, int32_t inHeight, - nsIScreen **outScreen) -{ - if (!(inWidth || inHeight)) { - NS_WARNING("trying to find screen for sizeless window, using primary monitor"); - *outScreen = CreateNewScreenObject(nullptr); // addrefs - return NS_OK; - } - - gfx::Rect logicalBounds(inLeft, inTop, inWidth, inHeight); - HMONITOR genScreen = widget::WinUtils::MonitorFromRect(logicalBounds); - - *outScreen = CreateNewScreenObject(genScreen); // addrefs - - return NS_OK; - -} // ScreenForRect - - -// -// GetPrimaryScreen -// -// The screen with the menubar/taskbar. This shouldn't be needed very -// often. -// -NS_IMETHODIMP -nsScreenManagerWin::GetPrimaryScreen(nsIScreen** aPrimaryScreen) -{ - *aPrimaryScreen = CreateNewScreenObject(nullptr); // addrefs - return NS_OK; - -} // GetPrimaryScreen - -NS_IMETHODIMP -nsScreenManagerWin::GetSystemDefaultScale(float *aDefaultScale) -{ - HMONITOR primary = widget::WinUtils::GetPrimaryMonitor(); - *aDefaultScale = float(widget::WinUtils::LogToPhysFactor(primary)); - return NS_OK; -} diff --git a/widget/windows/nsScreenManagerWin.h b/widget/windows/nsScreenManagerWin.h deleted file mode 100644 index c4757418a3b3..000000000000 --- a/widget/windows/nsScreenManagerWin.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef nsScreenManagerWin_h___ -#define nsScreenManagerWin_h___ - -#include "nsIScreenManager.h" - -#include -#include "nsCOMPtr.h" -#include "nsTArray.h" -#include "mozilla/Attributes.h" - -class nsIScreen; - -//------------------------------------------------------------------------ - -class ScreenListItem -{ -public: - ScreenListItem ( HMONITOR inMon, nsIScreen* inScreen ) - : mMon(inMon), mScreen(inScreen) { } ; - - HMONITOR mMon; - nsCOMPtr mScreen; -}; - -class nsScreenManagerWin final : public nsIScreenManager -{ -public: - nsScreenManagerWin ( ); - - NS_DECL_ISUPPORTS - NS_DECL_NSISCREENMANAGER - -private: - ~nsScreenManagerWin(); - - nsIScreen* CreateNewScreenObject ( HMONITOR inScreen ) ; - - uint32_t mNumberOfScreens; - - // cache the screens to avoid the memory allocations - AutoTArray mScreenList; - -}; - -#endif // nsScreenManagerWin_h___ diff --git a/widget/windows/nsScreenWin.cpp b/widget/windows/nsScreenWin.cpp deleted file mode 100644 index beacbf05fd2a..000000000000 --- a/widget/windows/nsScreenWin.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "nsScreenWin.h" -#include "nsCoord.h" -#include "nsIWidget.h" -#include "WinUtils.h" - -using namespace mozilla; - -static uint32_t sScreenId; - -nsScreenWin::nsScreenWin(HMONITOR inScreen) - : mScreen(inScreen) - , mId(++sScreenId) -{ -#ifdef DEBUG - HDC hDCScreen = ::GetDC(nullptr); - NS_ASSERTION(hDCScreen,"GetDC Failure"); - NS_ASSERTION(::GetDeviceCaps(hDCScreen, TECHNOLOGY) == DT_RASDISPLAY, "Not a display screen"); - ::ReleaseDC(nullptr,hDCScreen); -#endif - - // nothing else to do. I guess we could cache a bunch of information - // here, but we want to ask the device at runtime in case anything - // has changed. -} - - -nsScreenWin::~nsScreenWin() -{ - // nothing to see here. -} - - -NS_IMETHODIMP -nsScreenWin::GetId(uint32_t *outId) -{ - *outId = mId; - return NS_OK; -} - - -NS_IMETHODIMP -nsScreenWin::GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) -{ - BOOL success = FALSE; - if (mScreen) { - MONITORINFO info; - info.cbSize = sizeof(MONITORINFO); - success = ::GetMonitorInfoW(mScreen, &info); - if (success) { - *outLeft = info.rcMonitor.left; - *outTop = info.rcMonitor.top; - *outWidth = info.rcMonitor.right - info.rcMonitor.left; - *outHeight = info.rcMonitor.bottom - info.rcMonitor.top; - } - } - if (!success) { - HDC hDCScreen = ::GetDC(nullptr); - NS_ASSERTION(hDCScreen,"GetDC Failure"); - - *outTop = *outLeft = 0; - *outWidth = ::GetDeviceCaps(hDCScreen, HORZRES); - *outHeight = ::GetDeviceCaps(hDCScreen, VERTRES); - - ::ReleaseDC(nullptr, hDCScreen); - } - return NS_OK; - -} // GetRect - - -NS_IMETHODIMP -nsScreenWin::GetAvailRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) -{ - BOOL success = FALSE; - - if (mScreen) { - MONITORINFO info; - info.cbSize = sizeof(MONITORINFO); - success = ::GetMonitorInfoW(mScreen, &info); - if (success) { - *outLeft = info.rcWork.left; - *outTop = info.rcWork.top; - *outWidth = info.rcWork.right - info.rcWork.left; - *outHeight = info.rcWork.bottom - info.rcWork.top; - } - } - if (!success) { - RECT workArea; - ::SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0); - *outLeft = workArea.left; - *outTop = workArea.top; - *outWidth = workArea.right - workArea.left; - *outHeight = workArea.bottom - workArea.top; - } - - return NS_OK; - -} // GetAvailRect - -NS_IMETHODIMP -nsScreenWin::GetRectDisplayPix(int32_t *outLeft, int32_t *outTop, - int32_t *outWidth, int32_t *outHeight) -{ - if (widget::WinUtils::IsPerMonitorDPIAware()) { - // on per-monitor-dpi config, display pixels are device pixels - return GetRect(outLeft, outTop, outWidth, outHeight); - } - int32_t left, top, width, height; - nsresult rv = GetRect(&left, &top, &width, &height); - if (NS_FAILED(rv)) { - return rv; - } - double scaleFactor = 1.0 / widget::WinUtils::LogToPhysFactor(mScreen); - *outLeft = NSToIntRound(left * scaleFactor); - *outTop = NSToIntRound(top * scaleFactor); - *outWidth = NSToIntRound(width * scaleFactor); - *outHeight = NSToIntRound(height * scaleFactor); - return NS_OK; -} - -NS_IMETHODIMP -nsScreenWin::GetAvailRectDisplayPix(int32_t *outLeft, int32_t *outTop, - int32_t *outWidth, int32_t *outHeight) -{ - if (widget::WinUtils::IsPerMonitorDPIAware()) { - // on per-monitor-dpi config, display pixels are device pixels - return GetAvailRect(outLeft, outTop, outWidth, outHeight); - } - int32_t left, top, width, height; - nsresult rv = GetAvailRect(&left, &top, &width, &height); - if (NS_FAILED(rv)) { - return rv; - } - double scaleFactor = 1.0 / widget::WinUtils::LogToPhysFactor(mScreen); - *outLeft = NSToIntRound(left * scaleFactor); - *outTop = NSToIntRound(top * scaleFactor); - *outWidth = NSToIntRound(width * scaleFactor); - *outHeight = NSToIntRound(height * scaleFactor); - return NS_OK; -} - - -NS_IMETHODIMP -nsScreenWin :: GetPixelDepth(int32_t *aPixelDepth) -{ - //XXX not sure how to get this info for multiple monitors, this might be ok... - HDC hDCScreen = ::GetDC(nullptr); - NS_ASSERTION(hDCScreen,"GetDC Failure"); - - int32_t depth = ::GetDeviceCaps(hDCScreen, BITSPIXEL); - if (depth == 32) { - // If a device uses 32 bits per pixel, it's still only using 8 bits - // per color component, which is what our callers want to know. - // (Some devices report 32 and some devices report 24.) - depth = 24; - } - *aPixelDepth = depth; - - ::ReleaseDC(nullptr, hDCScreen); - return NS_OK; - -} // GetPixelDepth - - -NS_IMETHODIMP -nsScreenWin::GetColorDepth(int32_t *aColorDepth) -{ - return GetPixelDepth(aColorDepth); - -} // GetColorDepth - - -NS_IMETHODIMP -nsScreenWin::GetContentsScaleFactor(double *aContentsScaleFactor) -{ - if (widget::WinUtils::IsPerMonitorDPIAware()) { - *aContentsScaleFactor = 1.0; - } else { - *aContentsScaleFactor = widget::WinUtils::LogToPhysFactor(mScreen); - } - return NS_OK; -} - -NS_IMETHODIMP -nsScreenWin::GetDefaultCSSScaleFactor(double* aScaleFactor) -{ - double scale = nsIWidget::DefaultScaleOverride(); - if (scale > 0.0) { - *aScaleFactor = scale; - } else { - *aScaleFactor = widget::WinUtils::LogToPhysFactor(mScreen); - } - return NS_OK; -} diff --git a/widget/windows/nsScreenWin.h b/widget/windows/nsScreenWin.h deleted file mode 100644 index 55e6aa5e1d39..000000000000 --- a/widget/windows/nsScreenWin.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef nsScreenWin_h___ -#define nsScreenWin_h___ - -#include -#include "nsBaseScreen.h" - -//------------------------------------------------------------------------ - -class nsScreenWin final : public nsBaseScreen -{ -public: - explicit nsScreenWin ( HMONITOR inScreen ); - ~nsScreenWin(); - - NS_IMETHOD GetId(uint32_t* aId); - - // These methods return the size in device (physical) pixels - NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - - // And these methods get the screen size in 'desktop pixels' (AKA 'logical pixels') - // that are dependent on the logical DPI setting in windows - NS_IMETHOD GetRectDisplayPix(int32_t *outLeft, int32_t *outTop, - int32_t *outWidth, int32_t *outHeight); - NS_IMETHOD GetAvailRectDisplayPix(int32_t *outLeft, int32_t *outTop, - int32_t *outWidth, int32_t *outHeight); - - NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth); - NS_IMETHOD GetColorDepth(int32_t* aColorDepth); - - NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) override; - - NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) override; - -private: - HMONITOR mScreen; - uint32_t mId; -}; - -#endif // nsScreenWin_h___ diff --git a/widget/windows/nsWidgetFactory.cpp b/widget/windows/nsWidgetFactory.cpp index 7e6ffd638af1..25ace5217ca6 100644 --- a/widget/windows/nsWidgetFactory.cpp +++ b/widget/windows/nsWidgetFactory.cpp @@ -12,10 +12,10 @@ #include "nsAppShellSingleton.h" #include "mozilla/ModuleUtils.h" #include "mozilla/WidgetUtils.h" +#include "mozilla/widget/ScreenManager.h" #include "nsIServiceManager.h" #include "nsIdleServiceWin.h" #include "nsLookAndFeel.h" -#include "nsScreenManagerWin.h" #include "nsSound.h" #include "WinMouseScrollHandler.h" #include "KeyboardLayout.h" @@ -103,7 +103,7 @@ ColorPickerConstructor(nsISupports *aOuter, REFNSIID aIID, return picker->QueryInterface(aIID, aResult); } -NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerWin) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceWin, nsIdleServiceWin::GetInstance) NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard) NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper) @@ -172,7 +172,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { { &kNS_FILEPICKER_CID, false, nullptr, FilePickerConstructor, Module::MAIN_PROCESS_ONLY }, { &kNS_COLORPICKER_CID, false, nullptr, ColorPickerConstructor, Module::MAIN_PROCESS_ONLY }, { &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor, Module::ALLOW_IN_GPU_PROCESS }, - { &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerWinConstructor, + { &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor, Module::MAIN_PROCESS_ONLY }, { &kNS_GFXINFO_CID, false, nullptr, GfxInfoConstructor }, { &kNS_THEMERENDERER_CID, false, nullptr, NS_NewNativeTheme }, diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 4fbb5b06cc65..eb7b589ffa42 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -143,6 +143,7 @@ #include "nsThemeConstants.h" #include "gfxConfig.h" #include "InProcessWinCompositorWidget.h" +#include "ScreenHelperWin.h" #include "nsIGfxInfo.h" #include "nsUXThemeConstants.h" @@ -5714,6 +5715,12 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam, break; } + case WM_DISPLAYCHANGE: + { + ScreenHelperWin::RefreshScreens(); + break; + } + case WM_NCLBUTTONDBLCLK: DispatchMouseEvent(eMouseDoubleClick, 0, lParamToClient(lParam), false, WidgetMouseEvent::eLeftButton, From dbb51ca5fccfad6f5b9e4cda8a754ac570d2cffc Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Thu, 9 Mar 2017 19:34:49 +0800 Subject: [PATCH 38/57] Bug 1194751 - Part 8. Implement ScreenHelperCocoa and delete old nsScreenManagerCocoa/nsScreenCocoa. r=mstange ScreenHelperCocoa is the platform dependent part of the original nsScreenManagerCocoa and nsScreenCocoa. It registers NSApplicationDidChangeScreenParametersNotification and pushes updates to ScreenManager. See patch part 4. for how ScreenManager works. MozReview-Commit-ID: 1A5ha4Ys2dL --HG-- rename : widget/cocoa/nsScreenManagerCocoa.h => widget/cocoa/ScreenHelperCocoa.h rename : widget/cocoa/nsScreenManagerCocoa.mm => widget/cocoa/ScreenHelperCocoa.mm extra : rebase_source : c7737e18656710c36f6c04ac71a17deeca3224a5 --- widget/cocoa/ScreenHelperCocoa.h | 37 ++++++ widget/cocoa/ScreenHelperCocoa.mm | 166 +++++++++++++++++++++++++++ widget/cocoa/moz.build | 3 +- widget/cocoa/nsAppShell.mm | 7 ++ widget/cocoa/nsCocoaWindow.mm | 4 +- widget/cocoa/nsPrintOptionsX.mm | 2 + widget/cocoa/nsScreenCocoa.h | 41 ------- widget/cocoa/nsScreenCocoa.mm | 147 ------------------------ widget/cocoa/nsScreenManagerCocoa.h | 33 ------ widget/cocoa/nsScreenManagerCocoa.mm | 119 ------------------- widget/cocoa/nsWidgetFactory.mm | 7 +- 11 files changed, 218 insertions(+), 348 deletions(-) create mode 100644 widget/cocoa/ScreenHelperCocoa.h create mode 100644 widget/cocoa/ScreenHelperCocoa.mm delete mode 100644 widget/cocoa/nsScreenCocoa.h delete mode 100644 widget/cocoa/nsScreenCocoa.mm delete mode 100644 widget/cocoa/nsScreenManagerCocoa.h delete mode 100644 widget/cocoa/nsScreenManagerCocoa.mm diff --git a/widget/cocoa/ScreenHelperCocoa.h b/widget/cocoa/ScreenHelperCocoa.h new file mode 100644 index 000000000000..9195fd81b438 --- /dev/null +++ b/widget/cocoa/ScreenHelperCocoa.h @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_widget_cocoa_ScreenHelperCocoa_h +#define mozilla_widget_cocoa_ScreenHelperCocoa_h + +#include "mozilla/widget/ScreenManager.h" + +@class ScreenHelperDelegate; +@class NSScreen; + +namespace mozilla { +namespace widget { + +class ScreenHelperCocoa final : public ScreenManager::Helper +{ +public: + ScreenHelperCocoa(); + ~ScreenHelperCocoa() override; + + float GetSystemDefaultScale() override; + + void RefreshScreens(); + + static NSScreen* CocoaScreenForScreen(nsIScreen* aScreen); + +private: + ScreenHelperDelegate* mDelegate; +}; + +} // namespace widget +} // namespace mozilla + +#endif // mozilla_widget_gtk_ScreenHelperGtk_h diff --git a/widget/cocoa/ScreenHelperCocoa.mm b/widget/cocoa/ScreenHelperCocoa.mm new file mode 100644 index 000000000000..c09bc241d855 --- /dev/null +++ b/widget/cocoa/ScreenHelperCocoa.mm @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "ScreenHelperCocoa.h" + +#import + +#include "mozilla/Logging.h" +#include "nsCocoaUtils.h" +#include "nsObjCExceptions.h" + +static LazyLogModule sScreenLog("WidgetScreen"); + +@interface ScreenHelperDelegate : NSObject +{ + @private + mozilla::widget::ScreenHelperCocoa* mHelper; +} + +- (id)initWithScreenHelper:(mozilla::widget::ScreenHelperCocoa*)aScreenHelper; +- (void)didChangeScreenParameters:(NSNotification*)aNotification; +@end + +@implementation ScreenHelperDelegate +- (id)initWithScreenHelper:(mozilla::widget::ScreenHelperCocoa*)aScreenHelper +{ + if ((self = [self init])) { + mHelper = aScreenHelper; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didChangeScreenParameters:) + name:NSApplicationDidChangeScreenParametersNotification + object:nil]; + } + + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (void)didChangeScreenParameters:(NSNotification*)aNotification +{ + MOZ_LOG(sScreenLog, LogLevel::Debug, + ("Received NSApplicationDidChangeScreenParametersNotification")); + + mHelper->RefreshScreens(); +} +@end + +namespace mozilla { +namespace widget { + +ScreenHelperCocoa::ScreenHelperCocoa() +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + MOZ_LOG(sScreenLog, LogLevel::Debug, ("ScreenHelperCocoa created")); + + mDelegate = [[ScreenHelperDelegate alloc] initWithScreenHelper:this]; + + RefreshScreens(); + + NS_OBJC_END_TRY_ABORT_BLOCK; +} + +ScreenHelperCocoa::~ScreenHelperCocoa() +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + [mDelegate release]; + + NS_OBJC_END_TRY_ABORT_BLOCK; +} + +static already_AddRefed +MakeScreen(NSScreen* aScreen) +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; + + DesktopToLayoutDeviceScale contentsScaleFactor(nsCocoaUtils::GetBackingScaleFactor(aScreen)); + CSSToLayoutDeviceScale defaultCssScaleFactor(contentsScaleFactor.scale); + NSRect frame = [aScreen frame]; + LayoutDeviceIntRect rect = + nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, contentsScaleFactor.scale); + frame = [aScreen visibleFrame]; + LayoutDeviceIntRect availRect = + nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, contentsScaleFactor.scale); + NSWindowDepth depth = [aScreen depth]; + uint32_t pixelDepth = NSBitsPerPixelFromDepth(depth); + + MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f]", + rect.x, rect.y, rect.width, rect.height, + pixelDepth, contentsScaleFactor.scale)); + + RefPtr screen = new Screen(rect, availRect, + pixelDepth, pixelDepth, + contentsScaleFactor, defaultCssScaleFactor); + return screen.forget(); + + NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nullptr); +} + +float +ScreenHelperCocoa::GetSystemDefaultScale() +{ + return 1.0f; +} + +void +ScreenHelperCocoa::RefreshScreens() +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refreshing screens")); + + AutoTArray, 4> screens; + + for (NSScreen* screen in [NSScreen screens]) { + NSDictionary *desc = [screen deviceDescription]; + if ([desc objectForKey:NSDeviceIsScreen] == nil) { + continue; + } + screens.AppendElement(MakeScreen(screen)); + } + + ScreenManager& screenManager = ScreenManager::GetSingleton(); + screenManager.Refresh(Move(screens)); + + NS_OBJC_END_TRY_ABORT_BLOCK; +} + +NSScreen* +ScreenHelperCocoa::CocoaScreenForScreen(nsIScreen* aScreen) +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; + + for (NSScreen* screen in [NSScreen screens]) { + NSDictionary *desc = [screen deviceDescription]; + if ([desc objectForKey:NSDeviceIsScreen] == nil) { + continue; + } + LayoutDeviceIntRect rect; + double scale; + aScreen->GetRect(&rect.x, &rect.y, &rect.width, &rect.height); + aScreen->GetContentsScaleFactor(&scale); + NSRect frame = [screen frame]; + LayoutDeviceIntRect frameRect = + nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, scale); + if (rect == frameRect) { + return screen; + } + } + return [NSScreen mainScreen]; + + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; +} + +} // namespace widget +} // namespace mozilla diff --git a/widget/cocoa/moz.build b/widget/cocoa/moz.build index 6941ceb77163..9407117f95ed 100644 --- a/widget/cocoa/moz.build +++ b/widget/cocoa/moz.build @@ -46,8 +46,6 @@ UNIFIED_SOURCES += [ 'nsPrintDialogX.mm', 'nsPrintOptionsX.mm', 'nsPrintSettingsX.mm', - 'nsScreenCocoa.mm', - 'nsScreenManagerCocoa.mm', 'nsSound.mm', 'nsStandaloneNativeMenu.mm', 'nsSystemStatusBarCocoa.mm', @@ -56,6 +54,7 @@ UNIFIED_SOURCES += [ 'nsWindowMap.mm', 'OSXNotificationCenter.mm', 'RectTextureImage.mm', + 'ScreenHelperCocoa.mm', 'SwipeTracker.mm', 'TextInputHandler.mm', 'VibrancyManager.mm', diff --git a/widget/cocoa/nsAppShell.mm b/widget/cocoa/nsAppShell.mm index 33ce8e742aa6..9e3f63877659 100644 --- a/widget/cocoa/nsAppShell.mm +++ b/widget/cocoa/nsAppShell.mm @@ -32,6 +32,8 @@ #include "TextInputHandler.h" #include "mozilla/HangMonitor.h" #include "GeckoProfiler.h" +#include "ScreenHelperCocoa.h" +#include "mozilla/widget/ScreenManager.h" #include "pratom.h" #if !defined(RELEASE_OR_BETA) || defined(DEBUG) #include "nsSandboxViolationSink.h" @@ -306,6 +308,11 @@ nsAppShell::Init() ::CFRunLoopAddSource(mCFRunLoop, mCFRunLoopSource, kCFRunLoopCommonModes); + if (XRE_IsParentProcess()) { + ScreenManager& screenManager = ScreenManager::GetSingleton(); + screenManager.SetHelper(mozilla::MakeUnique()); + } + rv = nsBaseAppShell::Init(); if (!gAppShellMethodsSwizzled) { diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index dae21241956c..e000a114cc91 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -34,7 +34,6 @@ #include "nsIScreenManager.h" #include "nsIWidgetListener.h" #include "nsIPresShell.h" -#include "nsScreenCocoa.h" #include "gfxPlatform.h" #include "qcms.h" @@ -1398,8 +1397,7 @@ NS_IMPL_ISUPPORTS0(FullscreenTransitionData) nsCocoaWindow::PrepareForFullscreenTransition(nsISupports** aData) { nsCOMPtr widgetScreen = GetWidgetScreen(); - nsScreenCocoa* screen = static_cast(widgetScreen.get()); - NSScreen* cocoaScreen = screen->CocoaScreen(); + NSScreen* cocoaScreen = ScreenHelperCocoa::CocoaScreenForScreen(widgetScreen); NSWindow* win = [[NSWindow alloc] initWithContentRect:[cocoaScreen frame] diff --git a/widget/cocoa/nsPrintOptionsX.mm b/widget/cocoa/nsPrintOptionsX.mm index ed0dae2fe868..19cd4d5c812d 100644 --- a/widget/cocoa/nsPrintOptionsX.mm +++ b/widget/cocoa/nsPrintOptionsX.mm @@ -8,6 +8,8 @@ #include "nsIServiceManager.h" #include "nsPrintOptionsX.h" #include "nsPrintSettingsX.h" +#include "nsIWebBrowserPrint.h" +#include "nsCocoaUtils.h" using namespace mozilla::embedding; diff --git a/widget/cocoa/nsScreenCocoa.h b/widget/cocoa/nsScreenCocoa.h deleted file mode 100644 index 268d5beb0a1b..000000000000 --- a/widget/cocoa/nsScreenCocoa.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -#ifndef nsScreenCocoa_h_ -#define nsScreenCocoa_h_ - -#import - -#include "nsBaseScreen.h" - -class nsScreenCocoa : public nsBaseScreen -{ -public: - explicit nsScreenCocoa (NSScreen *screen); - ~nsScreenCocoa (); - - NS_IMETHOD GetId(uint32_t* outId); - NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth); - NS_IMETHOD GetColorDepth(int32_t* aColorDepth); - NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor); - NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) - { - return GetContentsScaleFactor(aScaleFactor); - } - - NSScreen *CocoaScreen() { return mScreen; } - -private: - CGFloat BackingScaleFactor(); - - NSScreen *mScreen; - uint32_t mId; -}; - -#endif // nsScreenCocoa_h_ diff --git a/widget/cocoa/nsScreenCocoa.mm b/widget/cocoa/nsScreenCocoa.mm deleted file mode 100644 index 08905bf0ad29..000000000000 --- a/widget/cocoa/nsScreenCocoa.mm +++ /dev/null @@ -1,147 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -#include "nsScreenCocoa.h" -#include "nsObjCExceptions.h" -#include "nsCocoaUtils.h" - -static uint32_t sScreenId = 0; - -nsScreenCocoa::nsScreenCocoa (NSScreen *screen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mScreen = [screen retain]; - mId = ++sScreenId; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsScreenCocoa::~nsScreenCocoa () -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mScreen release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetId(uint32_t *outId) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - *outId = mId; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetRect(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen frame]; - - mozilla::LayoutDeviceIntRect r = - nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, BackingScaleFactor()); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetAvailRect(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen visibleFrame]; - - mozilla::LayoutDeviceIntRect r = - nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, BackingScaleFactor()); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen frame]; - - mozilla::DesktopIntRect r = nsCocoaUtils::CocoaRectToGeckoRect(frame); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetAvailRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen visibleFrame]; - - mozilla::DesktopIntRect r = nsCocoaUtils::CocoaRectToGeckoRect(frame); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetPixelDepth(int32_t *aPixelDepth) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSWindowDepth depth = [mScreen depth]; - int bpp = NSBitsPerPixelFromDepth(depth); - - *aPixelDepth = bpp; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenCocoa::GetColorDepth(int32_t *aColorDepth) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSWindowDepth depth = [mScreen depth]; - int bpp = NSBitsPerPixelFromDepth (depth); - - *aColorDepth = bpp; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenCocoa::GetContentsScaleFactor(double *aContentsScaleFactor) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - *aContentsScaleFactor = (double) BackingScaleFactor(); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -CGFloat -nsScreenCocoa::BackingScaleFactor() -{ - return nsCocoaUtils::GetBackingScaleFactor(mScreen); -} diff --git a/widget/cocoa/nsScreenManagerCocoa.h b/widget/cocoa/nsScreenManagerCocoa.h deleted file mode 100644 index 61a059d97768..000000000000 --- a/widget/cocoa/nsScreenManagerCocoa.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -#ifndef nsScreenManagerCocoa_h_ -#define nsScreenManagerCocoa_h_ - -#import - -#include "mozilla/RefPtr.h" -#include "nsTArray.h" -#include "nsIScreenManager.h" -#include "nsScreenCocoa.h" - -class nsScreenManagerCocoa : public nsIScreenManager -{ -public: - nsScreenManagerCocoa(); - - NS_DECL_ISUPPORTS - NS_DECL_NSISCREENMANAGER - -protected: - virtual ~nsScreenManagerCocoa(); - -private: - - nsScreenCocoa *ScreenForCocoaScreen(NSScreen *screen); - nsTArray< RefPtr > mScreenList; -}; - -#endif // nsScreenManagerCocoa_h_ diff --git a/widget/cocoa/nsScreenManagerCocoa.mm b/widget/cocoa/nsScreenManagerCocoa.mm deleted file mode 100644 index 5f627f5663ee..000000000000 --- a/widget/cocoa/nsScreenManagerCocoa.mm +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -#include "nsScreenManagerCocoa.h" -#include "nsObjCExceptions.h" -#include "nsCOMPtr.h" -#include "nsCocoaUtils.h" - -using namespace mozilla; - -NS_IMPL_ISUPPORTS(nsScreenManagerCocoa, nsIScreenManager) - -nsScreenManagerCocoa::nsScreenManagerCocoa() -{ -} - -nsScreenManagerCocoa::~nsScreenManagerCocoa() -{ -} - -nsScreenCocoa* -nsScreenManagerCocoa::ScreenForCocoaScreen(NSScreen *screen) -{ - for (uint32_t i = 0; i < mScreenList.Length(); ++i) { - nsScreenCocoa* sc = mScreenList[i]; - if (sc->CocoaScreen() == screen) { - // doesn't addref - return sc; - } - } - - // didn't find it; create and insert - RefPtr sc = new nsScreenCocoa(screen); - mScreenList.AppendElement(sc); - return sc.get(); -} - -NS_IMETHODIMP -nsScreenManagerCocoa::ScreenForId (uint32_t aId, nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT - - *outScreen = nullptr; - - for (uint32_t i = 0; i < mScreenList.Length(); ++i) { - nsScreenCocoa* sc = mScreenList[i]; - uint32_t id; - nsresult rv = sc->GetId(&id); - - if (NS_SUCCEEDED(rv) && id == aId) { - *outScreen = sc; - NS_ADDREF(*outScreen); - return NS_OK; - } - } - - return NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::ScreenForRect (int32_t aX, int32_t aY, - int32_t aWidth, int32_t aHeight, - nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSEnumerator *screenEnum = [[NSScreen screens] objectEnumerator]; - NSRect inRect = - nsCocoaUtils::GeckoRectToCocoaRect(DesktopIntRect(aX, aY, - aWidth, aHeight)); - NSScreen *screenWindowIsOn = [NSScreen mainScreen]; - float greatestArea = 0; - - while (NSScreen *screen = [screenEnum nextObject]) { - NSDictionary *desc = [screen deviceDescription]; - if ([desc objectForKey:NSDeviceIsScreen] == nil) - continue; - - NSRect r = NSIntersectionRect([screen frame], inRect); - float area = r.size.width * r.size.height; - if (area > greatestArea) { - greatestArea = area; - screenWindowIsOn = screen; - } - } - - *outScreen = ScreenForCocoaScreen(screenWindowIsOn); - NS_ADDREF(*outScreen); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::GetPrimaryScreen (nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // the mainScreen is the screen with the "key window" (focus, I assume?) - NSScreen *sc = [[NSScreen screens] objectAtIndex:0]; - - *outScreen = ScreenForCocoaScreen(sc); - NS_ADDREF(*outScreen); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::GetSystemDefaultScale(float *aDefaultScale) -{ - *aDefaultScale = 1.0f; - return NS_OK; -} diff --git a/widget/cocoa/nsWidgetFactory.mm b/widget/cocoa/nsWidgetFactory.mm index 3bddaf95cea4..f0d86809b23e 100644 --- a/widget/cocoa/nsWidgetFactory.mm +++ b/widget/cocoa/nsWidgetFactory.mm @@ -32,13 +32,14 @@ #include "NativeKeyBindings.h" #include "OSXNotificationCenter.h" -#include "nsScreenManagerCocoa.h" #include "nsDeviceContextSpecX.h" #include "nsPrintOptionsX.h" #include "nsPrintDialogX.h" #include "nsPrintSession.h" #include "nsToolkitCompsCID.h" +#include "mozilla/widget/ScreenManager.h" + using namespace mozilla; using namespace mozilla::widget; @@ -52,12 +53,12 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard) NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerCocoa) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecX) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintOptionsX, Init) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintDialogServiceX, Init) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceX, nsIdleServiceX::GetInstance) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(OSXNotificationCenter, Init) #include "nsMenuBarX.h" @@ -138,7 +139,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { { &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor, mozilla::Module::MAIN_PROCESS_ONLY }, { &kNS_THEMERENDERER_CID, false, NULL, nsNativeThemeCocoaConstructor }, - { &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerCocoaConstructor, + { &kNS_SCREENMANAGER_CID, false, NULL, ScreenManagerConstructor, mozilla::Module::MAIN_PROCESS_ONLY }, { &kNS_DEVICE_CONTEXT_SPEC_CID, false, NULL, nsDeviceContextSpecXConstructor }, { &kNS_PRINTSESSION_CID, false, NULL, nsPrintSessionConstructor }, From 7f797ee3543d03a8e7c940690d94f40b705bbeb1 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Mon, 27 Mar 2017 14:58:30 +1100 Subject: [PATCH 39/57] Bug 1341102 - Update mochitest expectation. --- layout/style/test/stylo-failures.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/layout/style/test/stylo-failures.md b/layout/style/test/stylo-failures.md index 37bbbc2538af..4317a5791d91 100644 --- a/layout/style/test/stylo-failures.md +++ b/layout/style/test/stylo-failures.md @@ -365,9 +365,6 @@ to mochitest command. * test_variables.html `--weird`: name of custom property is not escaped properly servo/servo#15399 [1] * image-layer values should omit some of its parts when they are initial servo/servo#15951 * test_shorthand_property_getters.html `background` [2] - * counter-{reset,increment} doesn't serialize none servo/servo#15977 - * test_value_storage.html `counter-reset` [2] - * test_value_storage.html `counter-increment` [2] * :not(*) doesn't serialize properly servo/servo#16017 * test_selectors.html `:not()` [8] * ... `:not(html|)` [1] @@ -410,7 +407,6 @@ to mochitest command. * ... `perspective'`: servo/servo#15449 [20] * ... `'text-shadow'`: third length of text-shadow servo/servo#15999 [2] * ... `flex-basis`: servo/servo#15902 [6] - * ... `border-image-slice`: servo/servo#15339 [2] * Quirks mode support * hashless color servo/servo#15341 * test_property_syntax_errors.html `color: 000000` [22] From 42108a35bc6a1d73891a02af7a0e247dcc0f04c1 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Mon, 6 Mar 2017 16:45:35 +0000 Subject: [PATCH 40/57] Bug 1344748 - Remove B2G offline management from Marionette; r=maja_zf MozReview-Commit-ID: 68iUhwT7xdv --HG-- extra : rebase_source : 079cff5ead7887bf5708b5f01ad48769a0c7d4c7 --- testing/marionette/server.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/testing/marionette/server.js b/testing/marionette/server.js index 0d8a7bf23d0c..3b816d7b1954 100644 --- a/testing/marionette/server.js +++ b/testing/marionette/server.js @@ -26,7 +26,6 @@ const logger = Log.repository.getLogger("Marionette"); this.EXPORTED_SYMBOLS = ["MarionetteServer"]; const CONTENT_LISTENER_PREF = "marionette.contentListener"; -const MANAGE_OFFLINE_STATUS_PREF = "network.gonk.manage-offline-status"; /** * Bootstraps Marionette and handles incoming client connections. @@ -59,19 +58,8 @@ this.MarionetteServer = function (port, forceLocal) { * A driver instance. */ MarionetteServer.prototype.driverFactory = function() { - let appName = isMulet() ? "B2G" : Services.appinfo.name; - let bypassOffline = false; - Preferences.set(CONTENT_LISTENER_PREF, false); - - if (bypassOffline) { - logger.debug("Bypassing offline status"); - Preferences.set(MANAGE_OFFLINE_STATUS_PREF, false); - Services.io.manageOfflineStatus = false; - Services.io.offline = false; - } - - return new GeckoDriver(appName, this); + return new GeckoDriver(Services.appinfo.name, this); }; MarionetteServer.prototype.__defineSetter__("acceptConnections", function (value) { @@ -139,6 +127,3 @@ MarionetteServer.prototype.onConnectionClosed = function (conn) { logger.debug(`Closed connection ${id}`); }; -function isMulet() { - return Preferences.get("b2g.is_mulet", false); -} From a8f2ccfaf8836a1d268418fe8ae6406f334bd9b4 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Mon, 6 Mar 2017 16:47:38 +0000 Subject: [PATCH 41/57] Bug 1344748 - Set recommended prefs when Marionette starts; r=automatedtester,maja_zf,whimboo This makes the Marionette server itself set a long list of recommended automation preferences when it starts up, and reset those it changed when stopping. Preferences used in automation are currently written to the Firefox profile before Firefox starts, but after a closer examination of the preferences, it is thought that many of them can be set at runtime. There is a subset of preferences that are checked on startup and which must be set in the profile. These are clearly called out in the comments. We still set them at runtime, since we foresee a future where it will be possible to attach an existing Firefox session to geckodriver, and many of the prefs can also be checked at runtime during the course of that automation session. For example, if we would not set the "app.update.auto" preference in such a runtime, opening the About dialogue would cause a forced update of Firefox. This is not desirable when the browser is under Marionette control. When the Marionette server is stopped, the altered preferences are reset and the browser session's state is returned to its pre-existing condition. This change does not mean it is dangerous or wrong for consumers to write their own preferences to the profile. Any preferences written to the profile will take precedence over this set of recommended preferences. If the recommended Marionette preference has a user-defined value (i.e. it is written to the profile before starting up or has manually changed), that user-set value is preferred. The list of preferences in this file is the authorative reference of recommended preferences for using Marionette in automation. They have been gathered from geckoinstance.py and geckodriver. MozReview-Commit-ID: INHSQRg2XjF --HG-- extra : rebase_source : e1684133d287d2891feaa52ae4d267e8df4fa8e2 --- testing/marionette/server.js | 242 ++++++++++++++++++++++++++++++++++- 1 file changed, 241 insertions(+), 1 deletion(-) diff --git a/testing/marionette/server.js b/testing/marionette/server.js index 3b816d7b1954..2a4651872905 100644 --- a/testing/marionette/server.js +++ b/testing/marionette/server.js @@ -27,6 +27,228 @@ this.EXPORTED_SYMBOLS = ["MarionetteServer"]; const CONTENT_LISTENER_PREF = "marionette.contentListener"; +// Marionette sets preferences recommended for automation when it starts, +// unless |marionette.prefs.recommended| has been set to false. +// Where noted, some prefs should also be set in the profile passed to +// Marionette to prevent them from affecting startup, since some of these +// are checked before Marionette initialises. +const RECOMMENDED_PREFS = new Map([ + + // Disable automatic downloading of new releases. + // + // This should also be set in the profile prior to starting Firefox, + // as it is picked up at runtime. + ["app.update.auto", false], + + // Disable automatically upgrading Firefox. + // + // This should also be set in the profile prior to starting Firefox, + // as it is picked up at runtime. + ["app.update.enabled", false], + + // Increase the APZ content response timeout in tests to 1 minute. + // This is to accommodate the fact that test environments tends to be + // slower than production environments (with the b2g emulator being + // the slowest of them all), resulting in the production timeout value + // sometimes being exceeded and causing false-positive test failures. + // + // (bug 1176798, bug 1177018, bug 1210465) + ["apz.content_response_timeout", 60000], + + // Indicate that the download panel has been shown once so that + // whichever download test runs first doesn't show the popup + // inconsistently. + ["browser.download.panel.shown", true], + + // Do not show the EULA notification. + // + // This should also be set in the profile prior to starting Firefox, + // as it is picked up at runtime. + ["browser.EULA.override", true], + + // Turn off about:newtab and make use of about:blank instead for new + // opened tabs. + // + // This should also be set in the profile prior to starting Firefox, + // as it is picked up at runtime. + ["browser.newtabpage.enabled", false], + + // Assume the about:newtab page's intro panels have been shown to not + // depend on which test runs first and happens to open about:newtab + ["browser.newtabpage.introShown", true], + + // Never start the browser in offline mode + // + // This should also be set in the profile prior to starting Firefox, + // as it is picked up at runtime. + ["browser.offline", false], + + // Background thumbnails in particular cause grief, and disabling + // thumbnails in general cannot hurt + ["browser.pagethumbnails.capturing_disabled", true], + + // Avoid performing Reader Mode intros during tests + ["browser.reader.detectedFirstArticle", true], + + // Disable safebrowsing components. + // + // These should also be set in the profile prior to starting Firefox, + // as it is picked up at runtime. + ["browser.safebrowsing.blockedURIs.enabled", false], + ["browser.safebrowsing.downloads.enabled", false], + ["browser.safebrowsing.enabled", false], + ["browser.safebrowsing.forbiddenURIs.enabled", false], + ["browser.safebrowsing.malware.enabled", false], + ["browser.safebrowsing.phishing.enabled", false], + + // Disable updates to search engines. + // + // Should be set in profile. + ["browser.search.update", false], + + // Do not restore the last open set of tabs if the browser has crashed + ["browser.sessionstore.resume_from_crash", false], + + // Don't check for the default web browser during startup. + // + // These should also be set in the profile prior to starting Firefox, + // as it is picked up at runtime. + ["browser.shell.checkDefaultBrowser", false], + + // Start with a blank page (about:blank) + ["browser.startup.page", 0], + + // Disable tab animation + ["browser.tabs.animate", false], + + // Do not allow background tabs to be zombified, otherwise for tests + // that open additional tabs, the test harness tab itself might get + // unloaded + ["browser.tabs.disableBackgroundZombification", false], + + // Do not warn when closing all other open tabs + ["browser.tabs.warnOnCloseOtherTabs", false], + + // Do not warn when multiple tabs will be opened + ["browser.tabs.warnOnOpen", false], + + // Disable first run splash page on Windows 10 + ["browser.usedOnWindows10.introURL", ""], + + // Disable the UI tour. + // + // Should be set in profile. + ["browser.uitour.enabled", false], + + // Do not show datareporting policy notifications which can + // interfere with tests + ["datareporting.healthreport.about.reportUrl", "http://%(server)s/dummy/abouthealthreport/"], + ["datareporting.healthreport.documentServerURI", "http://%(server)s/dummy/healthreport/"], + ["datareporting.healthreport.logging.consoleEnabled", false], + ["datareporting.healthreport.service.enabled", false], + ["datareporting.healthreport.service.firstRun", false], + ["datareporting.healthreport.uploadEnabled", false], + ["datareporting.policy.dataSubmissionEnabled", false], + ["datareporting.policy.dataSubmissionPolicyAccepted", false], + ["datareporting.policy.dataSubmissionPolicyBypassNotification", true], + + // Disable popup-blocker + ["dom.disable_open_during_load", false], + + // Disable the ProcessHangMonitor + ["dom.ipc.reportProcessHangs", false], + + // Disable slow script dialogues + ["dom.max_chrome_script_run_time", 0], + ["dom.max_script_run_time", 0], + + // Only load extensions from the application and user profile + // AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION + // + // Should be set in profile. + ["extensions.autoDisableScopes", 0], + ["extensions.enabledScopes", 5], + + // Do not block add-ons for e10s + ["extensions.e10sBlocksEnabling", false], + + // Disable metadata caching for installed add-ons by default + ["extensions.getAddons.cache.enabled", false], + + // Disable intalling any distribution extensions or add-ons. + // Should be set in profile. + ["extensions.installDistroAddons", false], + ["extensions.showMismatchUI", false], + + // Turn off extension updates so they do not bother tests + ["extensions.update.enabled", false], + ["extensions.update.notifyUser", false], + + // Make sure opening about:addons will not hit the network + ["extensions.webservice.discoverURL", "http://%(server)s/dummy/discoveryURL"], + + // Allow the application to have focus even it runs in the background + ["focusmanager.testmode", true], + + // Disable useragent updates + ["general.useragent.updates.enabled", false], + + // Always use network provider for geolocation tests so we bypass the + // macOS dialog raised by the corelocation provider + ["geo.provider.testing", true], + + // Do not scan Wifi + ["geo.wifi.scan", false], + + // No hang monitor + ["hangmonitor.timeout", 0], + + // Show chrome errors and warnings in the error console + ["javascript.options.showInConsole", true], + + // Make sure the disk cache doesn't get auto disabled + ["network.http.bypass-cachelock-threshold", 200000], + + // Do not prompt for temporary redirects + ["network.http.prompt-temp-redirect", false], + + // Disable speculative connections so they are not reported as leaking + // when they are hanging around + ["network.http.speculative-parallel-limit", 0], + + // Do not automatically switch between offline and online + ["network.manage-offline-status", false], + + // Make sure SNTP requests do not hit the network + ["network.sntp.pools", "%(server)s"], + + // Local documents have access to all other local documents, + // including directory listings + ["security.fileuri.strict_origin_policy", false], + + // Tests do not wait for the notification button security delay + ["security.notification_enable_delay", 0], + + // Ensure blocklist updates do not hit the network + ["services.settings.server", "http://%(server)s/dummy/blocklist/"], + + // Do not automatically fill sign-in forms with known usernames and + // passwords + ["signon.autofillForms", false], + + // Disable password capture, so that tests that include forms are not + // influenced by the presence of the persistent doorhanger notification + ["signon.rememberSignons", false], + + // Disable first-run welcome page + ["startup.homepage_welcome_url", "about:blank"], + ["startup.homepage_welcome_url.additional", ""], + + // Prevent starting into safe mode after application crashes + ["toolkit.startup.max_resumed_crashes", -1], + +]); + /** * Bootstraps Marionette and handles incoming client connections. * @@ -47,6 +269,7 @@ this.MarionetteServer = function (port, forceLocal) { this.nextConnId = 0; this.alive = false; this._acceptConnections = false; + this.alteredPrefs = new Set(); }; /** @@ -76,12 +299,23 @@ MarionetteServer.prototype.start = function() { if (this.alive) { return; } + + // set recommended preferences if they are not already user-defined + for (let [k, v] of RECOMMENDED_PREFS) { + if (!Preferences.isSet(k)) { + logger.debug(`Setting recommended pref ${k} to ${v}`); + Preferences.set(k, v); + this.alteredPrefs.add(k); + } + } + let flags = Ci.nsIServerSocket.KeepWhenOffline; if (this.forceLocal) { flags |= Ci.nsIServerSocket.LoopbackOnly; } this.listener = new ServerSocket(this.port, flags, 1); this.listener.asyncListen(this); + this.alive = true; this._acceptConnections = true; }; @@ -90,7 +324,14 @@ MarionetteServer.prototype.stop = function() { if (!this.alive) { return; } + + for (let k of this.alteredPrefs) { + logger.debug(`Resetting recommended pref ${k}`); + Preferences.reset(k); + } this.closeListener(); + + this.alteredPrefs.clear(); this.alive = false; this._acceptConnections = false; }; @@ -126,4 +367,3 @@ MarionetteServer.prototype.onConnectionClosed = function (conn) { delete this.conns[id]; logger.debug(`Closed connection ${id}`); }; - From 55ec9308b0edd69e68c2fade68219e8f3b4f5c94 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Mon, 6 Mar 2017 17:09:07 +0000 Subject: [PATCH 42/57] Bug 1344748 - Make testing/marionette/server.js a class; r=maja_zf,whimboo No functional changes apart from class'ifying the file and harmonising the export symbol with the rest of the Marionette code base by renaming the MarionetteServer class to server.TCPListener. MozReview-Commit-ID: 8WJKoprGGvr --HG-- extra : rebase_source : 1f706a0f5e4c9fdccac90bfc14f767763ec85257 --- testing/marionette/components/marionette.js | 2 +- testing/marionette/server.js | 191 ++++++++++---------- tools/lint/eslint/modules.json | 2 +- 3 files changed, 99 insertions(+), 96 deletions(-) diff --git a/testing/marionette/components/marionette.js b/testing/marionette/components/marionette.js index 38e88cdf964e..ce89289062f7 100644 --- a/testing/marionette/components/marionette.js +++ b/testing/marionette/components/marionette.js @@ -241,7 +241,7 @@ MarionetteComponent.prototype.init = function() { let s; try { Cu.import("chrome://marionette/content/server.js"); - s = new MarionetteServer(port, forceLocal); + s = new server.TCPListener(port, forceLocal); s.start(); this.logger.info(`Listening on port ${s.port}`); } catch (e) { diff --git a/testing/marionette/server.js b/testing/marionette/server.js index 2a4651872905..85fb0c116f2d 100644 --- a/testing/marionette/server.js +++ b/testing/marionette/server.js @@ -23,7 +23,8 @@ loader.loadSubScript("resource://devtools/shared/transport/transport.js"); const logger = Log.repository.getLogger("Marionette"); -this.EXPORTED_SYMBOLS = ["MarionetteServer"]; +this.EXPORTED_SYMBOLS = ["server"]; +this.server = {}; const CONTENT_LISTENER_PREF = "marionette.contentListener"; @@ -255,115 +256,117 @@ const RECOMMENDED_PREFS = new Map([ * Once started, it opens a TCP socket sporting the debugger transport * protocol on the provided port. For every new client a Dispatcher is * created. - * - * @param {number} port - * Port for server to listen to. - * @param {boolean} forceLocal - * Listen only to connections from loopback if true. If false, - * accept all connections. */ -this.MarionetteServer = function (port, forceLocal) { - this.port = port; - this.forceLocal = forceLocal; - this.conns = {}; - this.nextConnId = 0; - this.alive = false; - this._acceptConnections = false; - this.alteredPrefs = new Set(); -}; - -/** - * Function produces a GeckoDriver. - * - * Determines application nameto initialise the driver with. - * - * @return {GeckoDriver} - * A driver instance. - */ -MarionetteServer.prototype.driverFactory = function() { - Preferences.set(CONTENT_LISTENER_PREF, false); - return new GeckoDriver(Services.appinfo.name, this); -}; - -MarionetteServer.prototype.__defineSetter__("acceptConnections", function (value) { - if (!value) { - logger.info("New connections will no longer be accepted"); - } else { - logger.info("New connections are accepted again"); +server.TCPListener = class { + /** + * @param {number} port + * Port for server to listen to. + * @param {boolean} forceLocal + * Listen only to connections from loopback if true. If false, + * accept all connections. + */ + constructor (port, forceLocal) { + this.port = port; + this.forceLocal = forceLocal; + this.conns = {}; + this.nextConnId = 0; + this.alive = false; + this._acceptConnections = false; + this.alteredPrefs = new Set(); } - this._acceptConnections = value; -}); - -MarionetteServer.prototype.start = function() { - if (this.alive) { - return; + /** + * Function produces a GeckoDriver. + * + * Determines application nameto initialise the driver with. + * + * @return {GeckoDriver} + * A driver instance. + */ + driverFactory () { + Preferences.set(CONTENT_LISTENER_PREF, false); + return new GeckoDriver(Services.appinfo.name, this); } - // set recommended preferences if they are not already user-defined - for (let [k, v] of RECOMMENDED_PREFS) { - if (!Preferences.isSet(k)) { - logger.debug(`Setting recommended pref ${k} to ${v}`); - Preferences.set(k, v); - this.alteredPrefs.add(k); + set acceptConnections (value) { + if (!value) { + logger.info("New connections will no longer be accepted"); + } else { + logger.info("New connections are accepted again"); } + + this._acceptConnections = value; } - let flags = Ci.nsIServerSocket.KeepWhenOffline; - if (this.forceLocal) { - flags |= Ci.nsIServerSocket.LoopbackOnly; - } - this.listener = new ServerSocket(this.port, flags, 1); - this.listener.asyncListen(this); + start () { + if (this.alive) { + return; + } - this.alive = true; - this._acceptConnections = true; -}; + // set recommended preferences if they are not already user-defined + for (let [k, v] of RECOMMENDED_PREFS) { + if (!Preferences.isSet(k)) { + logger.debug(`Setting recommended pref ${k} to ${v}`); + Preferences.set(k, v); + this.alteredPrefs.add(k); + } + } -MarionetteServer.prototype.stop = function() { - if (!this.alive) { - return; + let flags = Ci.nsIServerSocket.KeepWhenOffline; + if (this.forceLocal) { + flags |= Ci.nsIServerSocket.LoopbackOnly; + } + this.listener = new ServerSocket(this.port, flags, 1); + this.listener.asyncListen(this); + + this.alive = true; + this._acceptConnections = true; } - for (let k of this.alteredPrefs) { - logger.debug(`Resetting recommended pref ${k}`); - Preferences.reset(k); - } - this.closeListener(); + stop () { + if (!this.alive) { + return; + } - this.alteredPrefs.clear(); - this.alive = false; - this._acceptConnections = false; -}; + for (let k of this.alteredPrefs) { + logger.debug(`Resetting recommended pref ${k}`); + Preferences.reset(k); + } + this.closeListener(); -MarionetteServer.prototype.closeListener = function() { - this.listener.close(); - this.listener = null; -}; - -MarionetteServer.prototype.onSocketAccepted = function ( - serverSocket, clientSocket) { - if (!this._acceptConnections) { - logger.warn("New connections are currently not accepted"); - return; + this.alteredPrefs.clear(); + this.alive = false; + this._acceptConnections = false; } - let input = clientSocket.openInputStream(0, 0, 0); - let output = clientSocket.openOutputStream(0, 0, 0); - let transport = new DebuggerTransport(input, output); - let connId = "conn" + this.nextConnId++; + closeListener () { + this.listener.close(); + this.listener = null; + } - let dispatcher = new Dispatcher(connId, transport, this.driverFactory.bind(this)); - dispatcher.onclose = this.onConnectionClosed.bind(this); - this.conns[connId] = dispatcher; + onSocketAccepted (serverSocket, clientSocket) { + if (!this._acceptConnections) { + logger.warn("New connections are currently not accepted"); + return; + } - logger.debug(`Accepted connection ${connId} from ${clientSocket.host}:${clientSocket.port}`); - dispatcher.sayHello(); - transport.ready(); -}; - -MarionetteServer.prototype.onConnectionClosed = function (conn) { - let id = conn.connId; - delete this.conns[id]; - logger.debug(`Closed connection ${id}`); + let input = clientSocket.openInputStream(0, 0, 0); + let output = clientSocket.openOutputStream(0, 0, 0); + let transport = new DebuggerTransport(input, output); + let connId = "conn" + this.nextConnId++; + + let dispatcher = new Dispatcher(connId, transport, this.driverFactory.bind(this)); + dispatcher.onclose = this.onConnectionClosed.bind(this); + this.conns[connId] = dispatcher; + + logger.debug(`Accepted connection ${connId} from ${clientSocket.host}:${clientSocket.port}`); + dispatcher.sayHello(); + transport.ready(); + } + + onConnectionClosed (conn) { + let id = conn.connId; + delete this.conns[id]; + logger.debug(`Closed connection ${id}`); + } }; diff --git a/tools/lint/eslint/modules.json b/tools/lint/eslint/modules.json index a477c0b834a6..3eb462d96de7 100644 --- a/tools/lint/eslint/modules.json +++ b/tools/lint/eslint/modules.json @@ -193,7 +193,7 @@ "require.js": ["require"], "RTCStatsReport.jsm": ["convertToRTCStatsReport"], "scratchpad-manager.jsm": ["ScratchpadManager"], - "server.js": ["MarionetteServer"], + "server.js": ["server"], "service.js": ["Service"], "SharedPromptUtils.jsm": ["PromptUtils", "EnableDelayHelper"], "ShutdownLeaksCollector.jsm": ["ContentCollector"], From 83e7098d6d89bcf5a8bd56021c4a345aacec3d37 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Mon, 6 Mar 2017 17:39:42 +0000 Subject: [PATCH 43/57] Bug 1344748 - Merge dispatcher into server.js; r=maja_zf Merges testing/marionette/dispatcher.js into testing/marionette/server.js and renames it server.TCPConnection. The rationale behind this change is that the current dispatcher is not a single entity to which incoming requests are dispatched. The old organisation might make sense if this was an HTTP server where all connections are transitive and it didn't hold any connection details, however the dispatcher is in effect a representation of a client socket connection. Since the module is not used elsewhere, it makes sense to pair it with the existing server.TCPListener class. MozReview-Commit-ID: 2HF35OiP6AY --HG-- extra : rebase_source : 188bbc23a128642c1127694714e7fca4192827c9 --- testing/marionette/dispatcher.js | 228 --------------------------- testing/marionette/jar.mn | 1 - testing/marionette/server.js | 258 ++++++++++++++++++++++++++++--- 3 files changed, 235 insertions(+), 252 deletions(-) delete mode 100644 testing/marionette/dispatcher.js diff --git a/testing/marionette/dispatcher.js b/testing/marionette/dispatcher.js deleted file mode 100644 index 1f09ef8bf896..000000000000 --- a/testing/marionette/dispatcher.js +++ /dev/null @@ -1,228 +0,0 @@ -/* 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 strict"; - -const {interfaces: Ci, utils: Cu} = Components; - -Cu.import("resource://gre/modules/Log.jsm"); -Cu.import("resource://gre/modules/Preferences.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); - -Cu.import("chrome://marionette/content/assert.js"); -Cu.import("chrome://marionette/content/driver.js"); -Cu.import("chrome://marionette/content/error.js"); -Cu.import("chrome://marionette/content/message.js"); - -this.EXPORTED_SYMBOLS = ["Dispatcher"]; - -const PROTOCOL_VERSION = 3; - -const logger = Log.repository.getLogger("Marionette"); - -/** - * Manages a Marionette connection, and dispatches packets received to - * their correct destinations. - * - * @param {number} connId - * Unique identifier of the connection this dispatcher should handle. - * @param {DebuggerTransport} transport - * Debugger transport connection to the client. - * @param {function(): GeckoDriver} driverFactory - * A factory function that produces a GeckoDriver. - */ -this.Dispatcher = function (connId, transport, driverFactory) { - this.connId = connId; - this.conn = transport; - - // transport hooks are Dispatcher#onPacket - // and Dispatcher#onClosed - this.conn.hooks = this; - - // callback for when connection is closed - this.onclose = null; - - // last received/sent message ID - this.lastId = 0; - - this.driver = driverFactory(); - - // lookup of commands sent by server to client by message ID - this.commands_ = new Map(); -}; - -/** - * Debugger transport callback that cleans up - * after a connection is closed. - */ -Dispatcher.prototype.onClosed = function (reason) { - this.driver.deleteSession(); - if (this.onclose) { - this.onclose(this); - } -}; - -/** - * Callback that receives data packets from the client. - * - * If the message is a Response, we look up the command previously issued - * to the client and run its callback, if any. In case of a Command, - * the corresponding is executed. - * - * @param {Array.} data - * A four element array where the elements, in sequence, signifies - * message type, message ID, method name or error, and parameters - * or result. - */ -Dispatcher.prototype.onPacket = function (data) { - let msg = Message.fromMsg(data); - msg.origin = MessageOrigin.Client; - this.log_(msg); - - if (msg instanceof Response) { - let cmd = this.commands_.get(msg.id); - this.commands_.delete(msg.id); - cmd.onresponse(msg); - } else if (msg instanceof Command) { - this.lastId = msg.id; - this.execute(msg); - } -}; - -/** - * Executes a WebDriver command and sends back a response when it has - * finished executing. - * - * Commands implemented in GeckoDriver and registered in its - * {@code GeckoDriver.commands} attribute. The return values from - * commands are expected to be Promises. If the resolved value of said - * promise is not an object, the response body will be wrapped in an object - * under a "value" field. - * - * If the command implementation sends the response itself by calling - * {@code resp.send()}, the response is guaranteed to not be sent twice. - * - * Errors thrown in commands are marshaled and sent back, and if they - * are not WebDriverError instances, they are additionally propagated and - * reported to {@code Components.utils.reportError}. - * - * @param {Command} cmd - * The requested command to execute. - */ -Dispatcher.prototype.execute = function (cmd) { - let resp = new Response(cmd.id, this.send.bind(this)); - let sendResponse = () => resp.sendConditionally(resp => !resp.sent); - let sendError = resp.sendError.bind(resp); - - let req = Task.spawn(function*() { - let fn = this.driver.commands[cmd.name]; - if (typeof fn == "undefined") { - throw new UnknownCommandError(cmd.name); - } - - if (cmd.name !== "newSession") { - assert.session(this.driver); - } - - let rv = yield fn.bind(this.driver)(cmd, resp); - - if (typeof rv != "undefined") { - if (typeof rv != "object") { - resp.body = {value: rv}; - } else { - resp.body = rv; - } - } - }.bind(this)); - - req.then(sendResponse, sendError).catch(error.report); -}; - -Dispatcher.prototype.sendError = function (err, cmdId) { - let resp = new Response(cmdId, this.send.bind(this)); - resp.sendError(err); -}; - -// Convenience methods: - -/** - * When a client connects we send across a JSON Object defining the - * protocol level. - * - * This is the only message sent by Marionette that does not follow - * the regular message format. - */ -Dispatcher.prototype.sayHello = function() { - let whatHo = { - applicationType: "gecko", - marionetteProtocol: PROTOCOL_VERSION, - }; - this.sendRaw(whatHo); -}; - - -/** - * Delegates message to client based on the provided {@code cmdId}. - * The message is sent over the debugger transport socket. - * - * The command ID is a unique identifier assigned to the client's request - * that is used to distinguish the asynchronous responses. - * - * Whilst responses to commands are synchronous and must be sent in the - * correct order. - * - * @param {Command,Response} msg - * The command or response to send. - */ -Dispatcher.prototype.send = function (msg) { - msg.origin = MessageOrigin.Server; - if (msg instanceof Command) { - this.commands_.set(msg.id, msg); - this.sendToEmulator(msg); - } else if (msg instanceof Response) { - this.sendToClient(msg); - } -}; - -// Low-level methods: - -/** - * Send given response to the client over the debugger transport socket. - * - * @param {Response} resp - * The response to send back to the client. - */ -Dispatcher.prototype.sendToClient = function (resp) { - this.driver.responseCompleted(); - this.sendMessage(resp); -}; - -/** - * Marshal message to the Marionette message format and send it. - * - * @param {Command,Response} msg - * The message to send. - */ -Dispatcher.prototype.sendMessage = function (msg) { - this.log_(msg); - let payload = msg.toMsg(); - this.sendRaw(payload); -}; - -/** - * Send the given payload over the debugger transport socket to the - * connected client. - * - * @param {Object} payload - * The payload to ship. - */ -Dispatcher.prototype.sendRaw = function (payload) { - this.conn.send(payload); -}; - -Dispatcher.prototype.log_ = function (msg) { - let a = (msg.origin == MessageOrigin.Client ? " -> " : " <- "); - let s = JSON.stringify(msg.toMsg()); - logger.trace(this.connId + a + s); -}; diff --git a/testing/marionette/jar.mn b/testing/marionette/jar.mn index 962f2ae55b85..dddfde3c54dd 100644 --- a/testing/marionette/jar.mn +++ b/testing/marionette/jar.mn @@ -20,7 +20,6 @@ marionette.jar: content/error.js (error.js) content/wait.js (wait.js) content/message.js (message.js) - content/dispatcher.js (dispatcher.js) content/modal.js (modal.js) content/proxy.js (proxy.js) content/capture.js (capture.js) diff --git a/testing/marionette/server.js b/testing/marionette/server.js index 85fb0c116f2d..6c9bd618f80f 100644 --- a/testing/marionette/server.js +++ b/testing/marionette/server.js @@ -4,19 +4,20 @@ "use strict"; -var {Constructor: CC, classes: Cc, interfaces: Ci, utils: Cu} = Components; +const {Constructor: CC, classes: Cc, interfaces: Ci, utils: Cu} = Components; -var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader); +const loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader); const ServerSocket = CC("@mozilla.org/network/server-socket;1", "nsIServerSocket", "initSpecialConnection"); Cu.import("resource://gre/modules/Log.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("chrome://marionette/content/dispatcher.js"); +Cu.import("chrome://marionette/content/assert.js"); Cu.import("chrome://marionette/content/driver.js"); -Cu.import("chrome://marionette/content/element.js"); -Cu.import("chrome://marionette/content/simpletest.js"); +Cu.import("chrome://marionette/content/error.js"); +Cu.import("chrome://marionette/content/message.js"); // Bug 1083711: Load transport.js as an SDK module instead of subscript loader.loadSubScript("resource://devtools/shared/transport/transport.js"); @@ -27,6 +28,7 @@ this.EXPORTED_SYMBOLS = ["server"]; this.server = {}; const CONTENT_LISTENER_PREF = "marionette.contentListener"; +const PROTOCOL_VERSION = 3; // Marionette sets preferences recommended for automation when it starts, // unless |marionette.prefs.recommended| has been set to false. @@ -253,23 +255,23 @@ const RECOMMENDED_PREFS = new Map([ /** * Bootstraps Marionette and handles incoming client connections. * - * Once started, it opens a TCP socket sporting the debugger transport - * protocol on the provided port. For every new client a Dispatcher is - * created. + * Starting the Marionette server will open a TCP socket sporting the + * debugger transport interface on the provided |port|. For every new + * connection, a |server.TCPConnection| is created. */ server.TCPListener = class { /** * @param {number} port * Port for server to listen to. - * @param {boolean} forceLocal - * Listen only to connections from loopback if true. If false, - * accept all connections. + * @param {boolean=} forceLocal + * Listen only to connections from loopback if true (default). + * When false, accept all connections. */ - constructor (port, forceLocal) { + constructor (port, forceLocal = true) { this.port = port; this.forceLocal = forceLocal; - this.conns = {}; - this.nextConnId = 0; + this.conns = new Set(); + this.nextConnID = 0; this.alive = false; this._acceptConnections = false; this.alteredPrefs = new Set(); @@ -353,20 +355,230 @@ server.TCPListener = class { let input = clientSocket.openInputStream(0, 0, 0); let output = clientSocket.openOutputStream(0, 0, 0); let transport = new DebuggerTransport(input, output); - let connId = "conn" + this.nextConnId++; - let dispatcher = new Dispatcher(connId, transport, this.driverFactory.bind(this)); - dispatcher.onclose = this.onConnectionClosed.bind(this); - this.conns[connId] = dispatcher; + let conn = new server.TCPConnection( + this.nextConnID++, transport, this.driverFactory.bind(this)); + conn.onclose = this.onConnectionClosed.bind(this); + this.conns.add(conn); - logger.debug(`Accepted connection ${connId} from ${clientSocket.host}:${clientSocket.port}`); - dispatcher.sayHello(); + logger.debug(`Accepted connection ${conn.id} from ${clientSocket.host}:${clientSocket.port}`); + conn.sayHello(); transport.ready(); } onConnectionClosed (conn) { - let id = conn.connId; - delete this.conns[id]; - logger.debug(`Closed connection ${id}`); + logger.debug(`Closed connection ${conn.id}`); + this.conns.delete(conn); + } +}; + +/** + * Marionette client connection. + * + * Dispatches packets received to their correct service destinations + * and sends back the service endpoint's return values. + * + * @param {number} connID + * Unique identifier of the connection this dispatcher should handle. + * @param {DebuggerTransport} transport + * Debugger transport connection to the client. + * @param {function(): GeckoDriver} driverFactory + * Factory function that produces a |GeckoDriver|. + */ +server.TCPConnection = class { + constructor (connID, transport, driverFactory) { + this.id = connID; + this.conn = transport; + + // transport hooks are TCPConnection#onPacket + // and TCPConnection#onClosed + this.conn.hooks = this; + + // callback for when connection is closed + this.onclose = null; + + // last received/sent message ID + this.lastID = 0; + + this.driver = driverFactory(); + + // lookup of commands sent by server to client by message ID + this.commands_ = new Map(); + } + + /** + * Debugger transport callback that cleans up + * after a connection is closed. + */ + onClosed (reason) { + this.driver.deleteSession(); + if (this.onclose) { + this.onclose(this); + } + } + + /** + * Callback that receives data packets from the client. + * + * If the message is a Response, we look up the command previously + * issued to the client and run its callback, if any. In case of + * a Command, the corresponding is executed. + * + * @param {Array.} data + * A four element array where the elements, in sequence, signifies + * message type, message ID, method name or error, and parameters + * or result. + */ + onPacket (data) { + let msg = Message.fromMsg(data); + msg.origin = MessageOrigin.Client; + this.log_(msg); + + if (msg instanceof Response) { + let cmd = this.commands_.get(msg.id); + this.commands_.delete(msg.id); + cmd.onresponse(msg); + } else if (msg instanceof Command) { + this.lastID = msg.id; + this.execute(msg); + } + } + + /** + * Executes a WebDriver command and sends back a response when it has + * finished executing. + * + * Commands implemented in GeckoDriver and registered in its + * {@code GeckoDriver.commands} attribute. The return values from + * commands are expected to be Promises. If the resolved value of said + * promise is not an object, the response body will be wrapped in + * an object under a "value" field. + * + * If the command implementation sends the response itself by calling + * {@code resp.send()}, the response is guaranteed to not be sent twice. + * + * Errors thrown in commands are marshaled and sent back, and if they + * are not WebDriverError instances, they are additionally propagated + * and reported to {@code Components.utils.reportError}. + * + * @param {Command} cmd + * The requested command to execute. + */ + execute (cmd) { + let resp = new Response(cmd.id, this.send.bind(this)); + let sendResponse = () => resp.sendConditionally(resp => !resp.sent); + let sendError = resp.sendError.bind(resp); + + let req = Task.spawn(function*() { + let fn = this.driver.commands[cmd.name]; + if (typeof fn == "undefined") { + throw new UnknownCommandError(cmd.name); + } + + if (cmd.name !== "newSession") { + assert.session(this.driver); + } + + let rv = yield fn.bind(this.driver)(cmd, resp); + + if (typeof rv != "undefined") { + if (typeof rv != "object") { + resp.body = {value: rv}; + } else { + resp.body = rv; + } + } + }.bind(this)); + + req.then(sendResponse, sendError).catch(error.report); + } + + sendError (err, cmdID) { + let resp = new Response(cmdID, this.send.bind(this)); + resp.sendError(err); + } + + /** + * When a client connects we send across a JSON Object defining the + * protocol level. + * + * This is the only message sent by Marionette that does not follow + * the regular message format. + */ + sayHello () { + let whatHo = { + applicationType: "gecko", + marionetteProtocol: PROTOCOL_VERSION, + }; + this.sendRaw(whatHo); + }; + + /** + * Delegates message to client based on the provided {@code cmdID}. + * The message is sent over the debugger transport socket. + * + * The command ID is a unique identifier assigned to the client's request + * that is used to distinguish the asynchronous responses. + * + * Whilst responses to commands are synchronous and must be sent in the + * correct order. + * + * @param {Command,Response} msg + * The command or response to send. + */ + send (msg) { + msg.origin = MessageOrigin.Server; + if (msg instanceof Command) { + this.commands_.set(msg.id, msg); + this.sendToEmulator(msg); + } else if (msg instanceof Response) { + this.sendToClient(msg); + } + } + + // Low-level methods: + + /** + * Send given response to the client over the debugger transport socket. + * + * @param {Response} resp + * The response to send back to the client. + */ + sendToClient (resp) { + this.driver.responseCompleted(); + this.sendMessage(resp); + }; + + /** + * Marshal message to the Marionette message format and send it. + * + * @param {Command,Response} msg + * The message to send. + */ + sendMessage (msg) { + this.log_(msg); + let payload = msg.toMsg(); + this.sendRaw(payload); + } + + /** + * Send the given payload over the debugger transport socket to the + * connected client. + * + * @param {Object} payload + * The payload to ship. + */ + sendRaw (payload) { + this.conn.send(payload); + } + + log_ (msg) { + let a = (msg.origin == MessageOrigin.Client ? " -> " : " <- "); + let s = JSON.stringify(msg.toMsg()); + logger.trace(this.id + a + s); + } + + toString () { + return `[object server.TCPConnection ${this.id}]`; } }; From 869b1b932ab84d303afd2bf225a930f1850dd4cc Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Thu, 9 Mar 2017 11:12:53 +0000 Subject: [PATCH 44/57] Bug 1344748 - Rename and register Marionette prefs; r=maja_zf This change renames the following Marionette preferences: marionette.defaultPrefs.enabled marionette.enabled marionette.defaultPrefs.port marionette.port marionette.force-local marionette.forcelocal marionette.logging marionette.log.level The old preference names are still usable, but are henceforth considered deprecated. They will be removed when Firefox 55 ships. It also registers these preferences in Firefox so that they are discoverable through about:config. This patch also refactors testing/marionette/components/marionette.js. MozReview-Commit-ID: 1dAMQS2e0og --HG-- extra : rebase_source : e59a9e656442d8e8cebeaf5e741dc8306436bc22 --- .../client/marionette_driver/geckoinstance.py | 2 +- testing/marionette/components/marionette.js | 269 ++++++++++-------- testing/marionette/moz.build | 2 + testing/marionette/prefs.js | 16 ++ .../harness/wptrunner/browsers/firefox.py | 4 +- tools/lint/eslint/modules.json | 2 +- 6 files changed, 168 insertions(+), 127 deletions(-) create mode 100644 testing/marionette/prefs.js diff --git a/testing/marionette/client/marionette_driver/geckoinstance.py b/testing/marionette/client/marionette_driver/geckoinstance.py index f2e796103276..80431be3494d 100644 --- a/testing/marionette/client/marionette_driver/geckoinstance.py +++ b/testing/marionette/client/marionette_driver/geckoinstance.py @@ -71,7 +71,7 @@ class GeckoInstance(object): "hangmonitor.timeout": 0, "javascript.options.showInConsole": True, - "marionette.defaultPrefs.enabled": True, + "marionette.enabled": True, "media.volume_scale": "0.01", # Make sure the disk cache doesn't get auto disabled diff --git a/testing/marionette/components/marionette.js b/testing/marionette/components/marionette.js index ce89289062f7..fb1872adfa43 100644 --- a/testing/marionette/components/marionette.js +++ b/testing/marionette/components/marionette.js @@ -6,80 +6,76 @@ const {Constructor: CC, interfaces: Ci, utils: Cu, classes: Cc} = Components; -const MARIONETTE_CONTRACTID = "@mozilla.org/marionette;1"; +Cu.import("resource://gre/modules/Log.jsm"); +Cu.import("resource://gre/modules/Preferences.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +const MARIONETTE_CONTRACT_ID = "@mozilla.org/marionette;1"; const MARIONETTE_CID = Components.ID("{786a1369-dca5-4adc-8486-33d23c88010a}"); const DEFAULT_PORT = 2828; -const ENABLED_PREF = "marionette.defaultPrefs.enabled"; -const PORT_PREF = "marionette.defaultPrefs.port"; -const FORCELOCAL_PREF = "marionette.force-local"; -const LOG_PREF = "marionette.logging"; +const DEFAULT_LOG_LEVEL = "info"; +const LOG_LEVELS = new Map([ + ["fatal", Log.Level.Fatal], + ["error", Log.Level.Error], + ["warn", Log.Level.Warn], + ["info", Log.Level.Info], + ["config", Log.Level.Config], + ["debug", Log.Level.Debug], + ["trace", Log.Level.Trace], +]); -/** - * Besides starting based on existing prefs in a profile and a commandline flag, - * we also support inheriting prefs out of an env var, and to start marionette - * that way. - * This allows marionette prefs to persist when we do a restart into a - * different profile in order to test things like Firefox refresh. - * The env var itself, if present, is interpreted as a JSON structure, with the - * keys mapping to preference names in the "marionette." branch, and the values - * to the values of those prefs. So something like {"defaultPrefs.enabled": true} - * in the env var would result in the marionette.defaultPrefs.enabled pref being - * set to true, thus triggering marionette being enabled for that startup. - */ +// Besides starting based on existing prefs in a profile and a command +// line flag, we also support inheriting prefs out of an env var, and to +// start Marionette that way. +// +// This allows marionette prefs to persist when we do a restart into +// a different profile in order to test things like Firefox refresh. +// The environment variable itself, if present, is interpreted as a +// JSON structure, with the keys mapping to preference names in the +// "marionette." branch, and the values to the values of those prefs. So +// something like {"enabled": true} would result in the marionette.enabled +// pref being set to true, thus triggering marionette being enabled for +// that startup. const ENV_PREF_VAR = "MOZ_MARIONETTE_PREF_STATE_ACROSS_RESTARTS"; const ServerSocket = CC("@mozilla.org/network/server-socket;1", "nsIServerSocket", "initSpecialConnection"); -Cu.import("resource://gre/modules/Log.jsm"); -Cu.import("resource://gre/modules/Preferences.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +// Marionette preferences recently changed names. This is an abstraction +// that first looks for the new name, but falls back to using the old name +// if the new does not exist. +// +// This shim can be removed when Firefox 55 ships. +const prefs = { + get enabled () { +#ifdef ENABLE_MARIONETTE + let fallback = Preferences.get("marionette.defaultPrefs.enabled", false); + return Preferences.get("marionette.enabled", fallback); +#else + return false; +#endif + }, -function MarionetteComponent() { - this.loaded_ = false; - this.observerService = Services.obs; - this.logger = this.setupLogger_(this.determineLoggingLevel_()); -} + get port () { + let fallback = Preferences.get("marionette.defaultPrefs.port", DEFAULT_PORT); + return Preferences.get("marionette.port", fallback); + }, -MarionetteComponent.prototype = { - classDescription: "Marionette component", - classID: MARIONETTE_CID, - contractID: MARIONETTE_CONTRACTID, - QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler, Ci.nsIObserver]), - _xpcom_categories: [ - {category: "command-line-handler", entry: "b-marionette"}, - {category: "profile-after-change", service: true} - ], - enabled: false, - finalUiStartup: false, - gfxWindow: null, - server: null, -}; - -MarionetteComponent.prototype.setupLogger_ = function (level) { - let log = Log.repository.getLogger("Marionette"); - log.level = level; - log.addAppender(new Log.DumpAppender()); - return log; -}; - -MarionetteComponent.prototype.determineLoggingLevel_ = function() { - let level = Log.Level.Info; - - // marionette.logging pref can override default - // with an entry from the Log.Level enum - if (Preferences.has(LOG_PREF)) { - let p = Preferences.get(LOG_PREF); + get logLevel () { + let level = DEFAULT_LOG_LEVEL; + let fallback = Preferences.get("marionette.logging", level); + let p = Preferences.get("marionette.log.level", fallback); switch (typeof p) { // Gecko >= 46 case "string": let s = p.toLowerCase(); - s = s.charAt(0).toUpperCase() + s.slice(1); - level = Log.Level[s]; + if (LOG_LEVELS.has(s)) { + level = LOG_LEVELS.get(s); + } break; // Gecko <= 45 @@ -89,13 +85,61 @@ MarionetteComponent.prototype.determineLoggingLevel_ = function() { } break; } - } - return level; + return level; + }, + + get forceLocal () { + let fallback = Preferences.get("marionette.force-local", true); + return Preferences.get("marionette.forcelocal", fallback); + }, + + readFromEnvironment (key) { + const env = Cc["@mozilla.org/process/environment;1"] + .getService(Ci.nsIEnvironment); + + if (env.exists(key)) { + let prefs; + try { + prefs = JSON.parse(env.get(key)); + } catch (e) { + Cu.reportError( + "Invalid Marionette preferences in environment; " + + "preferences will not have been applied"); + Cu.reportError(e); + } + + if (prefs) { + for (let prefName of Object.keys(prefs)) { + Preferences.set("marionette." + prefName, prefs[prefName]); + } + } + } + }, }; -MarionetteComponent.prototype.onSocketAccepted = function( - socket, transport) { +function MarionetteComponent() { + this.enabled = prefs.enabled; + this.loaded = false; + this.logger = this.setupLogger(prefs.logLevel); + this.server = null; + this.gfxWindow = null; + this.finalUIStartup = false; +} + +MarionetteComponent.prototype = { + classDescription: "Marionette component", + classID: MARIONETTE_CID, + contractID: MARIONETTE_CONTRACT_ID, + QueryInterface: XPCOMUtils.generateQI( + [Ci.nsICommandLineHandler, Ci.nsIObserver]), + _xpcom_categories: [ + {category: "command-line-handler", entry: "b-marionette"}, + {category: "profile-after-change", service: true} + ], +}; + +MarionetteComponent.prototype.onSocketAccepted = function (socket, transport) { this.logger.info("onSocketAccepted for Marionette dummy socket"); }; @@ -104,9 +148,8 @@ MarionetteComponent.prototype.onStopListening = function (socket, status) { socket.close(); }; -/** Check cmdLine argument for {@code --marionette}. */ +/** Checks |cmdLine| for the --marionette flag. */ MarionetteComponent.prototype.handle = function (cmdLine) { - // if the CLI is there then lets do work otherwise nothing to see if (cmdLine.handleFlag("marionette", false)) { this.enabled = true; this.logger.debug("Marionette enabled via command-line flag"); @@ -117,46 +160,44 @@ MarionetteComponent.prototype.handle = function (cmdLine) { MarionetteComponent.prototype.observe = function (subject, topic, data) { switch (topic) { case "profile-after-change": - // Using sessionstore-windows-restored as the xpcom category doesn't seem to work, - // so we wait for that by adding an observer here. - this.observerService.addObserver(this, "sessionstore-windows-restored", false); + // Using sessionstore-windows-restored as the xpcom category doesn't + // seem to work, so we wait for that by adding an observer here. + Services.obs.addObserver(this, "sessionstore-windows-restored", false); - this.maybeReadPrefsFromEnvironment(); + prefs.readFromEnvironment(ENV_PREF_VAR); -#ifdef ENABLE_MARIONETTE - this.enabled = Preferences.get(ENABLED_PREF, false); if (this.enabled) { - this.logger.debug("Marionette enabled via build flag and pref"); + this.logger.debug("Marionette is enabled"); // We want to suppress the modal dialog that's shown // when starting up in safe-mode to enable testing. if (Services.appinfo.inSafeMode) { - this.observerService.addObserver(this, "domwindowopened", false); + Services.obs.addObserver(this, "domwindowopened", false); } } -#endif break; case "domwindowclosed": if (this.gfxWindow === null || subject === this.gfxWindow) { - this.observerService.removeObserver(this, topic); + Services.obs.removeObserver(this, topic); - this.observerService.addObserver(this, "xpcom-shutdown", false); - this.finalUiStartup = true; + Services.obs.addObserver(this, "xpcom-shutdown", false); + this.finalUIStartup = true; this.init(); } break; case "domwindowopened": - this.observerService.removeObserver(this, topic); - this.suppressSafeModeDialog_(subj); + Services.obs.removeObserver(this, topic); + this.suppressSafeModeDialog(subject); break; case "sessionstore-windows-restored": - this.observerService.removeObserver(this, topic); + Services.obs.removeObserver(this, topic); - // When Firefox starts on Windows, an additional GFX sanity test window - // may appear off-screen. Marionette should wait for it to close. + // When Firefox starts on Windows, an additional GFX sanity test + // window may appear off-screen. Marionette should wait for it + // to close. let winEn = Services.wm.getEnumerator(null); while (winEn.hasMoreElements()) { let win = winEn.getNext(); @@ -167,43 +208,31 @@ MarionetteComponent.prototype.observe = function (subject, topic, data) { } if (this.gfxWindow) { - this.observerService.addObserver(this, "domwindowclosed", false); + Services.obs.addObserver(this, "domwindowclosed", false); } else { - this.observerService.addObserver(this, "xpcom-shutdown", false); - this.finalUiStartup = true; + Services.obs.addObserver(this, "xpcom-shutdown", false); + this.finalUIStartup = true; this.init(); } break; case "xpcom-shutdown": - this.observerService.removeObserver(this, "xpcom-shutdown"); + Services.obs.removeObserver(this, "xpcom-shutdown"); this.uninit(); break; } }; -MarionetteComponent.prototype.maybeReadPrefsFromEnvironment = function() { - let env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment); - if (env.exists(ENV_PREF_VAR)) { - let prefStr = env.get(ENV_PREF_VAR); - let prefs; - try { - prefs = JSON.parse(prefStr); - } catch (ex) { - Cu.reportError("Invalid marionette prefs in environment; prefs won't have been applied."); - Cu.reportError(ex); - } - if (prefs) { - for (let prefName of Object.keys(prefs)) { - Preferences.set("marionette." + prefName, prefs[prefName]); - } - } - } -} +MarionetteComponent.prototype.setupLogger = function (level) { + let logger = Log.repository.getLogger("Marionette"); + logger.level = level; + logger.addAppender(new Log.DumpAppender()); + return logger; +}; -MarionetteComponent.prototype.suppressSafeModeDialog_ = function (win) { - // Wait for the modal dialog to finish loading. +/** Wait for the modal dialogue to finish loading. */ +MarionetteComponent.prototype.suppressSafeModeDialog = function (win) { win.addEventListener("load", function() { if (win.document.getElementById("safeModeDialog")) { // Accept the dialog to start in safe-mode @@ -214,18 +243,14 @@ MarionetteComponent.prototype.suppressSafeModeDialog_ = function (win) { }, {once: true}); }; -MarionetteComponent.prototype.init = function() { - if (this.loaded_ || !this.enabled || !this.finalUiStartup) { +MarionetteComponent.prototype.init = function () { + if (this.loaded || !this.enabled || !this.finalUIStartup) { return; } - this.loaded_ = true; + this.loaded = true; - let forceLocal = Preferences.get(FORCELOCAL_PREF, - Services.appinfo.name == "B2G" ? false : true); - Preferences.set(FORCELOCAL_PREF, forceLocal); - - if (!forceLocal) { + if (!prefs.forceLocal) { // See bug 800138. Because the first socket that opens with // force-local=false fails, we open a dummy socket that will fail. // keepWhenOffline=true so that it still work when offline (local). @@ -236,30 +261,28 @@ MarionetteComponent.prototype.init = function() { insaneSacrificialGoat.asyncListen(this); } - let port = Preferences.get(PORT_PREF, DEFAULT_PORT); - - let s; + let so; try { Cu.import("chrome://marionette/content/server.js"); - s = new server.TCPListener(port, forceLocal); - s.start(); - this.logger.info(`Listening on port ${s.port}`); + so = new server.TCPListener(prefs.port, prefs.forceLocal); + so.start(); + this.logger.info(`Listening on port ${so.port}`); } catch (e) { this.logger.error(`Error on starting server: ${e}`); dump(e.toString() + "\n" + e.stack + "\n"); } finally { - if (s) { - this.server = s; + if (so) { + this.server = so; } } }; -MarionetteComponent.prototype.uninit = function() { - if (!this.loaded_) { +MarionetteComponent.prototype.uninit = function () { + if (!this.loaded) { return; } this.server.stop(); - this.loaded_ = false; + this.loaded = false; }; this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MarionetteComponent]); diff --git a/testing/marionette/moz.build b/testing/marionette/moz.build index 7dbfcca3790c..44a65fa34ab7 100644 --- a/testing/marionette/moz.build +++ b/testing/marionette/moz.build @@ -4,6 +4,8 @@ DIRS += ["components"] +JS_PREFERENCE_FILES += ["prefs.js"] + JAR_MANIFESTS += ["jar.mn"] MARIONETTE_UNIT_MANIFESTS += ["harness/marionette_harness/tests/unit/unit-tests.ini"] MARIONETTE_WEBAPI_MANIFESTS += ["harness/marionette_harness/tests/webapi-tests.ini"] diff --git a/testing/marionette/prefs.js b/testing/marionette/prefs.js new file mode 100644 index 000000000000..250a71c2aa46 --- /dev/null +++ b/testing/marionette/prefs.js @@ -0,0 +1,16 @@ +/* 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/. */ + +// Whether or not Marionette is enabled. +pref("marionette.enabled", false); + +// Port to start Marionette server on. +pref("marionette.port", 2828); + +// Forces client connections to come from a loopback device. +pref("marionette.forcelocal", true); + +// Marionette logging verbosity. Allowed values are "fatal", "error", +// "warn", "info", "config", "debug", and "trace". +pref("marionette.log.level", "info"); diff --git a/testing/web-platform/harness/wptrunner/browsers/firefox.py b/testing/web-platform/harness/wptrunner/browsers/firefox.py index d93b082a8dc6..cdae762ea933 100644 --- a/testing/web-platform/harness/wptrunner/browsers/firefox.py +++ b/testing/web-platform/harness/wptrunner/browsers/firefox.py @@ -148,8 +148,8 @@ class FirefoxBrowser(Browser): self.profile = FirefoxProfile(locations=locations, preferences=preferences) - self.profile.set_preferences({"marionette.defaultPrefs.enabled": True, - "marionette.defaultPrefs.port": self.marionette_port, + self.profile.set_preferences({"marionette.enabled": True, + "marionette.port": self.marionette_port, "dom.disable_open_during_load": False, "network.dns.localDomains": ",".join(hostnames), "network.proxy.type": 0, diff --git a/tools/lint/eslint/modules.json b/tools/lint/eslint/modules.json index 3eb462d96de7..e500f720f256 100644 --- a/tools/lint/eslint/modules.json +++ b/tools/lint/eslint/modules.json @@ -55,7 +55,7 @@ "dbg-server.jsm": ["DebuggerServer", "ActorPool", "OriginalLocation"], "debug.js": ["NS_ASSERT"], "declined.js": ["DeclinedEngines"], - "dispatcher.js": ["Dispatcher"], + "dispatcher.js": ["dispatcher"], "distribution.js": ["DistributionCustomizer"], "DNSTypes.jsm": ["DNS_QUERY_RESPONSE_CODES", "DNS_AUTHORITATIVE_ANSWER_CODES", "DNS_CLASS_CODES", "DNS_RECORD_TYPES"], "doctor.js": ["Doctor"], From 3ab0090e1666b4e4eb6f1b51e9076cb1eb8d184c Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Tue, 7 Mar 2017 21:02:05 +0000 Subject: [PATCH 45/57] Bug 1344748 - Gate recommended prefs on a preference; r=maja_zf,whimboo MozReview-Commit-ID: FnqBDAXpg6v --HG-- extra : rebase_source : a716ea82000f6d5e5ed4408639cb1628c13a0a1c --- testing/marionette/prefs.js | 4 ++++ testing/marionette/server.js | 20 ++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/testing/marionette/prefs.js b/testing/marionette/prefs.js index 250a71c2aa46..62076e5cd793 100644 --- a/testing/marionette/prefs.js +++ b/testing/marionette/prefs.js @@ -14,3 +14,7 @@ pref("marionette.forcelocal", true); // Marionette logging verbosity. Allowed values are "fatal", "error", // "warn", "info", "config", "debug", and "trace". pref("marionette.log.level", "info"); + +// Sets preferences recommended when using Firefox in automation with +// Marionette. +pref("marionette.prefs.recommended", true); diff --git a/testing/marionette/server.js b/testing/marionette/server.js index 6c9bd618f80f..0ca950a9d77f 100644 --- a/testing/marionette/server.js +++ b/testing/marionette/server.js @@ -27,9 +27,11 @@ const logger = Log.repository.getLogger("Marionette"); this.EXPORTED_SYMBOLS = ["server"]; this.server = {}; -const CONTENT_LISTENER_PREF = "marionette.contentListener"; const PROTOCOL_VERSION = 3; +const PREF_CONTENT_LISTENER = "marionette.contentListener"; +const PREF_RECOMMENDED = "marionette.prefs.recommended"; + // Marionette sets preferences recommended for automation when it starts, // unless |marionette.prefs.recommended| has been set to false. // Where noted, some prefs should also be set in the profile passed to @@ -286,7 +288,7 @@ server.TCPListener = class { * A driver instance. */ driverFactory () { - Preferences.set(CONTENT_LISTENER_PREF, false); + Preferences.set(PREF_CONTENT_LISTENER, false); return new GeckoDriver(Services.appinfo.name, this); } @@ -305,12 +307,14 @@ server.TCPListener = class { return; } - // set recommended preferences if they are not already user-defined - for (let [k, v] of RECOMMENDED_PREFS) { - if (!Preferences.isSet(k)) { - logger.debug(`Setting recommended pref ${k} to ${v}`); - Preferences.set(k, v); - this.alteredPrefs.add(k); + if (Preferences.get(PREF_RECOMMENDED)) { + // set recommended prefs if they are not already user-defined + for (let [k, v] of RECOMMENDED_PREFS) { + if (!Preferences.isSet(k)) { + logger.debug(`Setting recommended pref ${k} to ${v}`); + Preferences.set(k, v); + this.alteredPrefs.add(k); + } } } From 5b7ab93fc132812daf91f18140a799047ababddb Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Mon, 6 Mar 2017 18:38:06 +0000 Subject: [PATCH 46/57] Bug 1344748 - Skip recommended Marionette prefs for Firefox tests; r=maja_zf,whimboo The recommended Marionette preferences for use in automation are not so useful when testing the browser itself. Many of the tests for Firefox have highly specific requirements, and setting the recommended Marionette preferences could for these mean a deterioration of test coverage. The majority of test harnesses utilising Marionette use it to install unsigned add-ons at runtime, and these preferences are not relevant in this context. The preferences they use are defined in prefs_general.js. To avoid an unfortunate and unintended regression in test coverage, we skip using the recommended Marionette preferences when we test the browser itself. MozReview-Commit-ID: 5h3cGPfbicV --HG-- extra : rebase_source : 3db358cd43208b274f0a255f8351f3f9762d386a --- testing/profiles/prefs_general.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/testing/profiles/prefs_general.js b/testing/profiles/prefs_general.js index 3d87df356565..6d4eb7970024 100644 --- a/testing/profiles/prefs_general.js +++ b/testing/profiles/prefs_general.js @@ -365,3 +365,8 @@ user_pref("signon.rememberSignons", false); // Enable form autofill feature testing. user_pref("browser.formautofill.experimental", true); + +// Disable all recommended Marionette preferences for Gecko tests. +// The prefs recommended by Marionette are typically geared towards +// consumer automation; not vendor testing. +user_pref("marionette.prefs.recommended", false); From 2da4fc5ac9d89927cba44697a5219ef32b4b4b77 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Thu, 9 Mar 2017 17:56:46 +0000 Subject: [PATCH 47/57] Bug 1344748 - Remove ENABLE_MARIONETTE check from MarionetteComponent; r=whimboo If ENABLE_MARIONETTE is false, the Marionette jar will not be included in the omnijar, making the check in MarionetteComponent superfluous. It also does not belong in this file: the intention of ENABLE_MARIONETTE is to disable the compilation and inclusion of Marionette altogether, not to gate whether to enable the Marionette server. The Marionette component is considered enables if the marionette.enabled/marionette.defaultPrefs.enable preference is true or --marionette is passed as a flag. This presupposes that the Marionette component is packaged. MozReview-Commit-ID: K8gam5hOvB0 --HG-- extra : rebase_source : 024ec27200cae7bc5149b1b8b564cdf7d97b552d --- testing/marionette/components/marionette.js | 4 ---- testing/marionette/components/moz.build | 9 ++++----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/testing/marionette/components/marionette.js b/testing/marionette/components/marionette.js index fb1872adfa43..a2a62468684b 100644 --- a/testing/marionette/components/marionette.js +++ b/testing/marionette/components/marionette.js @@ -51,12 +51,8 @@ const ServerSocket = CC("@mozilla.org/network/server-socket;1", // This shim can be removed when Firefox 55 ships. const prefs = { get enabled () { -#ifdef ENABLE_MARIONETTE let fallback = Preferences.get("marionette.defaultPrefs.enabled", false); return Preferences.get("marionette.enabled", fallback); -#else - return false; -#endif }, get port () { diff --git a/testing/marionette/components/moz.build b/testing/marionette/components/moz.build index 7fc4113a5ac1..ba161d9761b3 100644 --- a/testing/marionette/components/moz.build +++ b/testing/marionette/components/moz.build @@ -2,8 +2,7 @@ # 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/. -EXTRA_COMPONENTS += ["marionette.manifest"] -EXTRA_PP_COMPONENTS += ["marionette.js"] - -if CONFIG["ENABLE_MARIONETTE"]: - DEFINES["ENABLE_MARIONETTE"] = 1 +EXTRA_COMPONENTS += [ + "marionette.js", + "marionette.manifest", +] From 751e57ea3820001e7040245032415ec9252d3ea1 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Thu, 9 Mar 2017 17:57:26 +0000 Subject: [PATCH 48/57] Bug 1344748 - Document and make MarionetteComponent easier to read; r=whimboo MozReview-Commit-ID: 4VTCOsTYftG --HG-- extra : rebase_source : 4565132090ed095599b1c91090b12436ff40dbe8 --- testing/marionette/components/marionette.js | 52 +++++++++++++-------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/testing/marionette/components/marionette.js b/testing/marionette/components/marionette.js index a2a62468684b..c1ab3d84d468 100644 --- a/testing/marionette/components/marionette.js +++ b/testing/marionette/components/marionette.js @@ -115,12 +115,27 @@ const prefs = { }; function MarionetteComponent() { + // keeps track of whether Marionette is available, + // either as a result of the marionette.enabled pref + // or by use of the --marionette flag this.enabled = prefs.enabled; - this.loaded = false; - this.logger = this.setupLogger(prefs.logLevel); + + // guards against this component + // being initialised multiple times + this.running = false; + + // holds a reference to server.TCPListener this.server = null; + + // holds reference to ChromeWindow + // used to run GFX sanity tests on Windows this.gfxWindow = null; + + // indicates that all pending window checks have been completed + // and that we are ready to start the Marionette server this.finalUIStartup = false; + + this.logger = this.setupLogger(prefs.logLevel); } MarionetteComponent.prototype = { @@ -131,7 +146,7 @@ MarionetteComponent.prototype = { [Ci.nsICommandLineHandler, Ci.nsIObserver]), _xpcom_categories: [ {category: "command-line-handler", entry: "b-marionette"}, - {category: "profile-after-change", service: true} + {category: "profile-after-change", service: true}, ], }; @@ -144,7 +159,7 @@ MarionetteComponent.prototype.onStopListening = function (socket, status) { socket.close(); }; -/** Checks |cmdLine| for the --marionette flag. */ +// Handle --marionette flag MarionetteComponent.prototype.handle = function (cmdLine) { if (cmdLine.handleFlag("marionette", false)) { this.enabled = true; @@ -163,8 +178,6 @@ MarionetteComponent.prototype.observe = function (subject, topic, data) { prefs.readFromEnvironment(ENV_PREF_VAR); if (this.enabled) { - this.logger.debug("Marionette is enabled"); - // We want to suppress the modal dialog that's shown // when starting up in safe-mode to enable testing. if (Services.appinfo.inSafeMode) { @@ -227,11 +240,10 @@ MarionetteComponent.prototype.setupLogger = function (level) { return logger; }; -/** Wait for the modal dialogue to finish loading. */ MarionetteComponent.prototype.suppressSafeModeDialog = function (win) { - win.addEventListener("load", function() { + win.addEventListener("load", () => { if (win.document.getElementById("safeModeDialog")) { - // Accept the dialog to start in safe-mode + // accept the dialog to start in safe-mode win.setTimeout(() => { win.document.documentElement.getButton("accept").click(); }); @@ -240,11 +252,11 @@ MarionetteComponent.prototype.suppressSafeModeDialog = function (win) { }; MarionetteComponent.prototype.init = function () { - if (this.loaded || !this.enabled || !this.finalUIStartup) { + if (this.running || !this.enabled || !this.finalUIStartup) { return; } - this.loaded = true; + this.running = true; if (!prefs.forceLocal) { // See bug 800138. Because the first socket that opens with @@ -257,28 +269,28 @@ MarionetteComponent.prototype.init = function () { insaneSacrificialGoat.asyncListen(this); } - let so; + let s; try { Cu.import("chrome://marionette/content/server.js"); - so = new server.TCPListener(prefs.port, prefs.forceLocal); - so.start(); - this.logger.info(`Listening on port ${so.port}`); + s = new server.TCPListener(prefs.port, prefs.forceLocal); + s.start(); + this.logger.info(`Listening on port ${s.port}`); } catch (e) { this.logger.error(`Error on starting server: ${e}`); - dump(e.toString() + "\n" + e.stack + "\n"); + dump(`${e.toString()}\n${e.stack}\n`); } finally { - if (so) { - this.server = so; + if (s) { + this.server = s; } } }; MarionetteComponent.prototype.uninit = function () { - if (!this.loaded) { + if (!this.running) { return; } this.server.stop(); - this.loaded = false; + this.running = false; }; this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MarionetteComponent]); From e75a6d1524d10083377dd687ea5dd52de64aced4 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Thu, 9 Mar 2017 20:15:32 +0000 Subject: [PATCH 49/57] Bug 1344748 - Make Marionette respect marionette.enabled pref; r=whimboo This removes the internal enabledness state tracking in MarionetteComponent in favour of the marionette.enabled preference. When the marionette.enabled preference changes, Marionette is enabled or disabled. Depending on whether all the initialisation conditions have been met, Marionette is started. If it is running, it is stopped when toggling the preference back off. MozReview-Commit-ID: jQFYZhULqO --HG-- extra : rebase_source : 63f101cebf9db2f3400885a06449e91fce84094f --- testing/marionette/components/marionette.js | 62 ++++++++++++++------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/testing/marionette/components/marionette.js b/testing/marionette/components/marionette.js index c1ab3d84d468..a911f0e3b9e7 100644 --- a/testing/marionette/components/marionette.js +++ b/testing/marionette/components/marionette.js @@ -14,6 +14,15 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); const MARIONETTE_CONTRACT_ID = "@mozilla.org/marionette;1"; const MARIONETTE_CID = Components.ID("{786a1369-dca5-4adc-8486-33d23c88010a}"); +const PREF_ENABLED = "marionette.enabled"; +const PREF_ENABLED_FALLBACK = "marionette.defaultPrefs.enabled"; +const PREF_PORT = "marionette.port"; +const PREF_PORT_FALLBACK = "marionette.defaultPrefs.port"; +const PREF_LOG_LEVEL = "marionette.log.level"; +const PREF_LOG_LEVEL_FALLBACK = "marionette.logging"; +const PREF_FORCE_LOCAL = "marionette.forcelocal"; +const PREF_FORCE_LOCAL_FALLBACK = "marionette.force-local"; + const DEFAULT_PORT = 2828; const DEFAULT_LOG_LEVEL = "info"; const LOG_LEVELS = new Map([ @@ -50,20 +59,15 @@ const ServerSocket = CC("@mozilla.org/network/server-socket;1", // // This shim can be removed when Firefox 55 ships. const prefs = { - get enabled () { - let fallback = Preferences.get("marionette.defaultPrefs.enabled", false); - return Preferences.get("marionette.enabled", fallback); - }, - get port () { - let fallback = Preferences.get("marionette.defaultPrefs.port", DEFAULT_PORT); - return Preferences.get("marionette.port", fallback); + let fallback = Preferences.get(PREF_PORT_FALLBACK, DEFAULT_PORT); + return Preferences.get(PREF_PORT, fallback); }, get logLevel () { let level = DEFAULT_LOG_LEVEL; - let fallback = Preferences.get("marionette.logging", level); - let p = Preferences.get("marionette.log.level", fallback); + let fallback = Preferences.get(PREF_LOG_LEVEL_FALLBACK, level); + let p = Preferences.get(PREF_LOG_LEVEL, fallback); switch (typeof p) { // Gecko >= 46 @@ -86,8 +90,8 @@ const prefs = { }, get forceLocal () { - let fallback = Preferences.get("marionette.force-local", true); - return Preferences.get("marionette.forcelocal", fallback); + let fallback = Preferences.get(PREF_FORCE_LOCAL_FALLBACK, true); + return Preferences.get(PREF_FORCE_LOCAL, fallback); }, readFromEnvironment (key) { @@ -115,11 +119,6 @@ const prefs = { }; function MarionetteComponent() { - // keeps track of whether Marionette is available, - // either as a result of the marionette.enabled pref - // or by use of the --marionette flag - this.enabled = prefs.enabled; - // guards against this component // being initialised multiple times this.running = false; @@ -136,6 +135,13 @@ function MarionetteComponent() { this.finalUIStartup = false; this.logger = this.setupLogger(prefs.logLevel); + Services.prefs.addObserver(PREF_ENABLED, this, false); + + if (Preferences.isSet(PREF_ENABLED_FALLBACK)) { + this.logger.warn(`Deprecated preference ${PREF_ENABLED_FALLBACK} detected, ` + + `please use ${PREF_ENABLED}`); + Preferences.set(PREF_ENABLED, Preferences.get(PREF_ENABLED_FALLBACK)); + } } MarionetteComponent.prototype = { @@ -163,13 +169,29 @@ MarionetteComponent.prototype.onStopListening = function (socket, status) { MarionetteComponent.prototype.handle = function (cmdLine) { if (cmdLine.handleFlag("marionette", false)) { this.enabled = true; - this.logger.debug("Marionette enabled via command-line flag"); - this.init(); } }; +Object.defineProperty(MarionetteComponent.prototype, "enabled", { + set (value) { + Preferences.set(PREF_ENABLED, value); + }, + + get () { + return Preferences.get(PREF_ENABLED); + }, +}); + MarionetteComponent.prototype.observe = function (subject, topic, data) { switch (topic) { + case "nsPref:changed": + if (Preferences.get(PREF_ENABLED)) { + this.init(); + } else { + this.uninit(); + } + break; + case "profile-after-change": // Using sessionstore-windows-restored as the xpcom category doesn't // seem to work, so we wait for that by adding an observer here. @@ -256,8 +278,6 @@ MarionetteComponent.prototype.init = function () { return; } - this.running = true; - if (!prefs.forceLocal) { // See bug 800138. Because the first socket that opens with // force-local=false fails, we open a dummy socket that will fail. @@ -281,6 +301,7 @@ MarionetteComponent.prototype.init = function () { } finally { if (s) { this.server = s; + this.running = true; } } }; @@ -290,6 +311,7 @@ MarionetteComponent.prototype.uninit = function () { return; } this.server.stop(); + this.logger.info("Ceased listening"); this.running = false; }; From 6745d8932bf5bc0318e7965cfc03c92fc0e207ad Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Thu, 9 Mar 2017 20:16:17 +0000 Subject: [PATCH 50/57] Bug 1344748 - List --marionette in CLI help; r=whimboo This adds an entry to the firefox --help output mentioning Marionette, the remote control protocol server. MozReview-Commit-ID: 8mwGO0HjvOr --HG-- extra : rebase_source : 3bb2b96fbcbca024f15065f53dae91580f27b346 --- testing/marionette/components/marionette.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/testing/marionette/components/marionette.js b/testing/marionette/components/marionette.js index a911f0e3b9e7..2992b4b173c7 100644 --- a/testing/marionette/components/marionette.js +++ b/testing/marionette/components/marionette.js @@ -148,12 +148,15 @@ MarionetteComponent.prototype = { classDescription: "Marionette component", classID: MARIONETTE_CID, contractID: MARIONETTE_CONTRACT_ID, - QueryInterface: XPCOMUtils.generateQI( - [Ci.nsICommandLineHandler, Ci.nsIObserver]), + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsICommandLineHandler, + Ci.nsIObserver, + ]), _xpcom_categories: [ {category: "command-line-handler", entry: "b-marionette"}, {category: "profile-after-change", service: true}, ], + helpInfo: " --marionette Enable remote control server.\n", }; MarionetteComponent.prototype.onSocketAccepted = function (socket, transport) { From 94a0c13a310ef715e3ee2ea4c37b34ca4e27de98 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Thu, 23 Feb 2017 18:33:26 +0000 Subject: [PATCH 51/57] Bug 1342162 - Align pageLoad key with WebDriver; r=maja_zf The WebDriver specification recently decided to use "pageLoad" instead of "page load" to identify the page load duration timeout in the session timeouts configuration object: https://github.com/w3c/webdriver/pull/796 This change aligns Marionette with WebDriver, and as long as this patch is uplifted to Aurora (53) and Beta (52) in reasonable time, we should be able to avoid the backwards compatibility dance with the Python client (for upgrade tests) because the original change to the data format landed on the current Firefox version: https://bugzilla.mozilla.org/show_bug.cgi?id=1316622 MozReview-Commit-ID: BzQeJku4AFS --HG-- extra : rebase_source : 61b4450ef610cb36e6ed585ee6b20807b51f23be --- .../marionette/client/marionette_driver/timeout.py | 4 ++-- .../tests/unit/test_capabilities.py | 4 ++-- testing/marionette/session.js | 8 ++++---- testing/marionette/test_session.js | 14 +++++++------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/testing/marionette/client/marionette_driver/timeout.py b/testing/marionette/client/marionette_driver/timeout.py index e2fa94f4fdde..bf71dedc1194 100644 --- a/testing/marionette/client/marionette_driver/timeout.py +++ b/testing/marionette/client/marionette_driver/timeout.py @@ -63,7 +63,7 @@ class Timeouts(object): minutes (or 300 seconds). """ - return self._get("page load") + return self._get("pageLoad") @page_load.setter def page_load(self, sec): @@ -71,7 +71,7 @@ class Timeouts(object): to wait for the page loading to complete. """ - self._set("page load", sec) + self._set("pageLoad", sec) @property def implicit(self): diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_capabilities.py b/testing/marionette/harness/marionette_harness/tests/unit/test_capabilities.py index d3386316d2b2..f50fdc568438 100644 --- a/testing/marionette/harness/marionette_harness/tests/unit/test_capabilities.py +++ b/testing/marionette/harness/marionette_harness/tests/unit/test_capabilities.py @@ -35,7 +35,7 @@ class TestCapabilities(MarionetteTestCase): self.assertFalse(self.caps["acceptInsecureCerts"]) self.assertDictEqual(self.caps["timeouts"], {"implicit": 0, - "page load": 300000, + "pageLoad": 300000, "script": 30000}) def test_supported_features(self): @@ -245,7 +245,7 @@ class TestCapabilityMatching(MarionetteTestCase): self.assertEqual(self.marionette.get_pref("network.proxy.type"), 1) def test_timeouts(self): - timeouts = {u"implicit": 123, u"page load": 456, u"script": 789} + timeouts = {u"implicit": 123, u"pageLoad": 456, u"script": 789} caps = {"desiredCapabilities": {"timeouts": timeouts}} self.marionette.start_session(caps) self.assertIn("timeouts", self.marionette.session_capabilities) diff --git a/testing/marionette/session.js b/testing/marionette/session.js index 8bd16404f1f3..f5d5b93fe949 100644 --- a/testing/marionette/session.js +++ b/testing/marionette/session.js @@ -42,9 +42,9 @@ session.Timeouts = class { toJSON () { return { - "implicit": this.implicit, - "page load": this.pageLoad, - "script": this.script, + implicit: this.implicit, + pageLoad: this.pageLoad, + script: this.script, }; } @@ -64,7 +64,7 @@ session.Timeouts = class { t.script = ms; break; - case "page load": + case "pageLoad": t.pageLoad = ms; break; diff --git a/testing/marionette/test_session.js b/testing/marionette/test_session.js index ef45573a73ae..195495a82e94 100644 --- a/testing/marionette/test_session.js +++ b/testing/marionette/test_session.js @@ -29,21 +29,21 @@ add_test(function test_Timeouts_toString() { add_test(function test_Timeouts_toJSON() { let ts = new session.Timeouts(); - deepEqual(ts.toJSON(), {"implicit": 0, "page load": 300000, "script": 30000}); + deepEqual(ts.toJSON(), {"implicit": 0, "pageLoad": 300000, "script": 30000}); run_next_test(); }); add_test(function test_Timeouts_fromJSON() { let json = { - "implicit": 10, - "page load": 20, - "script": 30, + implicit: 10, + pageLoad: 20, + script: 30, }; let ts = session.Timeouts.fromJSON(json); - equal(ts.implicit, json["implicit"]); - equal(ts.pageLoad, json["page load"]); - equal(ts.script, json["script"]); + equal(ts.implicit, json.implicit); + equal(ts.pageLoad, json.pageLoad); + equal(ts.script, json.script); run_next_test(); }); From bf17093d1b26b79d15329ed951c88c0ad7964487 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Thu, 23 Mar 2017 16:22:34 +0000 Subject: [PATCH 52/57] Bug 1342162 - Make timeout API in client backwards compatible; r=whimboo This makes the session timeout duration configuration API backwards compatible with earlier Firefoxen. As Marionette changes to accept pageLoad, we must still continue to allow "page load" as a key for as long as the Marionette Python client is used for Firefox upgrade tests. MozReview-Commit-ID: Ln4D3bY2d7f --HG-- extra : rebase_source : 0ee6c33e0bfbb1605e250db2adea77942808855f --- .../client/marionette_driver/timeout.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/testing/marionette/client/marionette_driver/timeout.py b/testing/marionette/client/marionette_driver/timeout.py index bf71dedc1194..94ee7b1c716e 100644 --- a/testing/marionette/client/marionette_driver/timeout.py +++ b/testing/marionette/client/marionette_driver/timeout.py @@ -36,7 +36,10 @@ class Timeouts(object): self._marionette._send_message("timeouts", {"type": name, "ms": ms}) def _get(self, name): - ms = self._marionette._send_message("getTimeouts", key=name) + ts = self._marionette._send_message("getTimeouts") + if name not in ts: + raise KeyError() + ms = ts[name] return ms / 1000 @property @@ -63,7 +66,11 @@ class Timeouts(object): minutes (or 300 seconds). """ - return self._get("pageLoad") + # remove fallback when Firefox 56 is stable + try: + return self._get("pageLoad") + except KeyError: + return self._get("page load") @page_load.setter def page_load(self, sec): @@ -71,7 +78,11 @@ class Timeouts(object): to wait for the page loading to complete. """ - self._set("pageLoad", sec) + # remove fallback when Firefox 56 is stable + try: + self._set("pageLoad", sec) + except errors.InvalidArgumentException: + return self._set("page load", sec) @property def implicit(self): From 030755351f7b13570d2383772aa87f9baee56be4 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Sun, 26 Mar 2017 21:13:44 -0700 Subject: [PATCH 53/57] servo: Merge #16145 - Animation only restyles (from hiikezoe:animation-only-restyles); r=heycam This is a PR of https://bugzilla.mozilla.org/show_bug.cgi?id=1344966 --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes do not require tests because it's for stylo. Source-Repo: https://github.com/servo/servo Source-Revision: d77fceaf241843d0fee246c1c910072fe041a69e --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 9f2e870cb55520ba6deee3ba63b6b673d48bca2e --- servo/components/layout_thread/lib.rs | 5 +- servo/components/style/context.rs | 3 + servo/components/style/data.rs | 19 +- servo/components/style/dom.rs | 28 + servo/components/style/gecko/wrapper.rs | 13 + .../style/gecko_bindings/structs_debug.rs | 1239 ++++++++--------- .../style/gecko_bindings/structs_release.rs | 648 ++++----- servo/components/style/matching.rs | 66 +- servo/components/style/restyle_hints.rs | 8 +- servo/components/style/traversal.rs | 76 +- servo/ports/geckolib/glue.rs | 55 +- 11 files changed, 1081 insertions(+), 1079 deletions(-) diff --git a/servo/components/layout_thread/lib.rs b/servo/components/layout_thread/lib.rs index 31500461fa4f..2279b8f20587 100644 --- a/servo/components/layout_thread/lib.rs +++ b/servo/components/layout_thread/lib.rs @@ -120,7 +120,7 @@ use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets}; use style::stylist::Stylist; use style::thread_state; use style::timer::Timer; -use style::traversal::{DomTraversal, TraversalDriver}; +use style::traversal::{DomTraversal, TraversalDriver, TraversalFlags}; /// Information needed by the layout thread. pub struct LayoutThread { @@ -520,6 +520,7 @@ impl LayoutThread { local_context_creation_data: Mutex::new(thread_local_style_context_creation_data), timer: self.timer.clone(), quirks_mode: self.quirks_mode.unwrap(), + animation_only_restyle: false, }, image_cache_thread: Mutex::new(self.image_cache_thread.clone()), font_cache_thread: Mutex::new(self.font_cache_thread.clone()), @@ -1143,7 +1144,7 @@ impl LayoutThread { let stylist = &>::shared_context(&traversal).stylist; >::pre_traverse(element, stylist, /* skip_root = */ false) + DomTraversal>::pre_traverse(element, stylist, TraversalFlags::empty()) }; if token.should_traverse() { diff --git a/servo/components/style/context.rs b/servo/components/style/context.rs index 3a2926672acc..27943243ddfc 100644 --- a/servo/components/style/context.rs +++ b/servo/components/style/context.rs @@ -87,6 +87,9 @@ pub struct SharedStyleContext<'a> { /// The QuirksMode state which the document needs to be rendered with pub quirks_mode: QuirksMode, + + /// True if the traversal is processing only animation restyles. + pub animation_only_restyle: bool, } impl<'a> SharedStyleContext<'a> { diff --git a/servo/components/style/data.rs b/servo/components/style/data.rs index 096cd78c0f9e..5f714fcf99d3 100644 --- a/servo/components/style/data.rs +++ b/servo/components/style/data.rs @@ -9,7 +9,7 @@ use dom::TElement; use properties::ComputedValues; use properties::longhands::display::computed_value as display; -use restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint}; +use restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint}; use rule_tree::StrongRuleNode; use selector_parser::{PseudoElement, RestyleDamage, Snapshot}; use std::collections::HashMap; @@ -136,7 +136,12 @@ pub struct StoredRestyleHint(RestyleHint); impl StoredRestyleHint { /// Propagates this restyle hint to a child element. pub fn propagate(&self) -> Self { - StoredRestyleHint(if self.0.contains(RESTYLE_DESCENDANTS) { + // If we have RESTYLE_CSS_ANIMATIONS restyle hint, it means we are in the + // middle of an animation only restyle. In that case, we don't need to + // propagate any restyle hints. + StoredRestyleHint(if self.0.contains(RESTYLE_CSS_ANIMATIONS) { + RestyleHint::empty() + } else if self.0.contains(RESTYLE_DESCENDANTS) { RESTYLE_SELF | RESTYLE_DESCENDANTS } else { RestyleHint::empty() @@ -174,6 +179,16 @@ impl StoredRestyleHint { pub fn insert(&mut self, other: &Self) { self.0 |= other.0 } + + /// Remove animation restyle hint. + pub fn remove_animation_hint(&mut self) { + self.0.remove(RESTYLE_CSS_ANIMATIONS) + } + + /// Returns true if the hint has animation-only restyle. + pub fn has_animation_hint(&self) -> bool { + self.0.contains(RESTYLE_CSS_ANIMATIONS) + } } impl Default for StoredRestyleHint { diff --git a/servo/components/style/dom.rs b/servo/components/style/dom.rs index ac8ad3bd1092..cf64e2da6b84 100644 --- a/servo/components/style/dom.rs +++ b/servo/components/style/dom.rs @@ -309,6 +309,24 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre /// Only safe to call with exclusive access to the element. unsafe fn unset_dirty_descendants(&self); + /// Similar to the dirty_descendants but for representing a descendant of + /// the element needs to be updated in animation-only traversal. + fn has_animation_only_dirty_descendants(&self) -> bool { + false + } + + /// Flag that this element has a descendant for animation-only restyle processing. + /// + /// Only safe to call with exclusive access to the element. + unsafe fn set_animation_only_dirty_descendants(&self) { + } + + /// Flag that this element has no descendant for animation-only restyle processing. + /// + /// Only safe to call with exclusive access to the element. + unsafe fn unset_animation_only_dirty_descendants(&self) { + } + /// Atomically stores the number of children of this node that we will /// need to process during bottom-up traversal. fn store_children_to_process(&self, n: isize); @@ -354,6 +372,16 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre /// Returns true if the element has a CSS animation. fn has_css_animations(&self, _pseudo: Option<&PseudoElement>) -> bool; + + /// Returns true if the element has animation restyle hints. + fn has_animation_restyle_hints(&self) -> bool { + let data = match self.borrow_data() { + Some(d) => d, + None => return false, + }; + return data.get_restyle() + .map_or(false, |r| r.hint.has_animation_hint()); + } } /// TNode and TElement aren't Send because we want to be careful and explicit diff --git a/servo/components/style/gecko/wrapper.rs b/servo/components/style/gecko/wrapper.rs index bcdc81052aa5..3b0c5bf6cdba 100644 --- a/servo/components/style/gecko/wrapper.rs +++ b/servo/components/style/gecko/wrapper.rs @@ -42,6 +42,7 @@ use gecko_bindings::structs; use gecko_bindings::structs::{RawGeckoElement, RawGeckoNode}; use gecko_bindings::structs::{nsIAtom, nsIContent, nsStyleContext}; use gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel; +use gecko_bindings::structs::NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO; use gecko_bindings::structs::NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO; use gecko_bindings::structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE; use gecko_bindings::sugar::ownership::HasArcFFI; @@ -510,6 +511,18 @@ impl<'le> TElement for GeckoElement<'le> { self.unset_flags(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32) } + fn has_animation_only_dirty_descendants(&self) -> bool { + self.flags() & (NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32) != 0 + } + + unsafe fn set_animation_only_dirty_descendants(&self) { + self.set_flags(NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32) + } + + unsafe fn unset_animation_only_dirty_descendants(&self) { + self.unset_flags(NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32) + } + fn store_children_to_process(&self, _: isize) { // This is only used for bottom-up traversal, and is thus a no-op for Gecko. } diff --git a/servo/components/style/gecko_bindings/structs_debug.rs b/servo/components/style/gecko_bindings/structs_debug.rs index 4dfd92f3dfe9..99a64649299d 100644 --- a/servo/components/style/gecko_bindings/structs_debug.rs +++ b/servo/components/style/gecko_bindings/structs_debug.rs @@ -1632,14 +1632,14 @@ pub mod root { #[repr(C)] #[derive(Debug)] pub struct MutexImpl { - pub platformData_: [*mut ::std::os::raw::c_void; 8usize], + pub platformData_: [*mut ::std::os::raw::c_void; 5usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct MutexImpl_PlatformData([u8; 0]); #[test] fn bindgen_test_layout_MutexImpl() { - assert_eq!(::std::mem::size_of::() , 64usize , + assert_eq!(::std::mem::size_of::() , 40usize , concat ! ( "Size of: " , stringify ! ( MutexImpl ) )); assert_eq! (::std::mem::align_of::() , 8usize , @@ -3002,6 +3002,14 @@ pub mod root { #[allow(unused_imports)] use self::super::super::super::super::root; } + #[repr(u8)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum CSSStyleSheetParsingMode { + Author = 0, + User = 1, + Agent = 2, + EndGuard_ = 3, + } #[repr(C)] #[derive(Debug)] pub struct OriginAttributesDictionary { @@ -3061,18 +3069,6 @@ pub mod root { #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct Promise([u8; 0]); - pub mod workers { - #[allow(unused_imports)] - use self::super::super::super::super::root; - } - #[repr(u8)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum CSSStyleSheetParsingMode { - Author = 0, - User = 1, - Agent = 2, - EndGuard_ = 3, - } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct CSSRuleList([u8; 0]); @@ -4828,176 +4824,6 @@ pub mod root { #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct EventListenerManager([u8; 0]); - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct DeadlockDetector { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, - } - /** - * BlockingResourceBase - * Base class of resources that might block clients trying to acquire them. - * Does debugging and deadlock detection in DEBUG builds. - **/ - #[repr(C)] - #[derive(Debug)] - pub struct BlockingResourceBase { - /** - * mChainPrev - * A series of resource acquisitions creates a chain of orders. This - * chain is implemented as a linked list; |mChainPrev| points to the - * resource most recently Acquire()'d before this one. - **/ - pub mChainPrev: *mut root::mozilla::BlockingResourceBase, - /** - * mName - * A descriptive name for this resource. Used in error - * messages etc. - */ - pub mName: *const ::std::os::raw::c_char, - /** - * mType - * The more specific type of this resource. Used to implement - * special semantics (e.g., reentrancy of monitors). - **/ - pub mType: root::mozilla::BlockingResourceBase_BlockingResourceType, - /** - * mAcquired - * Indicates if this resource is currently acquired. - */ - pub mAcquired: root::mozilla::BlockingResourceBase_AcquisitionState, - } - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum BlockingResourceBase_BlockingResourceType { - eMutex = 0, - eReentrantMonitor = 1, - eCondVar = 2, - } - pub type BlockingResourceBase_DDT = - root::mozilla::DeadlockDetector; - pub type BlockingResourceBase_AcquisitionState = bool; - extern "C" { - #[link_name = - "_ZN7mozilla20BlockingResourceBase17kResourceTypeNameE"] - pub static mut BlockingResourceBase_kResourceTypeName: - [*const ::std::os::raw::c_char; 0usize]; - } - extern "C" { - #[link_name = "_ZN7mozilla20BlockingResourceBase9sCallOnceE"] - pub static mut BlockingResourceBase_sCallOnce: - root::PRCallOnceType; - } - extern "C" { - #[link_name = - "_ZN7mozilla20BlockingResourceBase26sResourceAcqnChainFrontTPIE"] - pub static mut BlockingResourceBase_sResourceAcqnChainFrontTPI: - ::std::os::raw::c_uint; - } - extern "C" { - #[link_name = - "_ZN7mozilla20BlockingResourceBase17sDeadlockDetectorE"] - pub static mut BlockingResourceBase_sDeadlockDetector: - *mut root::mozilla::BlockingResourceBase_DDT; - } - #[test] - fn bindgen_test_layout_BlockingResourceBase() { - assert_eq!(::std::mem::size_of::() , 24usize - , concat ! ( - "Size of: " , stringify ! ( BlockingResourceBase ) )); - assert_eq! (::std::mem::align_of::() , - 8usize , concat ! ( - "Alignment of " , stringify ! ( BlockingResourceBase ) - )); - assert_eq! (unsafe { - & ( * ( 0 as * const BlockingResourceBase ) ) . - mChainPrev as * const _ as usize } , 0usize , concat ! - ( - "Alignment of field: " , stringify ! ( - BlockingResourceBase ) , "::" , stringify ! ( - mChainPrev ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const BlockingResourceBase ) ) . mName - as * const _ as usize } , 8usize , concat ! ( - "Alignment of field: " , stringify ! ( - BlockingResourceBase ) , "::" , stringify ! ( mName ) - )); - assert_eq! (unsafe { - & ( * ( 0 as * const BlockingResourceBase ) ) . mType - as * const _ as usize } , 16usize , concat ! ( - "Alignment of field: " , stringify ! ( - BlockingResourceBase ) , "::" , stringify ! ( mType ) - )); - assert_eq! (unsafe { - & ( * ( 0 as * const BlockingResourceBase ) ) . - mAcquired as * const _ as usize } , 20usize , concat ! - ( - "Alignment of field: " , stringify ! ( - BlockingResourceBase ) , "::" , stringify ! ( - mAcquired ) )); - } - /** - * OffTheBooksMutex is identical to Mutex, except that OffTheBooksMutex doesn't - * include leak checking. Sometimes you want to intentionally "leak" a mutex - * until shutdown; in these cases, OffTheBooksMutex is for you. - */ - #[repr(C)] - #[derive(Debug)] - pub struct OffTheBooksMutex { - pub _base: root::mozilla::detail::MutexImpl, - pub _base_1: root::mozilla::BlockingResourceBase, - pub mOwningThread: *mut root::PRThread, - } - #[test] - fn bindgen_test_layout_OffTheBooksMutex() { - assert_eq!(::std::mem::size_of::() , 96usize , - concat ! ( - "Size of: " , stringify ! ( OffTheBooksMutex ) )); - assert_eq! (::std::mem::align_of::() , 8usize , - concat ! ( - "Alignment of " , stringify ! ( OffTheBooksMutex ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const OffTheBooksMutex ) ) . - mOwningThread as * const _ as usize } , 88usize , - concat ! ( - "Alignment of field: " , stringify ! ( - OffTheBooksMutex ) , "::" , stringify ! ( - mOwningThread ) )); - } - /** - * Mutex - * When possible, use MutexAutoLock/MutexAutoUnlock to lock/unlock this - * mutex within a scope, instead of calling Lock/Unlock directly. - */ - #[repr(C)] - #[derive(Debug)] - pub struct Mutex { - pub _base: root::mozilla::OffTheBooksMutex, - } - #[test] - fn bindgen_test_layout_Mutex() { - assert_eq!(::std::mem::size_of::() , 96usize , concat ! ( - "Size of: " , stringify ! ( Mutex ) )); - assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( - "Alignment of " , stringify ! ( Mutex ) )); - } - pub mod net { - #[allow(unused_imports)] - use self::super::super::super::root; - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum ReferrerPolicy { - RP_No_Referrer = 2, - RP_Origin = 3, - RP_No_Referrer_When_Downgrade = 1, - RP_Origin_When_Crossorigin = 4, - RP_Unsafe_URL = 5, - RP_Same_Origin = 6, - RP_Strict_Origin = 7, - RP_Strict_Origin_When_Cross_Origin = 8, - RP_Unset = 0, - } - } pub const FlushType_Frames: root::mozilla::FlushType = FlushType::Style; #[repr(u8)] @@ -5587,6 +5413,23 @@ pub mod root { assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( "Alignment of " , stringify ! ( StyleSheet ) )); } + pub mod net { + #[allow(unused_imports)] + use self::super::super::super::root; + #[repr(u32)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum ReferrerPolicy { + RP_No_Referrer = 2, + RP_Origin = 3, + RP_No_Referrer_When_Downgrade = 1, + RP_Origin_When_Crossorigin = 4, + RP_Unsafe_URL = 5, + RP_Same_Origin = 6, + RP_Strict_Origin = 7, + RP_Strict_Origin_When_Cross_Origin = 8, + RP_Unset = 0, + } + } #[repr(u8)] /** * Enumeration that represents one of the two supported style system backends. @@ -5699,7 +5542,7 @@ pub mod root { eUseCounter_ImageBitmapRenderingContext_TransferImageBitmap = 86, eUseCounter_URLCreateObjectURL_MediaStream = 87, eUseCounter_XMLBaseAttribute = 88, - eUseCounter_XMLBaseAttributeWithStyledElement = 89, + eUseCounter_XMLBaseAttributeForStyleAttr = 89, eUseCounter_Count = 90, } #[repr(u32)] @@ -6991,6 +6834,159 @@ pub mod root { #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct RestyleManager([u8; 0]); + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct DeadlockDetector { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, + } + /** + * BlockingResourceBase + * Base class of resources that might block clients trying to acquire them. + * Does debugging and deadlock detection in DEBUG builds. + **/ + #[repr(C)] + #[derive(Debug)] + pub struct BlockingResourceBase { + /** + * mChainPrev + * A series of resource acquisitions creates a chain of orders. This + * chain is implemented as a linked list; |mChainPrev| points to the + * resource most recently Acquire()'d before this one. + **/ + pub mChainPrev: *mut root::mozilla::BlockingResourceBase, + /** + * mName + * A descriptive name for this resource. Used in error + * messages etc. + */ + pub mName: *const ::std::os::raw::c_char, + /** + * mType + * The more specific type of this resource. Used to implement + * special semantics (e.g., reentrancy of monitors). + **/ + pub mType: root::mozilla::BlockingResourceBase_BlockingResourceType, + /** + * mAcquired + * Indicates if this resource is currently acquired. + */ + pub mAcquired: root::mozilla::BlockingResourceBase_AcquisitionState, + } + #[repr(u32)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum BlockingResourceBase_BlockingResourceType { + eMutex = 0, + eReentrantMonitor = 1, + eCondVar = 2, + } + pub type BlockingResourceBase_DDT = + root::mozilla::DeadlockDetector; + pub type BlockingResourceBase_AcquisitionState = bool; + extern "C" { + #[link_name = + "_ZN7mozilla20BlockingResourceBase17kResourceTypeNameE"] + pub static mut BlockingResourceBase_kResourceTypeName: + [*const ::std::os::raw::c_char; 0usize]; + } + extern "C" { + #[link_name = "_ZN7mozilla20BlockingResourceBase9sCallOnceE"] + pub static mut BlockingResourceBase_sCallOnce: + root::PRCallOnceType; + } + extern "C" { + #[link_name = + "_ZN7mozilla20BlockingResourceBase26sResourceAcqnChainFrontTPIE"] + pub static mut BlockingResourceBase_sResourceAcqnChainFrontTPI: + ::std::os::raw::c_uint; + } + extern "C" { + #[link_name = + "_ZN7mozilla20BlockingResourceBase17sDeadlockDetectorE"] + pub static mut BlockingResourceBase_sDeadlockDetector: + *mut root::mozilla::BlockingResourceBase_DDT; + } + #[test] + fn bindgen_test_layout_BlockingResourceBase() { + assert_eq!(::std::mem::size_of::() , 24usize + , concat ! ( + "Size of: " , stringify ! ( BlockingResourceBase ) )); + assert_eq! (::std::mem::align_of::() , + 8usize , concat ! ( + "Alignment of " , stringify ! ( BlockingResourceBase ) + )); + assert_eq! (unsafe { + & ( * ( 0 as * const BlockingResourceBase ) ) . + mChainPrev as * const _ as usize } , 0usize , concat ! + ( + "Alignment of field: " , stringify ! ( + BlockingResourceBase ) , "::" , stringify ! ( + mChainPrev ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const BlockingResourceBase ) ) . mName + as * const _ as usize } , 8usize , concat ! ( + "Alignment of field: " , stringify ! ( + BlockingResourceBase ) , "::" , stringify ! ( mName ) + )); + assert_eq! (unsafe { + & ( * ( 0 as * const BlockingResourceBase ) ) . mType + as * const _ as usize } , 16usize , concat ! ( + "Alignment of field: " , stringify ! ( + BlockingResourceBase ) , "::" , stringify ! ( mType ) + )); + assert_eq! (unsafe { + & ( * ( 0 as * const BlockingResourceBase ) ) . + mAcquired as * const _ as usize } , 20usize , concat ! + ( + "Alignment of field: " , stringify ! ( + BlockingResourceBase ) , "::" , stringify ! ( + mAcquired ) )); + } + /** + * OffTheBooksMutex is identical to Mutex, except that OffTheBooksMutex doesn't + * include leak checking. Sometimes you want to intentionally "leak" a mutex + * until shutdown; in these cases, OffTheBooksMutex is for you. + */ + #[repr(C)] + #[derive(Debug)] + pub struct OffTheBooksMutex { + pub _base: root::mozilla::detail::MutexImpl, + pub _base_1: root::mozilla::BlockingResourceBase, + pub mOwningThread: *mut root::PRThread, + } + #[test] + fn bindgen_test_layout_OffTheBooksMutex() { + assert_eq!(::std::mem::size_of::() , 72usize , + concat ! ( + "Size of: " , stringify ! ( OffTheBooksMutex ) )); + assert_eq! (::std::mem::align_of::() , 8usize , + concat ! ( + "Alignment of " , stringify ! ( OffTheBooksMutex ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const OffTheBooksMutex ) ) . + mOwningThread as * const _ as usize } , 64usize , + concat ! ( + "Alignment of field: " , stringify ! ( + OffTheBooksMutex ) , "::" , stringify ! ( + mOwningThread ) )); + } + /** + * Mutex + * When possible, use MutexAutoLock/MutexAutoUnlock to lock/unlock this + * mutex within a scope, instead of calling Lock/Unlock directly. + */ + #[repr(C)] + #[derive(Debug)] + pub struct Mutex { + pub _base: root::mozilla::OffTheBooksMutex, + } + #[test] + fn bindgen_test_layout_Mutex() { + assert_eq!(::std::mem::size_of::() , 72usize , concat ! ( + "Size of: " , stringify ! ( Mutex ) )); + assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( + "Alignment of " , stringify ! ( Mutex ) )); + } pub mod image { #[allow(unused_imports)] use self::super::super::super::root; @@ -8381,12 +8377,6 @@ pub mod root { pub type pair_first_type<_T1> = _T1; pub type pair_second_type<_T2> = _T2; #[repr(C)] - pub struct atomic<_Tp> { - pub _base: (), - pub _phantom_0: ::std::marker::PhantomData<_Tp>, - } - pub type atomic___base = [u8; 0usize]; - #[repr(C)] #[derive(Debug, Copy)] pub struct input_iterator_tag { pub _address: u8, @@ -8405,62 +8395,6 @@ pub mod root { fn clone(&self) -> Self { *self } } #[repr(C)] - #[derive(Debug, Copy)] - pub struct forward_iterator_tag { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_forward_iterator_tag() { - assert_eq!(::std::mem::size_of::() , 1usize - , concat ! ( - "Size of: " , stringify ! ( forward_iterator_tag ) )); - assert_eq! (::std::mem::align_of::() , - 1usize , concat ! ( - "Alignment of " , stringify ! ( forward_iterator_tag ) - )); - } - impl Clone for forward_iterator_tag { - fn clone(&self) -> Self { *self } - } - #[repr(C)] - #[derive(Debug, Copy)] - pub struct bidirectional_iterator_tag { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_bidirectional_iterator_tag() { - assert_eq!(::std::mem::size_of::() , - 1usize , concat ! ( - "Size of: " , stringify ! ( bidirectional_iterator_tag - ) )); - assert_eq! (::std::mem::align_of::() , - 1usize , concat ! ( - "Alignment of " , stringify ! ( - bidirectional_iterator_tag ) )); - } - impl Clone for bidirectional_iterator_tag { - fn clone(&self) -> Self { *self } - } - #[repr(C)] - #[derive(Debug, Copy)] - pub struct random_access_iterator_tag { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_random_access_iterator_tag() { - assert_eq!(::std::mem::size_of::() , - 1usize , concat ! ( - "Size of: " , stringify ! ( random_access_iterator_tag - ) )); - assert_eq! (::std::mem::align_of::() , - 1usize , concat ! ( - "Alignment of " , stringify ! ( - random_access_iterator_tag ) )); - } - impl Clone for random_access_iterator_tag { - fn clone(&self) -> Self { *self } - } - #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct iterator<_Category, _Tp, _Distance, _Pointer, _Reference> { pub _address: u8, @@ -8470,209 +8404,250 @@ pub mod root { pub _phantom_3: ::std::marker::PhantomData<_Pointer>, pub _phantom_4: ::std::marker::PhantomData<_Reference>, } + pub type iterator_iterator_category<_Category> = _Category; pub type iterator_value_type<_Tp> = _Tp; pub type iterator_difference_type<_Distance> = _Distance; pub type iterator_pointer<_Pointer> = _Pointer; pub type iterator_reference<_Reference> = _Reference; - pub type iterator_iterator_category<_Category> = _Category; #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct __bit_const_reference<_Cp> { - pub __seg_: root::std::__bit_const_reference___storage_pointer<_Cp>, - pub __mask_: root::std::__bit_const_reference___storage_type<_Cp>, + #[derive(Debug)] + pub struct atomic<_Tp> { + pub _M_i: _Tp, + } + pub mod chrono { + #[allow(unused_imports)] + use self::super::super::super::root; } - pub type __bit_const_reference___storage_type<_Cp> = _Cp; - pub type __bit_const_reference___storage_pointer<_Cp> = _Cp; } - pub type __int64_t = ::std::os::raw::c_longlong; - pub type __darwin_va_list = root::__builtin_va_list; - pub type __darwin_off_t = root::__int64_t; - pub type va_list = root::__darwin_va_list; - pub type fpos_t = root::__darwin_off_t; + pub mod __gnu_cxx { + #[allow(unused_imports)] + use self::super::super::root; + } + pub type __off_t = ::std::os::raw::c_long; + pub type __off64_t = ::std::os::raw::c_long; #[repr(C)] #[derive(Debug, Copy)] - pub struct __sbuf { - pub _base: *mut ::std::os::raw::c_uchar, - pub _size: ::std::os::raw::c_int, + pub struct _IO_FILE { + pub _flags: ::std::os::raw::c_int, + pub _IO_read_ptr: *mut ::std::os::raw::c_char, + pub _IO_read_end: *mut ::std::os::raw::c_char, + pub _IO_read_base: *mut ::std::os::raw::c_char, + pub _IO_write_base: *mut ::std::os::raw::c_char, + pub _IO_write_ptr: *mut ::std::os::raw::c_char, + pub _IO_write_end: *mut ::std::os::raw::c_char, + pub _IO_buf_base: *mut ::std::os::raw::c_char, + pub _IO_buf_end: *mut ::std::os::raw::c_char, + pub _IO_save_base: *mut ::std::os::raw::c_char, + pub _IO_backup_base: *mut ::std::os::raw::c_char, + pub _IO_save_end: *mut ::std::os::raw::c_char, + pub _markers: *mut root::_IO_marker, + pub _chain: *mut root::_IO_FILE, + pub _fileno: ::std::os::raw::c_int, + pub _flags2: ::std::os::raw::c_int, + pub _old_offset: root::__off_t, + pub _cur_column: ::std::os::raw::c_ushort, + pub _vtable_offset: ::std::os::raw::c_char, + pub _shortbuf: [::std::os::raw::c_char; 1usize], + pub _lock: *mut root::_IO_lock_t, + pub _offset: root::__off64_t, + pub __pad1: *mut ::std::os::raw::c_void, + pub __pad2: *mut ::std::os::raw::c_void, + pub __pad3: *mut ::std::os::raw::c_void, + pub __pad4: *mut ::std::os::raw::c_void, + pub __pad5: usize, + pub _mode: ::std::os::raw::c_int, + pub _unused2: [::std::os::raw::c_char; 20usize], } #[test] - fn bindgen_test_layout___sbuf() { - assert_eq!(::std::mem::size_of::<__sbuf>() , 16usize , concat ! ( - "Size of: " , stringify ! ( __sbuf ) )); - assert_eq! (::std::mem::align_of::<__sbuf>() , 8usize , concat ! ( - "Alignment of " , stringify ! ( __sbuf ) )); + fn bindgen_test_layout__IO_FILE() { + assert_eq!(::std::mem::size_of::<_IO_FILE>() , 216usize , concat ! ( + "Size of: " , stringify ! ( _IO_FILE ) )); + assert_eq! (::std::mem::align_of::<_IO_FILE>() , 8usize , concat ! ( + "Alignment of " , stringify ! ( _IO_FILE ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sbuf ) ) . _base as * const _ as + & ( * ( 0 as * const _IO_FILE ) ) . _flags as * const _ as usize } , 0usize , concat ! ( - "Alignment of field: " , stringify ! ( __sbuf ) , "::" , - stringify ! ( _base ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const __sbuf ) ) . _size as * const _ as - usize } , 8usize , concat ! ( - "Alignment of field: " , stringify ! ( __sbuf ) , "::" , - stringify ! ( _size ) )); - } - impl Clone for __sbuf { - fn clone(&self) -> Self { *self } - } - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct __sFILEX([u8; 0]); - #[repr(C)] - #[derive(Debug, Copy)] - pub struct __sFILE { - pub _p: *mut ::std::os::raw::c_uchar, - pub _r: ::std::os::raw::c_int, - pub _w: ::std::os::raw::c_int, - pub _flags: ::std::os::raw::c_short, - pub _file: ::std::os::raw::c_short, - pub _bf: root::__sbuf, - pub _lbfsize: ::std::os::raw::c_int, - pub _cookie: *mut ::std::os::raw::c_void, - pub _close: ::std::option::Option ::std::os::raw::c_int>, - pub _read: ::std::option::Option ::std::os::raw::c_int>, - pub _seek: ::std::option::Option ::std::os::raw::c_longlong>, - pub _write: ::std::option::Option ::std::os::raw::c_int>, - pub _ub: root::__sbuf, - pub _extra: *mut root::__sFILEX, - pub _ur: ::std::os::raw::c_int, - pub _ubuf: [::std::os::raw::c_uchar; 3usize], - pub _nbuf: [::std::os::raw::c_uchar; 1usize], - pub _lb: root::__sbuf, - pub _blksize: ::std::os::raw::c_int, - pub _offset: root::fpos_t, - } - #[test] - fn bindgen_test_layout___sFILE() { - assert_eq!(::std::mem::size_of::<__sFILE>() , 152usize , concat ! ( - "Size of: " , stringify ! ( __sFILE ) )); - assert_eq! (::std::mem::align_of::<__sFILE>() , 8usize , concat ! ( - "Alignment of " , stringify ! ( __sFILE ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _p as * const _ as - usize } , 0usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _p ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _r as * const _ as - usize } , 8usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _r ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _w as * const _ as - usize } , 12usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _w ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _flags as * const _ as - usize } , 16usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , stringify ! ( _flags ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _file as * const _ as - usize } , 18usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _file ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _IO_read_ptr as * + const _ as usize } , 8usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _IO_read_ptr ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _bf as * const _ as - usize } , 24usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _bf ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _IO_read_end as * + const _ as usize } , 16usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _IO_read_end ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _lbfsize as * const _ - as usize } , 40usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _lbfsize ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _IO_read_base as * + const _ as usize } , 24usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _IO_read_base ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _cookie as * const _ as - usize } , 48usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _cookie ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _IO_write_base as * + const _ as usize } , 32usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _IO_write_base ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _close as * const _ as - usize } , 56usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _close ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _IO_write_ptr as * + const _ as usize } , 40usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _IO_write_ptr ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _read as * const _ as - usize } , 64usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _read ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _IO_write_end as * + const _ as usize } , 48usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _IO_write_end ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _seek as * const _ as - usize } , 72usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _seek ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _IO_buf_base as * + const _ as usize } , 56usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _IO_buf_base ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _write as * const _ as - usize } , 80usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _write ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _IO_buf_end as * const + _ as usize } , 64usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _IO_buf_end ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _ub as * const _ as - usize } , 88usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _ub ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _IO_save_base as * + const _ as usize } , 72usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _IO_save_base ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _extra as * const _ as + & ( * ( 0 as * const _IO_FILE ) ) . _IO_backup_base as * + const _ as usize } , 80usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _IO_backup_base ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . _IO_save_end as * + const _ as usize } , 88usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _IO_save_end ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . _markers as * const _ + as usize } , 96usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _markers ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . _chain as * const _ as usize } , 104usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _extra ) )); + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _chain ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _ur as * const _ as - usize } , 112usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _ur ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _fileno as * const _ + as usize } , 112usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _fileno ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _ubuf as * const _ as - usize } , 116usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _ubuf ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _flags2 as * const _ + as usize } , 116usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _flags2 ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _nbuf as * const _ as - usize } , 119usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _nbuf ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _old_offset as * const + _ as usize } , 120usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _old_offset ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _lb as * const _ as - usize } , 120usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _lb ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _cur_column as * const + _ as usize } , 128usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _cur_column ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _blksize as * const _ - as usize } , 136usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , - stringify ! ( _blksize ) )); + & ( * ( 0 as * const _IO_FILE ) ) . _vtable_offset as * + const _ as usize } , 130usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _vtable_offset ) )); assert_eq! (unsafe { - & ( * ( 0 as * const __sFILE ) ) . _offset as * const _ as - usize } , 144usize , concat ! ( - "Alignment of field: " , stringify ! ( __sFILE ) , "::" , + & ( * ( 0 as * const _IO_FILE ) ) . _shortbuf as * const _ + as usize } , 131usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _shortbuf ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . _lock as * const _ as + usize } , 136usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _lock ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . _offset as * const _ + as usize } , 144usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , stringify ! ( _offset ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . __pad1 as * const _ as + usize } , 152usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( __pad1 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . __pad2 as * const _ as + usize } , 160usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( __pad2 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . __pad3 as * const _ as + usize } , 168usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( __pad3 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . __pad4 as * const _ as + usize } , 176usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( __pad4 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . __pad5 as * const _ as + usize } , 184usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( __pad5 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . _mode as * const _ as + usize } , 192usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _mode ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_FILE ) ) . _unused2 as * const _ + as usize } , 196usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" , + stringify ! ( _unused2 ) )); } - impl Clone for __sFILE { + impl Clone for _IO_FILE { + fn clone(&self) -> Self { *self } + } + pub type FILE = root::_IO_FILE; + pub type va_list = root::__builtin_va_list; + pub type _IO_lock_t = ::std::os::raw::c_void; + #[repr(C)] + #[derive(Debug, Copy)] + pub struct _IO_marker { + pub _next: *mut root::_IO_marker, + pub _sbuf: *mut root::_IO_FILE, + pub _pos: ::std::os::raw::c_int, + } + #[test] + fn bindgen_test_layout__IO_marker() { + assert_eq!(::std::mem::size_of::<_IO_marker>() , 24usize , concat ! ( + "Size of: " , stringify ! ( _IO_marker ) )); + assert_eq! (::std::mem::align_of::<_IO_marker>() , 8usize , concat ! ( + "Alignment of " , stringify ! ( _IO_marker ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_marker ) ) . _next as * const _ + as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_marker ) , "::" + , stringify ! ( _next ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_marker ) ) . _sbuf as * const _ + as usize } , 8usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_marker ) , "::" + , stringify ! ( _sbuf ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _IO_marker ) ) . _pos as * const _ as + usize } , 16usize , concat ! ( + "Alignment of field: " , stringify ! ( _IO_marker ) , "::" + , stringify ! ( _pos ) )); + } + impl Clone for _IO_marker { fn clone(&self) -> Self { *self } } - pub type FILE = root::__sFILE; /** * MozRefCountType is Mozilla's reference count type. * @@ -12177,7 +12152,7 @@ pub mod root { eImageBitmapRenderingContext_TransferImageBitmap = 39, eURLCreateObjectURL_MediaStream = 40, eXMLBaseAttribute = 41, - eXMLBaseAttributeWithStyledElement = 42, + eXMLBaseAttributeForStyleAttr = 42, eDeprecatedOperationCount = 43, } #[repr(u32)] @@ -12680,30 +12655,6 @@ pub mod root { #[derive(Debug, Copy, Clone)] pub struct nsISelection([u8; 0]); #[repr(C)] - #[derive(Debug, Copy)] - pub struct mozIDOMWindowProxy { - pub _base: root::nsISupports, - } - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct mozIDOMWindowProxy_COMTypeInfo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, - pub _phantom_1: ::std::marker::PhantomData, - } - #[test] - fn bindgen_test_layout_mozIDOMWindowProxy() { - assert_eq!(::std::mem::size_of::() , 8usize , - concat ! ( "Size of: " , stringify ! ( mozIDOMWindowProxy ) - )); - assert_eq! (::std::mem::align_of::() , 8usize , - concat ! ( - "Alignment of " , stringify ! ( mozIDOMWindowProxy ) )); - } - impl Clone for mozIDOMWindowProxy { - fn clone(&self) -> Self { *self } - } - #[repr(C)] #[derive(Debug)] pub struct nsPresContext { pub _base: root::nsIObserver, @@ -13786,157 +13737,12 @@ pub mod root { ! ( "Alignment of " , stringify ! ( ErrorNote ) )); } } - #[repr(C)] - #[derive(Debug, Copy)] - pub struct PRCallOnceType { - pub initialized: root::PRIntn, - pub inProgress: root::PRInt32, - pub status: root::PRStatus, - } - #[test] - fn bindgen_test_layout_PRCallOnceType() { - assert_eq!(::std::mem::size_of::() , 12usize , concat - ! ( "Size of: " , stringify ! ( PRCallOnceType ) )); - assert_eq! (::std::mem::align_of::() , 4usize , concat - ! ( "Alignment of " , stringify ! ( PRCallOnceType ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const PRCallOnceType ) ) . initialized as * - const _ as usize } , 0usize , concat ! ( - "Alignment of field: " , stringify ! ( PRCallOnceType ) , - "::" , stringify ! ( initialized ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const PRCallOnceType ) ) . inProgress as * - const _ as usize } , 4usize , concat ! ( - "Alignment of field: " , stringify ! ( PRCallOnceType ) , - "::" , stringify ! ( inProgress ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const PRCallOnceType ) ) . status as * - const _ as usize } , 8usize , concat ! ( - "Alignment of field: " , stringify ! ( PRCallOnceType ) , - "::" , stringify ! ( status ) )); - } - impl Clone for PRCallOnceType { - fn clone(&self) -> Self { *self } - } - #[repr(C)] - #[derive(Debug, Copy)] - pub struct nsIChannel { - pub _base: root::nsIRequest, - } - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct nsIChannel_COMTypeInfo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, - pub _phantom_1: ::std::marker::PhantomData, - } - pub const nsIChannel_LOAD_DOCUMENT_URI: root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_DOCUMENT_URI; - pub const nsIChannel_LOAD_RETARGETED_DOCUMENT_URI: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_RETARGETED_DOCUMENT_URI; - pub const nsIChannel_LOAD_REPLACE: root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_REPLACE; - pub const nsIChannel_LOAD_INITIAL_DOCUMENT_URI: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_INITIAL_DOCUMENT_URI; - pub const nsIChannel_LOAD_TARGETED: root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_TARGETED; - pub const nsIChannel_LOAD_CALL_CONTENT_SNIFFERS: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_CALL_CONTENT_SNIFFERS; - pub const nsIChannel_LOAD_CLASSIFY_URI: root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_CLASSIFY_URI; - pub const nsIChannel_LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE; - pub const nsIChannel_LOAD_EXPLICIT_CREDENTIALS: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_EXPLICIT_CREDENTIALS; - pub const nsIChannel_LOAD_BYPASS_SERVICE_WORKER: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_BYPASS_SERVICE_WORKER; #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum nsIChannel__bindgen_ty_1 { - LOAD_DOCUMENT_URI = 65536, - LOAD_RETARGETED_DOCUMENT_URI = 131072, - LOAD_REPLACE = 262144, - LOAD_INITIAL_DOCUMENT_URI = 524288, - LOAD_TARGETED = 1048576, - LOAD_CALL_CONTENT_SNIFFERS = 2097152, - LOAD_CLASSIFY_URI = 4194304, - LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE = 8388608, - LOAD_EXPLICIT_CREDENTIALS = 16777216, - LOAD_BYPASS_SERVICE_WORKER = 33554432, - } - pub const nsIChannel_DISPOSITION_INLINE: root::nsIChannel__bindgen_ty_2 = - nsIChannel__bindgen_ty_2::DISPOSITION_INLINE; - pub const nsIChannel_DISPOSITION_ATTACHMENT: - root::nsIChannel__bindgen_ty_2 = - nsIChannel__bindgen_ty_2::DISPOSITION_ATTACHMENT; - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum nsIChannel__bindgen_ty_2 { - DISPOSITION_INLINE = 0, - DISPOSITION_ATTACHMENT = 1, - } - #[test] - fn bindgen_test_layout_nsIChannel() { - assert_eq!(::std::mem::size_of::() , 8usize , concat ! ( - "Size of: " , stringify ! ( nsIChannel ) )); - assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( - "Alignment of " , stringify ! ( nsIChannel ) )); - } - impl Clone for nsIChannel { - fn clone(&self) -> Self { *self } - } - #[repr(C)] - #[derive(Debug, Copy)] - pub struct nsILoadContext { - pub _base: root::nsISupports, - } - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct nsILoadContext_COMTypeInfo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, - pub _phantom_1: ::std::marker::PhantomData, - } - #[test] - fn bindgen_test_layout_nsILoadContext() { - assert_eq!(::std::mem::size_of::() , 8usize , concat ! - ( "Size of: " , stringify ! ( nsILoadContext ) )); - assert_eq! (::std::mem::align_of::() , 8usize , concat - ! ( "Alignment of " , stringify ! ( nsILoadContext ) )); - } - impl Clone for nsILoadContext { - fn clone(&self) -> Self { *self } - } - #[repr(C)] - #[derive(Debug, Copy)] - pub struct nsIInterfaceRequestor { - pub _base: root::nsISupports, - } - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct nsIInterfaceRequestor_COMTypeInfo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, - pub _phantom_1: ::std::marker::PhantomData, - } - #[test] - fn bindgen_test_layout_nsIInterfaceRequestor() { - assert_eq!(::std::mem::size_of::() , 8usize , - concat ! ( - "Size of: " , stringify ! ( nsIInterfaceRequestor ) )); - assert_eq! (::std::mem::align_of::() , 8usize , - concat ! ( - "Alignment of " , stringify ! ( nsIInterfaceRequestor ) - )); - } - impl Clone for nsIInterfaceRequestor { - fn clone(&self) -> Self { *self } + pub enum nsCompatibility { + eCompatibility_FullStandards = 1, + eCompatibility_AlmostStandards = 2, + eCompatibility_NavQuirks = 3, } #[repr(C)] #[derive(Debug, Copy)] @@ -14285,6 +14091,82 @@ pub mod root { "Alignment of field: " , stringify ! ( nsINode ) , "::" , stringify ! ( mSlots ) )); } + #[repr(C)] + #[derive(Debug, Copy)] + pub struct nsIChannel { + pub _base: root::nsIRequest, + } + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct nsIChannel_COMTypeInfo { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, + pub _phantom_1: ::std::marker::PhantomData, + } + pub const nsIChannel_LOAD_DOCUMENT_URI: root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_DOCUMENT_URI; + pub const nsIChannel_LOAD_RETARGETED_DOCUMENT_URI: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_RETARGETED_DOCUMENT_URI; + pub const nsIChannel_LOAD_REPLACE: root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_REPLACE; + pub const nsIChannel_LOAD_INITIAL_DOCUMENT_URI: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_INITIAL_DOCUMENT_URI; + pub const nsIChannel_LOAD_TARGETED: root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_TARGETED; + pub const nsIChannel_LOAD_CALL_CONTENT_SNIFFERS: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_CALL_CONTENT_SNIFFERS; + pub const nsIChannel_LOAD_CLASSIFY_URI: root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_CLASSIFY_URI; + pub const nsIChannel_LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE; + pub const nsIChannel_LOAD_EXPLICIT_CREDENTIALS: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_EXPLICIT_CREDENTIALS; + pub const nsIChannel_LOAD_BYPASS_SERVICE_WORKER: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_BYPASS_SERVICE_WORKER; + #[repr(u32)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum nsIChannel__bindgen_ty_1 { + LOAD_DOCUMENT_URI = 65536, + LOAD_RETARGETED_DOCUMENT_URI = 131072, + LOAD_REPLACE = 262144, + LOAD_INITIAL_DOCUMENT_URI = 524288, + LOAD_TARGETED = 1048576, + LOAD_CALL_CONTENT_SNIFFERS = 2097152, + LOAD_CLASSIFY_URI = 4194304, + LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE = 8388608, + LOAD_EXPLICIT_CREDENTIALS = 16777216, + LOAD_BYPASS_SERVICE_WORKER = 33554432, + } + pub const nsIChannel_DISPOSITION_INLINE: root::nsIChannel__bindgen_ty_2 = + nsIChannel__bindgen_ty_2::DISPOSITION_INLINE; + pub const nsIChannel_DISPOSITION_ATTACHMENT: + root::nsIChannel__bindgen_ty_2 = + nsIChannel__bindgen_ty_2::DISPOSITION_ATTACHMENT; + #[repr(u32)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum nsIChannel__bindgen_ty_2 { + DISPOSITION_INLINE = 0, + DISPOSITION_ATTACHMENT = 1, + } + #[test] + fn bindgen_test_layout_nsIChannel() { + assert_eq!(::std::mem::size_of::() , 8usize , concat ! ( + "Size of: " , stringify ! ( nsIChannel ) )); + assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( + "Alignment of " , stringify ! ( nsIChannel ) )); + } + impl Clone for nsIChannel { + fn clone(&self) -> Self { *self } + } + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct nsILoadContext([u8; 0]); pub type nsSecurityFlags = u32; #[repr(C)] #[derive(Debug, Copy)] @@ -14393,6 +14275,31 @@ pub mod root { fn clone(&self) -> Self { *self } } #[repr(C)] + #[derive(Debug, Copy)] + pub struct nsIInterfaceRequestor { + pub _base: root::nsISupports, + } + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct nsIInterfaceRequestor_COMTypeInfo { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, + pub _phantom_1: ::std::marker::PhantomData, + } + #[test] + fn bindgen_test_layout_nsIInterfaceRequestor() { + assert_eq!(::std::mem::size_of::() , 8usize , + concat ! ( + "Size of: " , stringify ! ( nsIInterfaceRequestor ) )); + assert_eq! (::std::mem::align_of::() , 8usize , + concat ! ( + "Alignment of " , stringify ! ( nsIInterfaceRequestor ) + )); + } + impl Clone for nsIInterfaceRequestor { + fn clone(&self) -> Self { *self } + } + #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct nsIInputStream([u8; 0]); #[repr(C)] @@ -14419,13 +14326,6 @@ pub mod root { impl Clone for nsIStreamListener { fn clone(&self) -> Self { *self } } - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum nsCompatibility { - eCompatibility_FullStandards = 1, - eCompatibility_AlmostStandards = 2, - eCompatibility_NavQuirks = 3, - } #[repr(C)] #[derive(Debug)] pub struct nsAttrValue { @@ -15702,63 +15602,66 @@ pub mod root { #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct nsDOMMutationObserver([u8; 0]); - pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_LISTENERMANAGER; - pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_PROPERTIES; - pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_ANONYMOUS_ROOT; - pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE; - pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS_ROOT; - pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_FORCE_XBL_BINDINGS; - pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_MAY_BE_IN_BINDING_MNGR; - pub const NODE_IS_EDITABLE: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_EDITABLE; - pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS; - pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_IN_SHADOW_TREE; - pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_EMPTY_SELECTOR; - pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_SLOW_SELECTOR; - pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_EDGE_CHILD_SELECTOR; - pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS; - pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_ALL_SELECTOR_FLAGS; - pub const NODE_NEEDS_FRAME: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_NEEDS_FRAME; - pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_DESCENDANTS_NEED_FRAMES; - pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_ACCESSKEY; - pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_DIRECTION_RTL; - pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_DIRECTION_LTR; - pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_ALL_DIRECTION_FLAGS; - pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_CHROME_ONLY_ACCESS; - pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS; - pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1; - pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_2; - pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1; - pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_TYPE_SPECIFIC_BITS_OFFSET; + pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_HAS_LISTENERMANAGER; + pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_HAS_PROPERTIES; + pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_IS_ANONYMOUS_ROOT; + pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE; + pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_IS_NATIVE_ANONYMOUS_ROOT; + pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_FORCE_XBL_BINDINGS; + pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_MAY_BE_IN_BINDING_MNGR; + pub const NODE_IS_EDITABLE: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_IS_EDITABLE; + pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_IS_NATIVE_ANONYMOUS; + pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_IS_IN_SHADOW_TREE; + pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_HAS_EMPTY_SELECTOR; + pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_HAS_SLOW_SELECTOR; + pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_HAS_EDGE_CHILD_SELECTOR; + pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS; + pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_ALL_SELECTOR_FLAGS; + pub const NODE_NEEDS_FRAME: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_NEEDS_FRAME; + pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_DESCENDANTS_NEED_FRAMES; + pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_HAS_ACCESSKEY; + pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_HAS_DIRECTION_RTL; + pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_HAS_DIRECTION_LTR; + pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_ALL_DIRECTION_FLAGS; + pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_CHROME_ONLY_ACCESS; + pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS; + pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_SHARED_RESTYLE_BIT_1; + pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_SHARED_RESTYLE_BIT_2; + pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_SHARED_RESTYLE_BIT_1; + pub const NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO: + root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_SHARED_RESTYLE_BIT_2; + pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_118 = + _bindgen_ty_118::NODE_TYPE_SPECIFIC_BITS_OFFSET; #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum _bindgen_ty_28 { + pub enum _bindgen_ty_118 { NODE_HAS_LISTENERMANAGER = 4, NODE_HAS_PROPERTIES = 8, NODE_IS_ANONYMOUS_ROOT = 16, @@ -22650,6 +22553,38 @@ pub mod root { fn clone(&self) -> Self { *self } } #[repr(C)] + #[derive(Debug, Copy)] + pub struct PRCallOnceType { + pub initialized: root::PRIntn, + pub inProgress: root::PRInt32, + pub status: root::PRStatus, + } + #[test] + fn bindgen_test_layout_PRCallOnceType() { + assert_eq!(::std::mem::size_of::() , 12usize , concat + ! ( "Size of: " , stringify ! ( PRCallOnceType ) )); + assert_eq! (::std::mem::align_of::() , 4usize , concat + ! ( "Alignment of " , stringify ! ( PRCallOnceType ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const PRCallOnceType ) ) . initialized as * + const _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( PRCallOnceType ) , + "::" , stringify ! ( initialized ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const PRCallOnceType ) ) . inProgress as * + const _ as usize } , 4usize , concat ! ( + "Alignment of field: " , stringify ! ( PRCallOnceType ) , + "::" , stringify ! ( inProgress ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const PRCallOnceType ) ) . status as * + const _ as usize } , 8usize , concat ! ( + "Alignment of field: " , stringify ! ( PRCallOnceType ) , + "::" , stringify ! ( status ) )); + } + impl Clone for PRCallOnceType { + fn clone(&self) -> Self { *self } + } + #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct imgCacheValidator([u8; 0]); #[repr(C)] @@ -22714,7 +22649,7 @@ pub mod root { pub type imgRequest_HasThreadSafeRefCnt = root::mozilla::TrueType; #[test] fn bindgen_test_layout_imgRequest() { - assert_eq!(::std::mem::size_of::() , 440usize , concat ! ( + assert_eq!(::std::mem::size_of::() , 416usize , concat ! ( "Size of: " , stringify ! ( imgRequest ) )); assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( "Alignment of " , stringify ! ( imgRequest ) )); diff --git a/servo/components/style/gecko_bindings/structs_release.rs b/servo/components/style/gecko_bindings/structs_release.rs index 661b28a18f92..9ae2d19da522 100644 --- a/servo/components/style/gecko_bindings/structs_release.rs +++ b/servo/components/style/gecko_bindings/structs_release.rs @@ -1632,14 +1632,14 @@ pub mod root { #[repr(C)] #[derive(Debug)] pub struct MutexImpl { - pub platformData_: [*mut ::std::os::raw::c_void; 8usize], + pub platformData_: [*mut ::std::os::raw::c_void; 5usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct MutexImpl_PlatformData([u8; 0]); #[test] fn bindgen_test_layout_MutexImpl() { - assert_eq!(::std::mem::size_of::() , 64usize , + assert_eq!(::std::mem::size_of::() , 40usize , concat ! ( "Size of: " , stringify ! ( MutexImpl ) )); assert_eq! (::std::mem::align_of::() , 8usize , @@ -2993,6 +2993,14 @@ pub mod root { #[allow(unused_imports)] use self::super::super::super::super::root; } + #[repr(u8)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum CSSStyleSheetParsingMode { + Author = 0, + User = 1, + Agent = 2, + EndGuard_ = 3, + } #[repr(C)] #[derive(Debug)] pub struct OriginAttributesDictionary { @@ -3052,18 +3060,6 @@ pub mod root { #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct Promise([u8; 0]); - pub mod workers { - #[allow(unused_imports)] - use self::super::super::super::super::root; - } - #[repr(u8)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum CSSStyleSheetParsingMode { - Author = 0, - User = 1, - Agent = 2, - EndGuard_ = 3, - } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct CSSRuleList([u8; 0]); @@ -4774,92 +4770,6 @@ pub mod root { #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct EventListenerManager([u8; 0]); - /** - * BlockingResourceBase - * Base class of resources that might block clients trying to acquire them. - * Does debugging and deadlock detection in DEBUG builds. - **/ - #[repr(C)] - #[derive(Debug)] - pub struct BlockingResourceBase { - pub _address: u8, - } - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum BlockingResourceBase_BlockingResourceType { - eMutex = 0, - eReentrantMonitor = 1, - eCondVar = 2, - } - extern "C" { - #[link_name = - "_ZN7mozilla20BlockingResourceBase17kResourceTypeNameE"] - pub static mut BlockingResourceBase_kResourceTypeName: - [*const ::std::os::raw::c_char; 0usize]; - } - #[test] - fn bindgen_test_layout_BlockingResourceBase() { - assert_eq!(::std::mem::size_of::() , 1usize - , concat ! ( - "Size of: " , stringify ! ( BlockingResourceBase ) )); - assert_eq! (::std::mem::align_of::() , - 1usize , concat ! ( - "Alignment of " , stringify ! ( BlockingResourceBase ) - )); - } - /** - * OffTheBooksMutex is identical to Mutex, except that OffTheBooksMutex doesn't - * include leak checking. Sometimes you want to intentionally "leak" a mutex - * until shutdown; in these cases, OffTheBooksMutex is for you. - */ - #[repr(C)] - #[derive(Debug)] - pub struct OffTheBooksMutex { - pub _base: root::mozilla::detail::MutexImpl, - } - #[test] - fn bindgen_test_layout_OffTheBooksMutex() { - assert_eq!(::std::mem::size_of::() , 64usize , - concat ! ( - "Size of: " , stringify ! ( OffTheBooksMutex ) )); - assert_eq! (::std::mem::align_of::() , 8usize , - concat ! ( - "Alignment of " , stringify ! ( OffTheBooksMutex ) )); - } - /** - * Mutex - * When possible, use MutexAutoLock/MutexAutoUnlock to lock/unlock this - * mutex within a scope, instead of calling Lock/Unlock directly. - */ - #[repr(C)] - #[derive(Debug)] - pub struct Mutex { - pub _base: root::mozilla::OffTheBooksMutex, - } - #[test] - fn bindgen_test_layout_Mutex() { - assert_eq!(::std::mem::size_of::() , 64usize , concat ! ( - "Size of: " , stringify ! ( Mutex ) )); - assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( - "Alignment of " , stringify ! ( Mutex ) )); - } - pub mod net { - #[allow(unused_imports)] - use self::super::super::super::root; - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum ReferrerPolicy { - RP_No_Referrer = 2, - RP_Origin = 3, - RP_No_Referrer_When_Downgrade = 1, - RP_Origin_When_Crossorigin = 4, - RP_Unsafe_URL = 5, - RP_Same_Origin = 6, - RP_Strict_Origin = 7, - RP_Strict_Origin_When_Cross_Origin = 8, - RP_Unset = 0, - } - } pub const FlushType_Frames: root::mozilla::FlushType = FlushType::Style; #[repr(u8)] @@ -5418,6 +5328,23 @@ pub mod root { assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( "Alignment of " , stringify ! ( StyleSheet ) )); } + pub mod net { + #[allow(unused_imports)] + use self::super::super::super::root; + #[repr(u32)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum ReferrerPolicy { + RP_No_Referrer = 2, + RP_Origin = 3, + RP_No_Referrer_When_Downgrade = 1, + RP_Origin_When_Crossorigin = 4, + RP_Unsafe_URL = 5, + RP_Same_Origin = 6, + RP_Strict_Origin = 7, + RP_Strict_Origin_When_Cross_Origin = 8, + RP_Unset = 0, + } + } #[repr(u8)] /** * Enumeration that represents one of the two supported style system backends. @@ -5530,7 +5457,7 @@ pub mod root { eUseCounter_ImageBitmapRenderingContext_TransferImageBitmap = 86, eUseCounter_URLCreateObjectURL_MediaStream = 87, eUseCounter_XMLBaseAttribute = 88, - eUseCounter_XMLBaseAttributeWithStyledElement = 89, + eUseCounter_XMLBaseAttributeForStyleAttr = 89, eUseCounter_Count = 90, } #[repr(u32)] @@ -6795,6 +6722,75 @@ pub mod root { #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct RestyleManager([u8; 0]); + /** + * BlockingResourceBase + * Base class of resources that might block clients trying to acquire them. + * Does debugging and deadlock detection in DEBUG builds. + **/ + #[repr(C)] + #[derive(Debug)] + pub struct BlockingResourceBase { + pub _address: u8, + } + #[repr(u32)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum BlockingResourceBase_BlockingResourceType { + eMutex = 0, + eReentrantMonitor = 1, + eCondVar = 2, + } + extern "C" { + #[link_name = + "_ZN7mozilla20BlockingResourceBase17kResourceTypeNameE"] + pub static mut BlockingResourceBase_kResourceTypeName: + [*const ::std::os::raw::c_char; 0usize]; + } + #[test] + fn bindgen_test_layout_BlockingResourceBase() { + assert_eq!(::std::mem::size_of::() , 1usize + , concat ! ( + "Size of: " , stringify ! ( BlockingResourceBase ) )); + assert_eq! (::std::mem::align_of::() , + 1usize , concat ! ( + "Alignment of " , stringify ! ( BlockingResourceBase ) + )); + } + /** + * OffTheBooksMutex is identical to Mutex, except that OffTheBooksMutex doesn't + * include leak checking. Sometimes you want to intentionally "leak" a mutex + * until shutdown; in these cases, OffTheBooksMutex is for you. + */ + #[repr(C)] + #[derive(Debug)] + pub struct OffTheBooksMutex { + pub _base: root::mozilla::detail::MutexImpl, + } + #[test] + fn bindgen_test_layout_OffTheBooksMutex() { + assert_eq!(::std::mem::size_of::() , 40usize , + concat ! ( + "Size of: " , stringify ! ( OffTheBooksMutex ) )); + assert_eq! (::std::mem::align_of::() , 8usize , + concat ! ( + "Alignment of " , stringify ! ( OffTheBooksMutex ) )); + } + /** + * Mutex + * When possible, use MutexAutoLock/MutexAutoUnlock to lock/unlock this + * mutex within a scope, instead of calling Lock/Unlock directly. + */ + #[repr(C)] + #[derive(Debug)] + pub struct Mutex { + pub _base: root::mozilla::OffTheBooksMutex, + } + #[test] + fn bindgen_test_layout_Mutex() { + assert_eq!(::std::mem::size_of::() , 40usize , concat ! ( + "Size of: " , stringify ! ( Mutex ) )); + assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( + "Alignment of " , stringify ! ( Mutex ) )); + } pub mod image { #[allow(unused_imports)] use self::super::super::super::root; @@ -8185,12 +8181,6 @@ pub mod root { pub type pair_first_type<_T1> = _T1; pub type pair_second_type<_T2> = _T2; #[repr(C)] - pub struct atomic<_Tp> { - pub _base: (), - pub _phantom_0: ::std::marker::PhantomData<_Tp>, - } - pub type atomic___base = [u8; 0usize]; - #[repr(C)] #[derive(Debug, Copy)] pub struct input_iterator_tag { pub _address: u8, @@ -8209,62 +8199,6 @@ pub mod root { fn clone(&self) -> Self { *self } } #[repr(C)] - #[derive(Debug, Copy)] - pub struct forward_iterator_tag { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_forward_iterator_tag() { - assert_eq!(::std::mem::size_of::() , 1usize - , concat ! ( - "Size of: " , stringify ! ( forward_iterator_tag ) )); - assert_eq! (::std::mem::align_of::() , - 1usize , concat ! ( - "Alignment of " , stringify ! ( forward_iterator_tag ) - )); - } - impl Clone for forward_iterator_tag { - fn clone(&self) -> Self { *self } - } - #[repr(C)] - #[derive(Debug, Copy)] - pub struct bidirectional_iterator_tag { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_bidirectional_iterator_tag() { - assert_eq!(::std::mem::size_of::() , - 1usize , concat ! ( - "Size of: " , stringify ! ( bidirectional_iterator_tag - ) )); - assert_eq! (::std::mem::align_of::() , - 1usize , concat ! ( - "Alignment of " , stringify ! ( - bidirectional_iterator_tag ) )); - } - impl Clone for bidirectional_iterator_tag { - fn clone(&self) -> Self { *self } - } - #[repr(C)] - #[derive(Debug, Copy)] - pub struct random_access_iterator_tag { - pub _address: u8, - } - #[test] - fn bindgen_test_layout_random_access_iterator_tag() { - assert_eq!(::std::mem::size_of::() , - 1usize , concat ! ( - "Size of: " , stringify ! ( random_access_iterator_tag - ) )); - assert_eq! (::std::mem::align_of::() , - 1usize , concat ! ( - "Alignment of " , stringify ! ( - random_access_iterator_tag ) )); - } - impl Clone for random_access_iterator_tag { - fn clone(&self) -> Self { *self } - } - #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct iterator<_Category, _Tp, _Distance, _Pointer, _Reference> { pub _address: u8, @@ -8274,22 +8208,22 @@ pub mod root { pub _phantom_3: ::std::marker::PhantomData<_Pointer>, pub _phantom_4: ::std::marker::PhantomData<_Reference>, } + pub type iterator_iterator_category<_Category> = _Category; pub type iterator_value_type<_Tp> = _Tp; pub type iterator_difference_type<_Distance> = _Distance; pub type iterator_pointer<_Pointer> = _Pointer; pub type iterator_reference<_Reference> = _Reference; - pub type iterator_iterator_category<_Category> = _Category; #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct __bit_const_reference<_Cp> { - pub __seg_: root::std::__bit_const_reference___storage_pointer<_Cp>, - pub __mask_: root::std::__bit_const_reference___storage_type<_Cp>, + #[derive(Debug)] + pub struct atomic<_Tp> { + pub _M_i: _Tp, } - pub type __bit_const_reference___storage_type<_Cp> = _Cp; - pub type __bit_const_reference___storage_pointer<_Cp> = _Cp; } - pub type __darwin_va_list = root::__builtin_va_list; - pub type va_list = root::__darwin_va_list; + pub mod __gnu_cxx { + #[allow(unused_imports)] + use self::super::super::root; + } + pub type va_list = root::__builtin_va_list; /** * MozRefCountType is Mozilla's reference count type. * @@ -11754,7 +11688,7 @@ pub mod root { eImageBitmapRenderingContext_TransferImageBitmap = 39, eURLCreateObjectURL_MediaStream = 40, eXMLBaseAttribute = 41, - eXMLBaseAttributeWithStyledElement = 42, + eXMLBaseAttributeForStyleAttr = 42, eDeprecatedOperationCount = 43, } #[repr(u32)] @@ -12257,30 +12191,6 @@ pub mod root { #[derive(Debug, Copy, Clone)] pub struct nsISelection([u8; 0]); #[repr(C)] - #[derive(Debug, Copy)] - pub struct mozIDOMWindowProxy { - pub _base: root::nsISupports, - } - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct mozIDOMWindowProxy_COMTypeInfo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, - pub _phantom_1: ::std::marker::PhantomData, - } - #[test] - fn bindgen_test_layout_mozIDOMWindowProxy() { - assert_eq!(::std::mem::size_of::() , 8usize , - concat ! ( "Size of: " , stringify ! ( mozIDOMWindowProxy ) - )); - assert_eq! (::std::mem::align_of::() , 8usize , - concat ! ( - "Alignment of " , stringify ! ( mozIDOMWindowProxy ) )); - } - impl Clone for mozIDOMWindowProxy { - fn clone(&self) -> Self { *self } - } - #[repr(C)] #[derive(Debug)] pub struct nsPresContext { pub _base: root::nsIObserver, @@ -13303,125 +13213,12 @@ pub mod root { ! ( "Alignment of " , stringify ! ( ErrorNote ) )); } } - #[repr(C)] - #[derive(Debug, Copy)] - pub struct nsIChannel { - pub _base: root::nsIRequest, - } - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct nsIChannel_COMTypeInfo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, - pub _phantom_1: ::std::marker::PhantomData, - } - pub const nsIChannel_LOAD_DOCUMENT_URI: root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_DOCUMENT_URI; - pub const nsIChannel_LOAD_RETARGETED_DOCUMENT_URI: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_RETARGETED_DOCUMENT_URI; - pub const nsIChannel_LOAD_REPLACE: root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_REPLACE; - pub const nsIChannel_LOAD_INITIAL_DOCUMENT_URI: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_INITIAL_DOCUMENT_URI; - pub const nsIChannel_LOAD_TARGETED: root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_TARGETED; - pub const nsIChannel_LOAD_CALL_CONTENT_SNIFFERS: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_CALL_CONTENT_SNIFFERS; - pub const nsIChannel_LOAD_CLASSIFY_URI: root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_CLASSIFY_URI; - pub const nsIChannel_LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE; - pub const nsIChannel_LOAD_EXPLICIT_CREDENTIALS: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_EXPLICIT_CREDENTIALS; - pub const nsIChannel_LOAD_BYPASS_SERVICE_WORKER: - root::nsIChannel__bindgen_ty_1 = - nsIChannel__bindgen_ty_1::LOAD_BYPASS_SERVICE_WORKER; #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum nsIChannel__bindgen_ty_1 { - LOAD_DOCUMENT_URI = 65536, - LOAD_RETARGETED_DOCUMENT_URI = 131072, - LOAD_REPLACE = 262144, - LOAD_INITIAL_DOCUMENT_URI = 524288, - LOAD_TARGETED = 1048576, - LOAD_CALL_CONTENT_SNIFFERS = 2097152, - LOAD_CLASSIFY_URI = 4194304, - LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE = 8388608, - LOAD_EXPLICIT_CREDENTIALS = 16777216, - LOAD_BYPASS_SERVICE_WORKER = 33554432, - } - pub const nsIChannel_DISPOSITION_INLINE: root::nsIChannel__bindgen_ty_2 = - nsIChannel__bindgen_ty_2::DISPOSITION_INLINE; - pub const nsIChannel_DISPOSITION_ATTACHMENT: - root::nsIChannel__bindgen_ty_2 = - nsIChannel__bindgen_ty_2::DISPOSITION_ATTACHMENT; - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum nsIChannel__bindgen_ty_2 { - DISPOSITION_INLINE = 0, - DISPOSITION_ATTACHMENT = 1, - } - #[test] - fn bindgen_test_layout_nsIChannel() { - assert_eq!(::std::mem::size_of::() , 8usize , concat ! ( - "Size of: " , stringify ! ( nsIChannel ) )); - assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( - "Alignment of " , stringify ! ( nsIChannel ) )); - } - impl Clone for nsIChannel { - fn clone(&self) -> Self { *self } - } - #[repr(C)] - #[derive(Debug, Copy)] - pub struct nsILoadContext { - pub _base: root::nsISupports, - } - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct nsILoadContext_COMTypeInfo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, - pub _phantom_1: ::std::marker::PhantomData, - } - #[test] - fn bindgen_test_layout_nsILoadContext() { - assert_eq!(::std::mem::size_of::() , 8usize , concat ! - ( "Size of: " , stringify ! ( nsILoadContext ) )); - assert_eq! (::std::mem::align_of::() , 8usize , concat - ! ( "Alignment of " , stringify ! ( nsILoadContext ) )); - } - impl Clone for nsILoadContext { - fn clone(&self) -> Self { *self } - } - #[repr(C)] - #[derive(Debug, Copy)] - pub struct nsIInterfaceRequestor { - pub _base: root::nsISupports, - } - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct nsIInterfaceRequestor_COMTypeInfo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, - pub _phantom_1: ::std::marker::PhantomData, - } - #[test] - fn bindgen_test_layout_nsIInterfaceRequestor() { - assert_eq!(::std::mem::size_of::() , 8usize , - concat ! ( - "Size of: " , stringify ! ( nsIInterfaceRequestor ) )); - assert_eq! (::std::mem::align_of::() , 8usize , - concat ! ( - "Alignment of " , stringify ! ( nsIInterfaceRequestor ) - )); - } - impl Clone for nsIInterfaceRequestor { - fn clone(&self) -> Self { *self } + pub enum nsCompatibility { + eCompatibility_FullStandards = 1, + eCompatibility_AlmostStandards = 2, + eCompatibility_NavQuirks = 3, } #[repr(C)] #[derive(Debug, Copy)] @@ -13770,6 +13567,82 @@ pub mod root { "Alignment of field: " , stringify ! ( nsINode ) , "::" , stringify ! ( mSlots ) )); } + #[repr(C)] + #[derive(Debug, Copy)] + pub struct nsIChannel { + pub _base: root::nsIRequest, + } + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct nsIChannel_COMTypeInfo { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, + pub _phantom_1: ::std::marker::PhantomData, + } + pub const nsIChannel_LOAD_DOCUMENT_URI: root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_DOCUMENT_URI; + pub const nsIChannel_LOAD_RETARGETED_DOCUMENT_URI: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_RETARGETED_DOCUMENT_URI; + pub const nsIChannel_LOAD_REPLACE: root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_REPLACE; + pub const nsIChannel_LOAD_INITIAL_DOCUMENT_URI: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_INITIAL_DOCUMENT_URI; + pub const nsIChannel_LOAD_TARGETED: root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_TARGETED; + pub const nsIChannel_LOAD_CALL_CONTENT_SNIFFERS: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_CALL_CONTENT_SNIFFERS; + pub const nsIChannel_LOAD_CLASSIFY_URI: root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_CLASSIFY_URI; + pub const nsIChannel_LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE; + pub const nsIChannel_LOAD_EXPLICIT_CREDENTIALS: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_EXPLICIT_CREDENTIALS; + pub const nsIChannel_LOAD_BYPASS_SERVICE_WORKER: + root::nsIChannel__bindgen_ty_1 = + nsIChannel__bindgen_ty_1::LOAD_BYPASS_SERVICE_WORKER; + #[repr(u32)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum nsIChannel__bindgen_ty_1 { + LOAD_DOCUMENT_URI = 65536, + LOAD_RETARGETED_DOCUMENT_URI = 131072, + LOAD_REPLACE = 262144, + LOAD_INITIAL_DOCUMENT_URI = 524288, + LOAD_TARGETED = 1048576, + LOAD_CALL_CONTENT_SNIFFERS = 2097152, + LOAD_CLASSIFY_URI = 4194304, + LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE = 8388608, + LOAD_EXPLICIT_CREDENTIALS = 16777216, + LOAD_BYPASS_SERVICE_WORKER = 33554432, + } + pub const nsIChannel_DISPOSITION_INLINE: root::nsIChannel__bindgen_ty_2 = + nsIChannel__bindgen_ty_2::DISPOSITION_INLINE; + pub const nsIChannel_DISPOSITION_ATTACHMENT: + root::nsIChannel__bindgen_ty_2 = + nsIChannel__bindgen_ty_2::DISPOSITION_ATTACHMENT; + #[repr(u32)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum nsIChannel__bindgen_ty_2 { + DISPOSITION_INLINE = 0, + DISPOSITION_ATTACHMENT = 1, + } + #[test] + fn bindgen_test_layout_nsIChannel() { + assert_eq!(::std::mem::size_of::() , 8usize , concat ! ( + "Size of: " , stringify ! ( nsIChannel ) )); + assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( + "Alignment of " , stringify ! ( nsIChannel ) )); + } + impl Clone for nsIChannel { + fn clone(&self) -> Self { *self } + } + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct nsILoadContext([u8; 0]); pub type nsSecurityFlags = u32; #[repr(C)] #[derive(Debug, Copy)] @@ -13878,6 +13751,31 @@ pub mod root { fn clone(&self) -> Self { *self } } #[repr(C)] + #[derive(Debug, Copy)] + pub struct nsIInterfaceRequestor { + pub _base: root::nsISupports, + } + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct nsIInterfaceRequestor_COMTypeInfo { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, + pub _phantom_1: ::std::marker::PhantomData, + } + #[test] + fn bindgen_test_layout_nsIInterfaceRequestor() { + assert_eq!(::std::mem::size_of::() , 8usize , + concat ! ( + "Size of: " , stringify ! ( nsIInterfaceRequestor ) )); + assert_eq! (::std::mem::align_of::() , 8usize , + concat ! ( + "Alignment of " , stringify ! ( nsIInterfaceRequestor ) + )); + } + impl Clone for nsIInterfaceRequestor { + fn clone(&self) -> Self { *self } + } + #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct nsIInputStream([u8; 0]); #[repr(C)] @@ -13904,13 +13802,6 @@ pub mod root { impl Clone for nsIStreamListener { fn clone(&self) -> Self { *self } } - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum nsCompatibility { - eCompatibility_FullStandards = 1, - eCompatibility_AlmostStandards = 2, - eCompatibility_NavQuirks = 3, - } #[repr(C)] #[derive(Debug)] pub struct nsAttrValue { @@ -15159,63 +15050,66 @@ pub mod root { #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct nsDOMMutationObserver([u8; 0]); - pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_LISTENERMANAGER; - pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_PROPERTIES; - pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_ANONYMOUS_ROOT; - pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE; - pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS_ROOT; - pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_FORCE_XBL_BINDINGS; - pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_MAY_BE_IN_BINDING_MNGR; - pub const NODE_IS_EDITABLE: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_EDITABLE; - pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS; - pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_IN_SHADOW_TREE; - pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_EMPTY_SELECTOR; - pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_SLOW_SELECTOR; - pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_EDGE_CHILD_SELECTOR; - pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS; - pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_ALL_SELECTOR_FLAGS; - pub const NODE_NEEDS_FRAME: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_NEEDS_FRAME; - pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_DESCENDANTS_NEED_FRAMES; - pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_ACCESSKEY; - pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_DIRECTION_RTL; - pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_HAS_DIRECTION_LTR; - pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_ALL_DIRECTION_FLAGS; - pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_CHROME_ONLY_ACCESS; - pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS; - pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1; - pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_2; - pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1; - pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_28 = - _bindgen_ty_28::NODE_TYPE_SPECIFIC_BITS_OFFSET; + pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_HAS_LISTENERMANAGER; + pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_HAS_PROPERTIES; + pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_IS_ANONYMOUS_ROOT; + pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE; + pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_IS_NATIVE_ANONYMOUS_ROOT; + pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_FORCE_XBL_BINDINGS; + pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_MAY_BE_IN_BINDING_MNGR; + pub const NODE_IS_EDITABLE: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_IS_EDITABLE; + pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_IS_NATIVE_ANONYMOUS; + pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_IS_IN_SHADOW_TREE; + pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_HAS_EMPTY_SELECTOR; + pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_HAS_SLOW_SELECTOR; + pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_HAS_EDGE_CHILD_SELECTOR; + pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS; + pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_ALL_SELECTOR_FLAGS; + pub const NODE_NEEDS_FRAME: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_NEEDS_FRAME; + pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_DESCENDANTS_NEED_FRAMES; + pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_HAS_ACCESSKEY; + pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_HAS_DIRECTION_RTL; + pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_HAS_DIRECTION_LTR; + pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_ALL_DIRECTION_FLAGS; + pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_CHROME_ONLY_ACCESS; + pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS; + pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_1; + pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_2; + pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_1; + pub const NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO: + root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_2; + pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_105 = + _bindgen_ty_105::NODE_TYPE_SPECIFIC_BITS_OFFSET; #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum _bindgen_ty_28 { + pub enum _bindgen_ty_105 { NODE_HAS_LISTENERMANAGER = 4, NODE_HAS_PROPERTIES = 8, NODE_IS_ANONYMOUS_ROOT = 16, @@ -22096,7 +21990,7 @@ pub mod root { pub type imgRequest_HasThreadSafeRefCnt = root::mozilla::TrueType; #[test] fn bindgen_test_layout_imgRequest() { - assert_eq!(::std::mem::size_of::() , 400usize , concat ! ( + assert_eq!(::std::mem::size_of::() , 376usize , concat ! ( "Size of: " , stringify ! ( imgRequest ) )); assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( "Alignment of " , stringify ! ( imgRequest ) )); diff --git a/servo/components/style/matching.rs b/servo/components/style/matching.rs index 33905e0aebb1..c0eb82d90868 100644 --- a/servo/components/style/matching.rs +++ b/servo/components/style/matching.rs @@ -17,7 +17,7 @@ use data::{ComputedStyle, ElementData, ElementStyles, RestyleData}; use dom::{AnimationRules, SendElement, TElement, TNode}; use properties::{CascadeFlags, ComputedValues, SHAREABLE, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade}; use properties::longhands::display::computed_value as display; -use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RestyleHint}; +use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RESTYLE_CSS_ANIMATIONS, RestyleHint}; use rule_tree::{CascadeLevel, RuleTree, StrongRuleNode}; use selector_parser::{PseudoElement, RestyleDamage, SelectorImpl}; use selectors::MatchAttr; @@ -954,30 +954,54 @@ pub trait MatchMethods : TElement { context: &StyleContext, data: &mut AtomicRefMut) -> bool { - let primary_rules = &mut data.styles_mut().primary.rules; + use properties::PropertyDeclarationBlock; + use shared_lock::Locked; + + let element_styles = &mut data.styles_mut(); + let primary_rules = &mut element_styles.primary.rules; let mut rule_node_changed = false; - if hint.contains(RESTYLE_STYLE_ATTRIBUTE) { - let style_attribute = self.style_attribute(); + { + let mut replace_rule_node = |level: CascadeLevel, + pdb: Option<&Arc>>, + path: &mut StrongRuleNode| { + let new_node = context.shared.stylist.rule_tree + .update_rule_at_level(level, pdb, path, &context.shared.guards); + if let Some(n) = new_node { + *path = n; + rule_node_changed = true; + } + }; - let new_node = context.shared.stylist.rule_tree - .update_rule_at_level(CascadeLevel::StyleAttributeNormal, - style_attribute, - primary_rules, - &context.shared.guards); - if let Some(n) = new_node { - *primary_rules = n; - rule_node_changed = true; - } + // RESTYLE_CSS_ANIMATIONS is processed prior to other restyle hints + // in the name of animation-only traversal. Rest of restyle hints + // will be processed in a subsequent normal traversal. + if hint.contains(RESTYLE_CSS_ANIMATIONS) { + debug_assert!(context.shared.animation_only_restyle); - let new_node = context.shared.stylist.rule_tree - .update_rule_at_level(CascadeLevel::StyleAttributeImportant, - style_attribute, - primary_rules, - &context.shared.guards); - if let Some(n) = new_node { - *primary_rules = n; - rule_node_changed = true; + let animation_rule = self.get_animation_rule(None); + replace_rule_node(CascadeLevel::Animations, + animation_rule.as_ref(), + primary_rules); + + let iter = element_styles.pseudos.iter_mut().filter(|&(p, _)| + ::Impl::pseudo_is_before_or_after(p)); + for (pseudo, ref mut computed) in iter { + let animation_rule = self.get_animation_rule(Some(pseudo)); + let pseudo_rules = &mut computed.rules; + replace_rule_node(CascadeLevel::Animations, + animation_rule.as_ref(), + pseudo_rules); + } + } else if hint.contains(RESTYLE_STYLE_ATTRIBUTE) { + let style_attribute = self.style_attribute(); + replace_rule_node(CascadeLevel::StyleAttributeNormal, + style_attribute, + primary_rules); + replace_rule_node(CascadeLevel::StyleAttributeImportant, + style_attribute, + primary_rules); + // The per-pseudo rule nodes never change in this path. } } diff --git a/servo/components/style/restyle_hints.rs b/servo/components/style/restyle_hints.rs index 76065e12578c..c0827b788bbc 100644 --- a/servo/components/style/restyle_hints.rs +++ b/servo/components/style/restyle_hints.rs @@ -47,6 +47,11 @@ bitflags! { /// of their descendants. const RESTYLE_LATER_SIBLINGS = 0x08, + /// Replace the style data coming from CSS animations without updating + /// any other style data. This hint is only processed in animation-only + /// traversal which is prior to normal traversal. + const RESTYLE_CSS_ANIMATIONS = 0x20, + /// Don't re-run selector-matching on the element, only the style /// attribute has changed, and this change didn't have any other /// dependencies. @@ -81,6 +86,7 @@ pub fn assert_restyle_hints_match() { // (RESTYLE_SELF | RESTYLE_DESCENDANTS). nsRestyleHint_eRestyle_Subtree => RESTYLE_DESCENDANTS, nsRestyleHint_eRestyle_LaterSiblings => RESTYLE_LATER_SIBLINGS, + nsRestyleHint_eRestyle_CSSAnimations => RESTYLE_CSS_ANIMATIONS, nsRestyleHint_eRestyle_StyleAttribute => RESTYLE_STYLE_ATTRIBUTE, } } @@ -89,7 +95,7 @@ impl RestyleHint { /// The subset hints that affect the styling of a single element during the /// traversal. pub fn for_self() -> Self { - RESTYLE_SELF | RESTYLE_STYLE_ATTRIBUTE + RESTYLE_SELF | RESTYLE_STYLE_ATTRIBUTE | RESTYLE_CSS_ANIMATIONS } } diff --git a/servo/components/style/traversal.rs b/servo/components/style/traversal.rs index 767547f3a281..df70c29664cd 100644 --- a/servo/components/style/traversal.rs +++ b/servo/components/style/traversal.rs @@ -31,6 +31,28 @@ pub struct PerLevelTraversalData { pub current_dom_depth: Option, } +bitflags! { + /// Represents that target elements of the traversal. + pub flags TraversalFlags: u8 { + /// Traverse only unstyled children. + const UNSTYLED_CHILDREN_ONLY = 0x01, + /// Traverse only elements for animation restyles + const ANIMATION_ONLY = 0x02, + } +} + +impl TraversalFlags { + /// Returns true if the traversal is for animation-only restyles. + pub fn for_animation_only(&self) -> bool { + self.contains(ANIMATION_ONLY) + } + + /// Returns true if the traversal is for unstyled children. + pub fn for_unstyled_children_only(&self) -> bool { + self.contains(UNSTYLED_CHILDREN_ONLY) + } +} + /// This structure exists to enforce that callers invoke pre_traverse, and also /// to pass information from the pre-traversal into the primary traversal. pub struct PreTraverseToken { @@ -109,12 +131,15 @@ pub trait DomTraversal : Sync { /// a traversal is needed. Returns a token that allows the caller to prove /// that the call happened. /// - /// The unstyled_children_only parameter is used in Gecko to style newly- + /// The traversal_flag is used in Gecko. + /// If traversal_flag::UNSTYLED_CHILDREN_ONLY is specified, style newly- /// appended children without restyling the parent. - fn pre_traverse(root: E, stylist: &Stylist, unstyled_children_only: bool) + /// If traversal_flag::ANIMATION_ONLY is specified, style only elements for + /// animations. + fn pre_traverse(root: E, stylist: &Stylist, traversal_flags: TraversalFlags) -> PreTraverseToken { - if unstyled_children_only { + if traversal_flags.for_unstyled_children_only() { return PreTraverseToken { traverse: true, unstyled_children_only: true, @@ -135,7 +160,7 @@ pub trait DomTraversal : Sync { } PreTraverseToken { - traverse: Self::node_needs_traversal(root.as_node()), + traverse: Self::node_needs_traversal(root.as_node(), traversal_flags.for_animation_only()), unstyled_children_only: false, } } @@ -149,7 +174,7 @@ pub trait DomTraversal : Sync { } /// Returns true if traversal is needed for the given node and subtree. - fn node_needs_traversal(node: E::ConcreteNode) -> bool { + fn node_needs_traversal(node: E::ConcreteNode, animation_only: bool) -> bool { // Non-incremental layout visits every node. if cfg!(feature = "servo") && opts::get().nonincremental_layout { return true; @@ -158,6 +183,22 @@ pub trait DomTraversal : Sync { match node.as_element() { None => Self::text_node_needs_traversal(node), Some(el) => { + // In case of animation-only traversal we need to traverse + // the element if the element has animation only dirty + // descendants bit, animation-only restyle hint or recascade. + if animation_only { + if el.has_animation_only_dirty_descendants() { + return true; + } + + let data = match el.borrow_data() { + Some(d) => d, + None => return false, + }; + return data.get_restyle() + .map_or(false, |r| r.hint.has_animation_hint() || r.recascade); + } + // If the dirty descendants bit is set, we need to traverse no // matter what. Skip examining the ElementData. if el.has_dirty_descendants() { @@ -270,7 +311,7 @@ pub trait DomTraversal : Sync { } for kid in parent.as_node().children() { - if Self::node_needs_traversal(kid) { + if Self::node_needs_traversal(kid, self.shared_context().animation_only_restyle) { let el = kid.as_element(); if el.as_ref().and_then(|el| el.borrow_data()) .map_or(false, |d| d.has_styles()) @@ -448,21 +489,38 @@ pub fn recalc_style_at(traversal: &D, None => empty_hint, Some(r) => { r.recascade = false; - mem::replace(&mut r.hint, empty_hint).propagate() + if r.hint.has_animation_hint() { + debug_assert!(context.shared.animation_only_restyle, + "animation restyle hint should be handled during animation-only restyles"); + // Drop animation restyle hint. + let propagated_hint = r.hint.propagate(); + r.hint.remove_animation_hint(); + propagated_hint + } else { + mem::replace(&mut r.hint, empty_hint).propagate() + } }, }; - debug_assert!(data.has_current_styles()); + debug_assert!(data.has_current_styles() || context.shared.animation_only_restyle, + "Should have computed style or haven't yet valid computed style in case of animation-only restyle"); trace!("propagated_hint={:?}, inherited_style_changed={:?}", propagated_hint, inherited_style_changed); // Preprocess children, propagating restyle hints and handling sibling relationships. if traversal.should_traverse_children(&mut context.thread_local, element, &data, DontLog) && - (element.has_dirty_descendants() || !propagated_hint.is_empty() || inherited_style_changed) { + ((!context.shared.animation_only_restyle && element.has_dirty_descendants()) || + (context.shared.animation_only_restyle && element.has_animation_only_dirty_descendants()) || + !propagated_hint.is_empty() || + inherited_style_changed) { let damage_handled = data.get_restyle().map_or(RestyleDamage::empty(), |r| { r.damage_handled() | r.damage.handled_for_descendants() }); preprocess_children(traversal, element, propagated_hint, damage_handled, inherited_style_changed); } + if context.shared.animation_only_restyle { + unsafe { element.unset_animation_only_dirty_descendants(); } + } + // Make sure the dirty descendants bit is not set for the root of a // display:none subtree, even if the style didn't change (since, if // the style did change, we'd have already cleared it above). diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index 272d4d2302bc..ac04ee62c3dd 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -83,7 +83,8 @@ use style::stylesheets::StylesheetLoader as StyleStylesheetLoader; use style::supports::parse_condition_or_declaration; use style::thread_state; use style::timer::Timer; -use style::traversal::{resolve_style, DomTraversal, TraversalDriver}; +use style::traversal::{ANIMATION_ONLY, UNSTYLED_CHILDREN_ONLY}; +use style::traversal::{resolve_style, DomTraversal, TraversalDriver, TraversalFlags}; use style_traits::ToCss; use super::stylesheet_loader::StylesheetLoader; @@ -124,7 +125,8 @@ pub extern "C" fn Servo_Shutdown() { } fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard, - per_doc_data: &PerDocumentStyleDataImpl) -> SharedStyleContext<'a> { + per_doc_data: &PerDocumentStyleDataImpl, + animation_only: bool) -> SharedStyleContext<'a> { let local_context_data = ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone()); @@ -139,11 +141,12 @@ fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard, timer: Timer::new(), // FIXME Find the real QuirksMode information for this document quirks_mode: QuirksMode::NoQuirks, + animation_only_restyle: animation_only, } } fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed, - unstyled_children_only: bool) { + traversal_flags: TraversalFlags) { // When new content is inserted in a display:none subtree, we will call into // servo to try to style it. Detect that here and bail out. if let Some(parent) = element.parent_element() { @@ -155,7 +158,7 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed, let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow(); - let token = RecalcStyleOnly::pre_traverse(element, &per_doc_data.stylist, unstyled_children_only); + let token = RecalcStyleOnly::pre_traverse(element, &per_doc_data.stylist, traversal_flags); if !token.should_traverse() { return; } @@ -165,7 +168,8 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed, let global_style_data = &*GLOBAL_STYLE_DATA; let guard = global_style_data.shared_lock.read(); - let shared_style_context = create_shared_context(&guard, &per_doc_data); + let shared_style_context = create_shared_context(&guard, &per_doc_data, + traversal_flags.for_animation_only()); let traversal_driver = if global_style_data.style_thread_pool.is_none() { TraversalDriver::Sequential @@ -192,8 +196,18 @@ pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed, behavior: structs::TraversalRootBehavior) -> bool { let element = GeckoElement(root); debug!("Servo_TraverseSubtree: {:?}", element); - traverse_subtree(element, raw_data, - behavior == structs::TraversalRootBehavior::UnstyledChildrenOnly); + + let traversal_flags = match behavior { + structs::TraversalRootBehavior::UnstyledChildrenOnly => UNSTYLED_CHILDREN_ONLY, + _ => TraversalFlags::empty(), + }; + + if element.has_animation_only_dirty_descendants() || + element.has_animation_restyle_hints() { + traverse_subtree(element, raw_data, traversal_flags | ANIMATION_ONLY); + } + + traverse_subtree(element, raw_data, traversal_flags); element.has_dirty_descendants() || element.mutate_data().unwrap().has_restyle() } @@ -1359,7 +1373,9 @@ pub extern "C" fn Servo_CSSSupports(cond: *const nsACString) -> bool { /// Only safe to call on the main thread, with exclusive access to the element and /// its ancestors. -unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut, element: GeckoElement) +unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut, + element: GeckoElement, + animation_only: bool) -> Option<&'a mut RestyleData> { // Don't generate a useless RestyleData if the element hasn't been styled. @@ -1371,8 +1387,13 @@ unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut, element: Ge let mut curr = element; while let Some(parent) = curr.parent_element() { curr = parent; - if curr.has_dirty_descendants() { break; } - curr.set_dirty_descendants(); + if animation_only { + if curr.has_animation_only_dirty_descendants() { break; } + curr.set_animation_only_dirty_descendants(); + } else { + if curr.has_dirty_descendants() { break; } + curr.set_dirty_descendants(); + } } bindings::Gecko_SetOwnerDocumentNeedsStyleFlush(element.0); @@ -1387,7 +1408,7 @@ pub extern "C" fn Servo_Element_GetSnapshot(element: RawGeckoElementBorrowed) -> let snapshot = match element.mutate_data() { None => ptr::null_mut(), Some(mut data) => { - if let Some(restyle_data) = unsafe { maybe_restyle(&mut data, element) } { + if let Some(restyle_data) = unsafe { maybe_restyle(&mut data, element, false) } { restyle_data.snapshot.ensure(|| element.create_snapshot()).borrow_mut_raw() } else { ptr::null_mut() @@ -1407,10 +1428,14 @@ pub extern "C" fn Servo_NoteExplicitHints(element: RawGeckoElementBorrowed, let damage = GeckoRestyleDamage::new(change_hint); debug!("Servo_NoteExplicitHints: {:?}, restyle_hint={:?}, change_hint={:?}", element, restyle_hint, change_hint); + debug_assert!(restyle_hint == structs::nsRestyleHint_eRestyle_CSSAnimations || + (restyle_hint.0 & structs::nsRestyleHint_eRestyle_CSSAnimations.0) == 0, + "eRestyle_CSSAnimations should only appear by itself"); let mut maybe_data = element.mutate_data(); - let maybe_restyle_data = - maybe_data.as_mut().and_then(|d| unsafe { maybe_restyle(d, element) }); + let maybe_restyle_data = maybe_data.as_mut().and_then(|d| unsafe { + maybe_restyle(d, element, restyle_hint == structs::nsRestyleHint_eRestyle_CSSAnimations) + }); if let Some(restyle_data) = maybe_restyle_data { let restyle_hint: RestyleHint = restyle_hint.into(); restyle_data.hint.insert(&restyle_hint.into()); @@ -1492,7 +1517,7 @@ pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed, } // We don't have the style ready. Go ahead and compute it as necessary. - let shared = create_shared_context(&guard, &mut doc_data.borrow_mut()); + let shared = create_shared_context(&guard, &mut doc_data.borrow_mut(), false); let mut tlc = ThreadLocalStyleContext::new(&shared); let mut context = StyleContext { shared: &shared, @@ -1592,7 +1617,7 @@ pub extern "C" fn Servo_AssertTreeIsClean(root: RawGeckoElementBorrowed) { let root = GeckoElement(root); fn assert_subtree_is_clean<'le>(el: GeckoElement<'le>) { - debug_assert!(!el.has_dirty_descendants()); + debug_assert!(!el.has_dirty_descendants() && !el.has_animation_only_dirty_descendants()); for child in el.as_node().children() { if let Some(child) = child.as_element() { assert_subtree_is_clean(child); From bec36f074f652a974d44755d1970ef74afc29cd3 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Mon, 27 Mar 2017 06:17:07 +0900 Subject: [PATCH 54/57] Bug 1344966 - Add NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO to represent that an element's descendant has animation. r=heycam MozReview-Commit-ID: GRumykMgGg0 --HG-- extra : rebase_source : 8b9675d1c56a0d2dd81532e28c03d85996f0cc7f --- dom/base/nsINode.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h index 4c66cf60da8d..b8354399316f 100644 --- a/dom/base/nsINode.h +++ b/dom/base/nsINode.h @@ -214,6 +214,11 @@ enum { // Whether this node has dirty descendants for Servo's style system. NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO = NODE_SHARED_RESTYLE_BIT_1, + // Whether this node has dirty descendants for animation-only restyle for + // Servo's style system. + NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO = + NODE_SHARED_RESTYLE_BIT_2, + // Remaining bits are node type specific. NODE_TYPE_SPECIFIC_BITS_OFFSET = 23 }; From 0ec76c29e2200ec63a0ce815a126ed6eae2b639b Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Mon, 27 Mar 2017 06:17:08 +0900 Subject: [PATCH 55/57] Bug 1344966 - Post eRestyle_CSSAnimations instead of eRestyle_Self and eRestyle_Subtree. r=heycam MozReview-Commit-ID: 7azwzIPc45X --HG-- extra : rebase_source : 5943ab5db1a0a7ca4e77f9373151a5d1387ab25f --- dom/animation/EffectCompositor.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/dom/animation/EffectCompositor.cpp b/dom/animation/EffectCompositor.cpp index 6d34f8f181f8..225875ddb4c2 100644 --- a/dom/animation/EffectCompositor.cpp +++ b/dom/animation/EffectCompositor.cpp @@ -332,12 +332,8 @@ EffectCompositor::PostRestyleForAnimation(dom::Element* aElement, // second traversal so we don't need to post any restyle requests to the // PresShell. return; - } else if (!mPresContext->RestyleManager()->IsInStyleRefresh()) { - // FIXME: stylo only supports Self and Subtree hints now, so we override - // it for stylo if we are not in process of restyling. - hint = eRestyle_Self | eRestyle_Subtree; } else { - MOZ_ASSERT_UNREACHABLE("Should not request restyle"); + MOZ_ASSERT(!mPresContext->RestyleManager()->IsInStyleRefresh()); } } mPresContext->PresShell()->RestyleForAnimation(element, hint); @@ -983,8 +979,8 @@ EffectCompositor::PreTraverse() // We can't call PostRestyleEvent directly here since we are still in the // middle of the servo traversal. mPresContext->RestyleManager()->AsServo()-> - PostRestyleEventForAnimations(target.mElement, - eRestyle_Self | eRestyle_Subtree); + PostRestyleEventForAnimations(target.mElement, eRestyle_CSSAnimations); + foundElementsNeedingRestyle = true; EffectSet* effects = @@ -1035,7 +1031,7 @@ EffectCompositor::PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull) } mPresContext->RestyleManager()->AsServo()-> - PostRestyleEventForAnimations(aElement, eRestyle_Self); + PostRestyleEventForAnimations(aElement, eRestyle_CSSAnimations); EffectSet* effects = EffectSet::GetEffectSet(aElement, pseudoType); if (effects) { From fb9844d9162687a2645de944ad482616734afba2 Mon Sep 17 00:00:00 2001 From: "Alfredo.Yang" Date: Tue, 14 Mar 2017 15:42:09 +0800 Subject: [PATCH 56/57] Bug 1330243 - add preference to enable rust mp4 parser. r=kinetik MozReview-Commit-ID: LINNEMiXYx4 --HG-- extra : rebase_source : 747b9854b0d5d1f0419c59c5966414872e8ea158 --- dom/media/MediaPrefs.h | 2 ++ media/libstagefright/binding/MP4Metadata.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dom/media/MediaPrefs.h b/dom/media/MediaPrefs.h index 38c446abf3dd..038d015a8916 100644 --- a/dom/media/MediaPrefs.h +++ b/dom/media/MediaPrefs.h @@ -170,6 +170,8 @@ private: DECL_MEDIA_PREF("media.rust.test_mode", RustTestMode, bool, false); #endif + DECL_MEDIA_PREF("media.rust.mp4parser", EnableRustMP4Parser, bool, false); + public: // Manage the singleton: static MediaPrefs& GetSingleton(); diff --git a/media/libstagefright/binding/MP4Metadata.cpp b/media/libstagefright/binding/MP4Metadata.cpp index 108cfda5a89d..7e6809436544 100644 --- a/media/libstagefright/binding/MP4Metadata.cpp +++ b/media/libstagefright/binding/MP4Metadata.cpp @@ -230,7 +230,7 @@ IndiceWrapperRust::GetIndice(size_t aIndex, Index::Indice& aIndice) const MP4Metadata::MP4Metadata(Stream* aSource) : mStagefright(MakeUnique(aSource)) , mRust(MakeUnique(aSource)) - , mPreferRust(false) + , mPreferRust(MediaPrefs::EnableRustMP4Parser()) , mReportedAudioTrackTelemetry(false) , mReportedVideoTrackTelemetry(false) #ifndef RELEASE_OR_BETA From b6f5ac4f524a79b8e35a79841e5075493e2a0cec Mon Sep 17 00:00:00 2001 From: "Alfredo.Yang" Date: Sat, 25 Mar 2017 17:55:06 +0800 Subject: [PATCH 57/57] Bug 1330243 - update gtest for mp4 rust parser. r=kinetik MozReview-Commit-ID: 3CfsHkpk625 --HG-- extra : rebase_source : 1f2b54f8c058bb6d9fdb649224d4a09df662c06f --- media/libstagefright/gtest/TestParser.cpp | 107 ++++++++++++++++++---- 1 file changed, 88 insertions(+), 19 deletions(-) diff --git a/media/libstagefright/gtest/TestParser.cpp b/media/libstagefright/gtest/TestParser.cpp index f88a3d6cc661..f88c9cc4e258 100644 --- a/media/libstagefright/gtest/TestParser.cpp +++ b/media/libstagefright/gtest/TestParser.cpp @@ -5,6 +5,7 @@ #include "gtest/gtest.h" #include "MediaData.h" +#include "MediaPrefs.h" #include "mozilla/ArrayUtils.h" #include "mp4_demuxer/BufferStream.h" #include "mp4_demuxer/MP4Metadata.h" @@ -205,10 +206,64 @@ static const TestFileData testFiles[] = { false, 0, false, false, 2 }, }; +static const TestFileData rustTestFiles[] = { + // filename #V dur w h #A dur crypt off moof headr audio_profile + { "test_case_1156505.mp4", 0, -1, 0, 0, 0, -1, false, 152, false, false, 0 }, + { "test_case_1181213.mp4", 1, 416666, + 320, 240, 1, 477460, + true, 0, false, false, 2 }, + { "test_case_1181215.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 }, + { "test_case_1181220.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 }, + { "test_case_1181223.mp4", 1, 416666, + 320, 240, 0, -1, false, 0, false, false, 0 }, + { "test_case_1181719.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 }, + { "test_case_1185230.mp4", 2, 416666, + 320, 240, 2, 5, false, 0, false, false, 2 }, + { "test_case_1187067.mp4", 1, 80000, + 160, 90, 0, -1, false, 0, false, false, 0 }, + { "test_case_1200326.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 }, + { "test_case_1204580.mp4", 1, 502500, + 320, 180, 0, -1, false, 0, false, false, 0 }, + { "test_case_1216748.mp4", 0, -1, 0, 0, 0, -1, false, 152, false, false, 0 }, + { "test_case_1296473.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 }, + { "test_case_1296532.mp4", 1, 5589333, + 560, 320, 1, 5589333, + true, 0, true, true, 2 }, + { "test_case_1301065.mp4", 0, -1, 0, 0, 1, 100079991719000000, + false, 0, false, false, 2 }, + { "test_case_1301065-u32max.mp4", 0, -1, 0, 0, 1, 97391548639, + false, 0, false, false, 2 }, + { "test_case_1301065-max-ez.mp4", 0, -1, 0, 0, 1, 209146758205306, + false, 0, false, false, 2 }, + { "test_case_1301065-harder.mp4", 0, -1, 0, 0, 1, 209146758205328, + false, 0, false, false, 2 }, + { "test_case_1301065-max-ok.mp4", 0, -1, 0, 0, 1, 9223372036854775804, + false, 0, false, false, 2 }, + // The duration is overflow for int64_t in TestFileData, rust parser uses uint64_t so + // this file is ignore. + //{ "test_case_1301065-overfl.mp4", 0, -1, 0, 0, 1, 9223372036854775827, + // false, 0, false, false, 2 }, + { "test_case_1301065-i64max.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 }, + { "test_case_1301065-i64min.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 }, + { "test_case_1301065-u64max.mp4", 0, -1, 0, 0, 1, 0, false, 0, false, false, 2 }, + { "test_case_1329061.mov", 0, -1, 0, 0, 1, 234567981, + false, 0, false, false, 2 }, +}; TEST(stagefright_MPEG4Metadata, test_case_mp4) { - for (size_t test = 0; test < ArrayLength(testFiles); ++test) { - nsTArray buffer = ReadTestFile(testFiles[test].mFilename); + const TestFileData* tests = nullptr; + size_t length = 0; + + if (MediaPrefs::EnableRustMP4Parser()) { + tests = rustTestFiles; + length = ArrayLength(rustTestFiles); + } else { + tests = testFiles; + length = ArrayLength(testFiles); + } + + for (size_t test = 0; test < length; ++test) { + nsTArray buffer = ReadTestFile(tests[test].mFilename); ASSERT_FALSE(buffer.IsEmpty()); RefPtr stream = new TestStream(buffer.Elements(), buffer.Length()); @@ -217,15 +272,15 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4) MP4Metadata metadata(stream); EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kUndefinedTrack)); - EXPECT_EQ(testFiles[test].mNumberAudioTracks, + EXPECT_EQ(tests[test].mNumberAudioTracks, metadata.GetNumberTracks(TrackInfo::kAudioTrack)); - EXPECT_EQ(testFiles[test].mNumberVideoTracks, + EXPECT_EQ(tests[test].mNumberVideoTracks, metadata.GetNumberTracks(TrackInfo::kVideoTrack)); EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kTextTrack)); EXPECT_EQ(0u, metadata.GetNumberTracks(static_cast(-1))); EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kUndefinedTrack, 0)); UniquePtr trackInfo = metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0); - if (testFiles[test].mNumberVideoTracks == 0) { + if (tests[test].mNumberVideoTracks == 0) { EXPECT_TRUE(!trackInfo); } else { ASSERT_TRUE(!!trackInfo); @@ -233,9 +288,9 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4) ASSERT_TRUE(!!videoInfo); EXPECT_TRUE(videoInfo->IsValid()); EXPECT_TRUE(videoInfo->IsVideo()); - EXPECT_EQ(testFiles[test].mVideoDuration, videoInfo->mDuration); - EXPECT_EQ(testFiles[test].mWidth, videoInfo->mDisplay.width); - EXPECT_EQ(testFiles[test].mHeight, videoInfo->mDisplay.height); + EXPECT_EQ(tests[test].mVideoDuration, videoInfo->mDuration); + EXPECT_EQ(tests[test].mWidth, videoInfo->mDisplay.width); + EXPECT_EQ(tests[test].mHeight, videoInfo->mDisplay.height); UniquePtr indices = metadata.GetTrackIndice(videoInfo->mTrackId); EXPECT_TRUE(!!indices); @@ -247,7 +302,7 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4) } } trackInfo = metadata.GetTrackInfo(TrackInfo::kAudioTrack, 0); - if (testFiles[test].mNumberAudioTracks == 0) { + if (tests[test].mNumberAudioTracks == 0) { EXPECT_TRUE(!trackInfo); } else { ASSERT_TRUE(!!trackInfo); @@ -255,8 +310,11 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4) ASSERT_TRUE(!!audioInfo); EXPECT_TRUE(audioInfo->IsValid()); EXPECT_TRUE(audioInfo->IsAudio()); - EXPECT_EQ(testFiles[test].mAudioDuration, audioInfo->mDuration); - EXPECT_EQ(testFiles[test].mAudioProfile, audioInfo->mProfile); + EXPECT_EQ(tests[test].mAudioDuration, audioInfo->mDuration); + EXPECT_EQ(tests[test].mAudioProfile, audioInfo->mProfile); + if (tests[test].mAudioDuration != audioInfo->mDuration) { + MOZ_RELEASE_ASSERT(false); + } UniquePtr indices = metadata.GetTrackIndice(audioInfo->mTrackId); EXPECT_TRUE(!!indices); @@ -264,14 +322,14 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4) Index::Indice data; EXPECT_TRUE(indices->GetIndice(i, data)); EXPECT_TRUE(data.start_offset <= data.end_offset); - EXPECT_TRUE(data.start_composition <= data.end_composition); + EXPECT_TRUE(int64_t(data.start_composition) <= int64_t(data.end_composition)); } } EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kTextTrack, 0)); EXPECT_FALSE(metadata.GetTrackInfo(static_cast(-1), 0)); // We can see anywhere in any MPEG4. EXPECT_TRUE(metadata.CanSeek()); - EXPECT_EQ(testFiles[test].mHasCrypto, metadata.Crypto().valid); + EXPECT_EQ(tests[test].mHasCrypto, metadata.Crypto().valid); } } @@ -315,8 +373,19 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4_subsets) TEST(stagefright_MoofParser, test_case_mp4) { - for (size_t test = 0; test < ArrayLength(testFiles); ++test) { - nsTArray buffer = ReadTestFile(testFiles[test].mFilename); + const TestFileData* tests = nullptr; + size_t length = 0; + + if (MediaPrefs::EnableRustMP4Parser()) { + tests = rustTestFiles; + length = ArrayLength(rustTestFiles); + } else { + tests = testFiles; + length = ArrayLength(testFiles); + } + + for (size_t test = 0; test < length; ++test) { + nsTArray buffer = ReadTestFile(tests[test].mFilename); ASSERT_FALSE(buffer.IsEmpty()); RefPtr stream = new TestStream(buffer.Elements(), buffer.Length()); @@ -332,20 +401,20 @@ TEST(stagefright_MoofParser, test_case_mp4) EXPECT_FALSE(parser.mInitRange.IsEmpty()); const MediaByteRangeSet byteRanges( MediaByteRange(0, int64_t(buffer.Length()))); - EXPECT_EQ(testFiles[test].mValidMoof, + EXPECT_EQ(tests[test].mValidMoof, parser.RebuildFragmentedIndex(byteRanges)); - if (testFiles[test].mMoofReachedOffset == 0) { + if (tests[test].mMoofReachedOffset == 0) { EXPECT_EQ(buffer.Length(), parser.mOffset); EXPECT_TRUE(parser.ReachedEnd()); } else { - EXPECT_EQ(testFiles[test].mMoofReachedOffset, parser.mOffset); + EXPECT_EQ(tests[test].mMoofReachedOffset, parser.mOffset); EXPECT_FALSE(parser.ReachedEnd()); } EXPECT_FALSE(parser.mInitRange.IsEmpty()); EXPECT_TRUE(parser.GetCompositionRange(byteRanges).IsNull()); EXPECT_TRUE(parser.FirstCompleteMediaSegment().IsEmpty()); - EXPECT_EQ(testFiles[test].mHeader, + EXPECT_EQ(tests[test].mHeader, !parser.FirstCompleteMediaHeader().IsEmpty()); } }