Bug 1669459 - Introduce InspectorUtils.supports(). r=rcaliman,heycam

Which allows to run CSS.supports in chrome/user-agent context. We should
probably add a couple more tweaks for stuff like quirks or what not (the
`ParsingMode` enum), but that seem lower priority.

I only added the one-value version of CSS.supports because it should be enough
and supporting the two value version required a bit of awkward code due to when
we parse the CSS property name right now.

Differential Revision: https://phabricator.services.mozilla.com/D92585
This commit is contained in:
Emilio Cobos Álvarez 2020-10-09 03:20:34 +00:00
parent 5a3e382de8
commit e9e00c7007
13 changed files with 126 additions and 57 deletions

View File

@ -45,6 +45,9 @@ namespace InspectorUtils {
[Throws] boolean cssPropertySupportsType(UTF8String property, InspectorPropertyType type);
// A version of CSS.supports that allows you to set UA or chrome context.
boolean supports(UTF8String conditionText, optional SupportsOptions options = {});
boolean isIgnorableWhitespace(CharacterData dataNode);
Node? getParentForNode(Node node, boolean showingAnonymousContent);
[NewObject] NodeList getChildrenForNode(Node node,
@ -84,6 +87,12 @@ namespace InspectorUtils {
[NewObject] NodeList getOverflowingChildrenOfElement(Element element);
};
dictionary SupportsOptions {
boolean userAgent = false;
boolean chrome = false;
boolean quirks = false;
};
dictionary PropertyNamesOptions {
boolean includeAliases = false;
boolean includeShorthands = true;

View File

@ -301,7 +301,6 @@ void nsLayoutStatics::Shutdown() {
if (XRE_IsParentProcess() || XRE_IsContentProcess()) {
ShutdownServo();
URLExtraData::ReleaseDummy();
}
mozilla::dom::AbstractRange::Shutdown();

View File

@ -443,6 +443,12 @@ static uint8_t ToServoCssType(InspectorPropertyType aType) {
}
}
bool InspectorUtils::Supports(GlobalObject&, const nsACString& aDeclaration,
const SupportsOptions& aOptions) {
return Servo_CSSSupports(&aDeclaration, aOptions.mUserAgent, aOptions.mChrome,
aOptions.mQuirks);
}
bool InspectorUtils::CssPropertySupportsType(GlobalObject& aGlobalObject,
const nsACString& aProperty,
InspectorPropertyType aType,

View File

@ -165,6 +165,9 @@ class InspectorUtils {
const nsACString& aProperty,
InspectorPropertyType, ErrorResult& aRv);
static bool Supports(GlobalObject&, const nsACString& aDeclaration,
const SupportsOptions&);
static bool IsIgnorableWhitespace(GlobalObject& aGlobalObject,
CharacterData& aDataNode) {
return IsIgnorableWhitespace(aDataNode);

View File

@ -36,3 +36,4 @@ skip-if = os == 'android'
[test_parseStyleSheet.html]
[test_parseStyleSheetImport.html]
[test_selectormatcheselement.html]
[test_supports.html]

View File

@ -0,0 +1,23 @@
<!doctype html>
<title>Test for InspectorUtils.supports</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script>
const InspectorUtils = SpecialPowers.InspectorUtils;
ok(!CSS.supports("-moz-window-transform: unset"), "-moz-window-transform is only available to chrome and UA sheets");
for (let chrome of [true, false]) {
is(InspectorUtils.supports("-moz-window-transform: unset", { chrome }), chrome, "InspectorUtils.supports should properly report to support chrome-only properties");
}
ok(!CSS.supports("-moz-top-layer: top"), "-moz-top-layer is only available to UA sheets");
ok(!CSS.supports("selector(:-moz-inert)"), "-moz-inert is an UA-only pseudo-class");
for (let userAgent of [true, false]) {
is(InspectorUtils.supports("-moz-top-layer: top", { userAgent }), userAgent, "InspectorUtils.supports should properly report to support UA properties");
is(InspectorUtils.supports("selector(:-moz-inert)", { userAgent }), userAgent, "InspectorUtils.supports should properly report to support UA-only selectors");
}
ok(!CSS.supports("width: 100"), "width shouldn't allow unitless lengths in non-quirks, and in CSS.supports");
for (let quirks of [true, false]) {
is(InspectorUtils.supports("width: 100", { quirks }), quirks, "InspectorUtils.supports should allow quirks if told to do so");
}
</script>

View File

@ -26,11 +26,12 @@ bool CSS::Supports(const GlobalObject&, const nsACString& aProperty,
/* static */
bool CSS::Supports(const GlobalObject&, const nsACString& aCondition) {
return Servo_CSSSupports(&aCondition);
return Servo_CSSSupports(&aCondition, /* ua = */ false, /* chrome = */ false,
/* quirks = */ false);
}
/* static */
void CSS::Escape(const GlobalObject& aGlobal, const nsAString& aIdent,
void CSS::Escape(const GlobalObject&, const nsAString& aIdent,
nsAString& aReturn) {
nsStyleUtil::AppendEscapedCSSIdent(aIdent, aReturn);
}

View File

@ -1400,8 +1400,8 @@ static StaticRefPtr<UACacheReporter> gUACacheReporter;
namespace mozilla {
void InitializeServo() {
URLExtraData::InitDummy();
Servo_Initialize(URLExtraData::Dummy());
URLExtraData::Init();
Servo_Initialize(URLExtraData::Dummy(), URLExtraData::DummyChrome());
gUACacheReporter = new UACacheReporter();
RegisterWeakMemoryReporter(gUACacheReporter);
@ -1416,7 +1416,10 @@ void ShutdownServo() {
gUACacheReporter = nullptr;
delete sServoFFILock;
sServoFFILock = nullptr;
Servo_Shutdown();
URLExtraData::Shutdown();
}
void AssertIsMainThreadOrServoFontMetricsLocked() {

View File

@ -15,17 +15,26 @@
namespace mozilla {
StaticRefPtr<URLExtraData> URLExtraData::sDummy;
StaticRefPtr<URLExtraData> URLExtraData::sDummyChrome;
/* static */
void URLExtraData::InitDummy() {
void URLExtraData::Init() {
RefPtr<nsIURI> baseURI = new NullPrincipalURI();
nsCOMPtr<nsIReferrerInfo> referrerInfo = new dom::ReferrerInfo(nullptr);
sDummy = new URLExtraData(baseURI.forget(), referrerInfo.forget(),
sDummy = new URLExtraData(do_AddRef(baseURI), do_AddRef(referrerInfo),
NullPrincipal::CreateWithoutOriginAttributes());
sDummyChrome =
new URLExtraData(baseURI.forget(), referrerInfo.forget(),
NullPrincipal::CreateWithoutOriginAttributes());
sDummyChrome->mIsChrome = true;
}
/* static */
void URLExtraData::ReleaseDummy() { sDummy = nullptr; }
void URLExtraData::Shutdown() {
sDummy = nullptr;
sDummyChrome = nullptr;
}
URLExtraData::~URLExtraData() {
if (!NS_IsMainThread()) {

View File

@ -53,8 +53,14 @@ struct URLExtraData {
MOZ_ASSERT(sDummy);
return sDummy;
}
static void InitDummy();
static void ReleaseDummy();
static URLExtraData* DummyChrome() {
MOZ_ASSERT(sDummyChrome);
return sDummyChrome;
}
static void Init();
static void Shutdown();
// URLExtraData objects that shared style sheets use a sheet ID index to
// refer to.
@ -72,6 +78,7 @@ struct URLExtraData {
bool mIsChrome;
static StaticRefPtr<URLExtraData> sDummy;
static StaticRefPtr<URLExtraData> sDummyChrome;
};
} // namespace mozilla

View File

@ -82,27 +82,6 @@ impl<'a> ParserContext<'a> {
}
}
/// Create a parser context for on-the-fly parsing in CSSOM
#[inline]
pub fn new_for_cssom(
url_data: &'a UrlExtraData,
rule_type: Option<CssRuleType>,
parsing_mode: ParsingMode,
quirks_mode: QuirksMode,
error_reporter: Option<&'a dyn ParseErrorReporter>,
use_counters: Option<&'a UseCounters>,
) -> Self {
Self::new(
Origin::Author,
url_data,
rule_type,
parsing_mode,
quirks_mode,
error_reporter,
use_counters,
)
}
/// Create a parser context based on a previous context, but with a modified
/// rule type.
#[inline]

View File

@ -1288,6 +1288,7 @@ pub fn parse_one_declaration_into(
declarations: &mut SourcePropertyDeclaration,
id: PropertyId,
input: &str,
origin: Origin,
url_data: &UrlExtraData,
error_reporter: Option<&dyn ParseErrorReporter>,
parsing_mode: ParsingMode,
@ -1295,7 +1296,7 @@ pub fn parse_one_declaration_into(
rule_type: CssRuleType,
) -> Result<(), ()> {
let context = ParserContext::new(
Origin::Author,
origin,
url_data,
Some(rule_type),
parsing_mode,

View File

@ -165,11 +165,14 @@ impl ClosureHelper for DeclarationBlockMutationClosure {
*/
// A dummy url data for where we don't pass url data in.
// We need to get rid of this sooner than later.
static mut DUMMY_URL_DATA: *mut URLExtraData = 0 as *mut _;
static mut DUMMY_CHROME_URL_DATA: *mut URLExtraData = 0 as *mut _;
#[no_mangle]
pub unsafe extern "C" fn Servo_Initialize(dummy_url_data: *mut URLExtraData) {
pub unsafe extern "C" fn Servo_Initialize(
dummy_url_data: *mut URLExtraData,
dummy_chrome_url_data: *mut URLExtraData,
) {
use style::gecko_bindings::sugar::origin_flags;
// Pretend that we're a Servo Layout thread, to make some assertions happy.
@ -183,11 +186,13 @@ pub unsafe extern "C" fn Servo_Initialize(dummy_url_data: *mut URLExtraData) {
specified::font::assert_variant_ligatures_matches();
DUMMY_URL_DATA = dummy_url_data;
DUMMY_CHROME_URL_DATA = dummy_chrome_url_data;
}
#[no_mangle]
pub unsafe extern "C" fn Servo_Shutdown() {
DUMMY_URL_DATA = ptr::null_mut();
DUMMY_CHROME_URL_DATA = ptr::null_mut();
Stylist::shutdown();
url::shutdown();
}
@ -4050,14 +4055,14 @@ fn parse_property_into(
declarations: &mut SourcePropertyDeclaration,
property_id: PropertyId,
value: &nsACString,
data: *mut URLExtraData,
origin: Origin,
url_data: &UrlExtraData,
parsing_mode: structs::ParsingMode,
quirks_mode: QuirksMode,
rule_type: CssRuleType,
reporter: Option<&dyn ParseErrorReporter>,
) -> Result<(), ()> {
let value = unsafe { value.as_str_unchecked() };
let url_data = unsafe { UrlExtraData::from_ptr_ref(&data) };
let parsing_mode = ParsingMode::from_bits_truncate(parsing_mode);
if let Some(non_custom) = property_id.non_custom_id() {
@ -4070,6 +4075,7 @@ fn parse_property_into(
declarations,
property_id,
value,
origin,
url_data,
reporter,
parsing_mode,
@ -4079,7 +4085,7 @@ fn parse_property_into(
}
#[no_mangle]
pub extern "C" fn Servo_ParseProperty(
pub unsafe extern "C" fn Servo_ParseProperty(
property: nsCSSPropertyID,
value: &nsACString,
data: *mut URLExtraData,
@ -4091,10 +4097,12 @@ pub extern "C" fn Servo_ParseProperty(
let id = get_property_id_from_nscsspropertyid!(property, Strong::null());
let mut declarations = SourcePropertyDeclaration::new();
let reporter = ErrorReporter::new(ptr::null_mut(), loader, data);
let data = UrlExtraData::from_ptr_ref(&data);
let result = parse_property_into(
&mut declarations,
id,
value,
Origin::Author,
data,
parsing_mode,
quirks_mode.into(),
@ -4454,7 +4462,7 @@ fn set_property(
property_id: PropertyId,
value: &nsACString,
is_important: bool,
data: *mut URLExtraData,
data: &UrlExtraData,
parsing_mode: structs::ParsingMode,
quirks_mode: QuirksMode,
loader: *mut Loader,
@ -4462,11 +4470,12 @@ fn set_property(
before_change_closure: DeclarationBlockMutationClosure,
) -> bool {
let mut source_declarations = SourcePropertyDeclaration::new();
let reporter = ErrorReporter::new(ptr::null_mut(), loader, data);
let reporter = ErrorReporter::new(ptr::null_mut(), loader, data.ptr());
let result = parse_property_into(
&mut source_declarations,
property_id,
value,
Origin::Author,
data,
parsing_mode,
quirks_mode,
@ -4516,7 +4525,7 @@ pub unsafe extern "C" fn Servo_DeclarationBlock_SetProperty(
get_property_id_from_property!(property, false),
value,
is_important,
data,
UrlExtraData::from_ptr_ref(&data),
parsing_mode,
quirks_mode.into(),
loader,
@ -4560,7 +4569,7 @@ pub unsafe extern "C" fn Servo_DeclarationBlock_SetPropertyById(
get_property_id_from_nscsspropertyid!(property, false),
value,
is_important,
data,
UrlExtraData::from_ptr_ref(&data),
parsing_mode,
quirks_mode.into(),
loader,
@ -4723,13 +4732,11 @@ pub extern "C" fn Servo_MediaList_GetMediumAt(
}
#[no_mangle]
pub extern "C" fn Servo_MediaList_AppendMedium(
list: &RawServoMediaList,
new_medium: &nsACString,
) {
pub extern "C" fn Servo_MediaList_AppendMedium(list: &RawServoMediaList, new_medium: &nsACString) {
let new_medium = unsafe { new_medium.as_str_unchecked() };
let url_data = unsafe { dummy_url_data() };
let context = ParserContext::new_for_cssom(
let context = ParserContext::new(
Origin::Author,
url_data,
Some(CssRuleType::Media),
ParsingMode::DEFAULT,
@ -4749,7 +4756,8 @@ pub extern "C" fn Servo_MediaList_DeleteMedium(
) -> bool {
let old_medium = unsafe { old_medium.as_str_unchecked() };
let url_data = unsafe { dummy_url_data() };
let context = ParserContext::new_for_cssom(
let context = ParserContext::new(
Origin::Author,
url_data,
Some(CssRuleType::Media),
ParsingMode::DEFAULT,
@ -5306,18 +5314,16 @@ pub extern "C" fn Servo_DeclarationBlock_SetAspectRatio(
}
#[no_mangle]
pub unsafe extern "C" fn Servo_CSSSupports2(
property: &nsACString,
value: &nsACString,
) -> bool {
let id = get_property_id_from_property!(property, false);
pub extern "C" fn Servo_CSSSupports2(property: &nsACString, value: &nsACString) -> bool {
let id = unsafe { get_property_id_from_property!(property, false) };
let mut declarations = SourcePropertyDeclaration::new();
parse_property_into(
&mut declarations,
id,
value,
DUMMY_URL_DATA,
Origin::Author,
unsafe { dummy_url_data() },
structs::ParsingMode_Default,
QuirksMode::NoQuirks,
CssRuleType::Style,
@ -5327,7 +5333,12 @@ pub unsafe extern "C" fn Servo_CSSSupports2(
}
#[no_mangle]
pub extern "C" fn Servo_CSSSupports(cond: &nsACString) -> bool {
pub extern "C" fn Servo_CSSSupports(
cond: &nsACString,
ua_origin: bool,
chrome_sheet: bool,
quirks: bool,
) -> bool {
let condition = unsafe { cond.as_str_unchecked() };
let mut input = ParserInput::new(&condition);
let mut input = Parser::new(&mut input);
@ -5336,15 +5347,32 @@ pub extern "C" fn Servo_CSSSupports(cond: &nsACString) -> bool {
Err(..) => return false,
};
let url_data = unsafe { dummy_url_data() };
let origin = if ua_origin {
Origin::UserAgent
} else {
Origin::Author
};
let url_data = unsafe {
UrlExtraData::from_ptr_ref(if chrome_sheet {
&DUMMY_CHROME_URL_DATA
} else {
&DUMMY_URL_DATA
})
};
let quirks_mode = if quirks {
QuirksMode::Quirks
} else {
QuirksMode::NoQuirks
};
// NOTE(emilio): The supports API is not associated to any stylesheet,
// so the fact that there is no namespace map here is fine.
let context = ParserContext::new_for_cssom(
let context = ParserContext::new(
origin,
url_data,
Some(CssRuleType::Style),
ParsingMode::DEFAULT,
QuirksMode::NoQuirks,
quirks_mode,
None,
None,
);