зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1525107 - Implement <meta name=color-scheme>. r=dholbert
There are still tests failing because https://bugzilla.mozilla.org/show_bug.cgi?id=1736034 hasn't been synced yet. Once that lands, they will still fail because we don't change Canvas/CanvasText based on color-scheme, but that I'm attaching patches for after this one. Differential Revision: https://phabricator.services.mozilla.com/D129743
This commit is contained in:
Родитель
c5e7ceef0c
Коммит
f85c48f96d
|
@ -220,7 +220,6 @@
|
|||
#include "mozilla/dom/TimeoutManager.h"
|
||||
#include "mozilla/dom/Touch.h"
|
||||
#include "mozilla/dom/TouchEvent.h"
|
||||
#include "mozilla/dom/TreeOrderedArray.h"
|
||||
#include "mozilla/dom/TreeOrderedArrayInlines.h"
|
||||
#include "mozilla/dom/TreeWalker.h"
|
||||
#include "mozilla/dom/URL.h"
|
||||
|
@ -10768,6 +10767,45 @@ void Document::GetXMLDeclaration(nsAString& aVersion, nsAString& aEncoding,
|
|||
}
|
||||
}
|
||||
|
||||
void Document::AddColorSchemeMeta(HTMLMetaElement& aMeta) {
|
||||
mColorSchemeMetaTags.Insert(aMeta);
|
||||
RecomputeColorScheme();
|
||||
}
|
||||
|
||||
void Document::RemoveColorSchemeMeta(HTMLMetaElement& aMeta) {
|
||||
mColorSchemeMetaTags.RemoveElement(aMeta);
|
||||
RecomputeColorScheme();
|
||||
}
|
||||
|
||||
void Document::RecomputeColorScheme() {
|
||||
if (!StaticPrefs::layout_css_color_scheme_enabled()) {
|
||||
return;
|
||||
}
|
||||
auto oldColorScheme = mColorSchemeBits;
|
||||
mColorSchemeBits = 0;
|
||||
const nsTArray<HTMLMetaElement*>& elements = mColorSchemeMetaTags;
|
||||
for (const HTMLMetaElement* el : elements) {
|
||||
nsAutoString content;
|
||||
if (!el->GetAttr(nsGkAtoms::content, content)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 contentU8(content);
|
||||
if (Servo_ColorScheme_Parse(&contentU8, &mColorSchemeBits)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mColorSchemeBits == oldColorScheme) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsPresContext* pc = GetPresContext()) {
|
||||
// This affects system colors, which are inherited, so we need to recascade.
|
||||
pc->RebuildAllStyleData(nsChangeHint(0), RestyleHint::RecascadeSubtree());
|
||||
}
|
||||
}
|
||||
|
||||
bool Document::IsScriptEnabled() {
|
||||
// If this document is sandboxed without 'allow-scripts'
|
||||
// script is not enabled
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/EventTarget.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/dom/TreeOrderedArray.h"
|
||||
#include "mozilla/dom/ViewportMetaData.h"
|
||||
#include "nsAtom.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
@ -2179,11 +2180,17 @@ class Document : public nsINode,
|
|||
/**
|
||||
* Returns the bits for the color-scheme specified by the
|
||||
* <meta name="color-scheme">.
|
||||
*
|
||||
* TODO(emilio): Actually process the meta tag.
|
||||
*/
|
||||
uint8_t GetColorSchemeBits() const { return mColorSchemeBits; }
|
||||
|
||||
/**
|
||||
* Traverses the DOM and computes the supported color schemes as per
|
||||
* https://html.spec.whatwg.org/#meta-color-scheme
|
||||
*/
|
||||
void RecomputeColorScheme();
|
||||
void AddColorSchemeMeta(HTMLMetaElement&);
|
||||
void RemoveColorSchemeMeta(HTMLMetaElement&);
|
||||
|
||||
/**
|
||||
* Returns true if this is what HTML 5 calls an "HTML document" (for example
|
||||
* regular HTML document with Content-Type "text/html", image documents and
|
||||
|
@ -5188,6 +5195,13 @@ class Document : public nsINode,
|
|||
// element.
|
||||
UniquePtr<ViewportMetaData> mLastModifiedViewportMetaData;
|
||||
|
||||
// A tree ordered list of all color-scheme meta tags in this document.
|
||||
//
|
||||
// TODO(emilio): There are other meta tags in the spec that have a similar
|
||||
// processing model to color-scheme. We could store all in-document meta tags
|
||||
// here to get sane and fast <meta> element processing.
|
||||
TreeOrderedArray<HTMLMetaElement> mColorSchemeMetaTags;
|
||||
|
||||
// These member variables cache information about the viewport so we don't
|
||||
// have to recalculate it each time.
|
||||
LayoutDeviceToScreenScale mScaleMinFloat;
|
||||
|
|
|
@ -43,15 +43,15 @@ nsresult HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||
if (Document* document = GetUncomposedDoc()) {
|
||||
if (aName == nsGkAtoms::content) {
|
||||
if (const nsAttrValue* name = GetParsedAttr(nsGkAtoms::name)) {
|
||||
MetaAddedOrChanged(*document, *name, FromChange::Yes);
|
||||
MetaAddedOrChanged(*document, *name, ChangeKind::ContentChange);
|
||||
}
|
||||
CreateAndDispatchEvent(*document, u"DOMMetaChanged"_ns);
|
||||
} else if (aName == nsGkAtoms::name) {
|
||||
if (aOldValue) {
|
||||
MetaRemoved(*document, *aOldValue, FromChange::Yes);
|
||||
MetaRemoved(*document, *aOldValue, ChangeKind::NameChange);
|
||||
}
|
||||
if (aValue) {
|
||||
MetaAddedOrChanged(*document, *aValue, FromChange::Yes);
|
||||
MetaAddedOrChanged(*document, *aValue, ChangeKind::NameChange);
|
||||
}
|
||||
CreateAndDispatchEvent(*document, u"DOMMetaChanged"_ns);
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ nsresult HTMLMetaElement::BindToTree(BindContext& aContext, nsINode& aParent) {
|
|||
}
|
||||
|
||||
if (const nsAttrValue* name = GetParsedAttr(nsGkAtoms::name)) {
|
||||
MetaAddedOrChanged(doc, *name, FromChange::No);
|
||||
MetaAddedOrChanged(doc, *name, ChangeKind::TreeChange);
|
||||
}
|
||||
CreateAndDispatchEvent(doc, u"DOMMetaAdded"_ns);
|
||||
return rv;
|
||||
|
@ -122,7 +122,7 @@ nsresult HTMLMetaElement::BindToTree(BindContext& aContext, nsINode& aParent) {
|
|||
void HTMLMetaElement::UnbindFromTree(bool aNullParent) {
|
||||
if (Document* oldDoc = GetUncomposedDoc()) {
|
||||
if (const nsAttrValue* name = GetParsedAttr(nsGkAtoms::name)) {
|
||||
MetaRemoved(*oldDoc, *name, FromChange::No);
|
||||
MetaRemoved(*oldDoc, *name, ChangeKind::TreeChange);
|
||||
}
|
||||
CreateAndDispatchEvent(*oldDoc, u"DOMMetaRemoved"_ns);
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ JSObject* HTMLMetaElement::WrapNode(JSContext* aCx,
|
|||
|
||||
void HTMLMetaElement::MetaAddedOrChanged(Document& aDoc,
|
||||
const nsAttrValue& aName,
|
||||
FromChange aFromChange) {
|
||||
ChangeKind aChangeKind) {
|
||||
nsAutoString content;
|
||||
const bool hasContent = GetAttr(nsGkAtoms::content, content);
|
||||
if (aName.Equals(nsGkAtoms::viewport, eIgnoreCase)) {
|
||||
|
@ -159,12 +159,21 @@ void HTMLMetaElement::MetaAddedOrChanged(Document& aDoc,
|
|||
return aDoc.UpdateReferrerInfoFromMeta(content,
|
||||
/* aPreload = */ false);
|
||||
}
|
||||
if (aName.Equals(nsGkAtoms::color_scheme, eIgnoreCase)) {
|
||||
if (aChangeKind != ChangeKind::ContentChange) {
|
||||
return aDoc.AddColorSchemeMeta(*this);
|
||||
}
|
||||
return aDoc.RecomputeColorScheme();
|
||||
}
|
||||
}
|
||||
|
||||
void HTMLMetaElement::MetaRemoved(Document& aDoc, const nsAttrValue& aName,
|
||||
FromChange aFromChange) {
|
||||
// TODO(emilio): We probably want to deal with <meta name=color-scheme> and co
|
||||
// here.
|
||||
ChangeKind aChangeKind) {
|
||||
MOZ_ASSERT(aChangeKind != ChangeKind::ContentChange,
|
||||
"Content change can't trigger removal");
|
||||
if (aName.Equals(nsGkAtoms::color_scheme, eIgnoreCase)) {
|
||||
return aDoc.RemoveColorSchemeMeta(*this);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -62,11 +62,11 @@ class HTMLMetaElement final : public nsGenericHTMLElement {
|
|||
virtual ~HTMLMetaElement();
|
||||
|
||||
private:
|
||||
enum class FromChange : bool { No, Yes };
|
||||
enum class ChangeKind : uint8_t { TreeChange, NameChange, ContentChange };
|
||||
void MetaRemoved(Document& aDoc, const nsAttrValue& aName,
|
||||
FromChange aFromChange);
|
||||
ChangeKind aChangeKind);
|
||||
void MetaAddedOrChanged(Document& aDoc, const nsAttrValue& aName,
|
||||
FromChange aFromChange);
|
||||
ChangeKind aChangeKind);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -935,6 +935,11 @@ impl ColorScheme {
|
|||
bits: ColorSchemeFlags::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the raw bitfield.
|
||||
pub fn raw_bits(&self) -> u8 {
|
||||
self.bits.bits
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for ColorScheme {
|
||||
|
|
|
@ -7214,3 +7214,27 @@ pub extern "C" fn Servo_GenericFontFamily_Parse(input: &nsACString) -> GenericFo
|
|||
let mut input = Parser::new(&mut input);
|
||||
GenericFontFamily::parse(&context, &mut input).unwrap_or(GenericFontFamily::None)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ColorScheme_Parse(input: &nsACString, out: &mut u8) -> bool {
|
||||
use style::values::specified::ColorScheme;
|
||||
|
||||
let context = ParserContext::new(
|
||||
Origin::Author,
|
||||
unsafe { dummy_url_data() },
|
||||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let input = unsafe { input.as_str_unchecked() };
|
||||
let mut input = ParserInput::new(&input);
|
||||
let mut input = Parser::new(&mut input);
|
||||
let scheme = match input.parse_entirely(|i| ColorScheme::parse(&context, i)) {
|
||||
Ok(scheme) => scheme,
|
||||
Err(..) => return false,
|
||||
};
|
||||
*out = scheme.raw_bits();
|
||||
true
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
prefs: [layout.css.color-scheme.enabled:true]
|
|
@ -1,24 +1,9 @@
|
|||
[meta-color-scheme-attribute-changes.html]
|
||||
[Removed name attribute from meta color-scheme.]
|
||||
expected: FAIL
|
||||
|
||||
[Set content attribute of meta color-scheme to empty string.]
|
||||
expected: FAIL
|
||||
|
||||
[Set content attribute of meta color-scheme to 'light'.]
|
||||
expected: FAIL
|
||||
|
||||
[Removed the content attribute of meta color-scheme.]
|
||||
expected: FAIL
|
||||
|
||||
[Set meta name to color-scheme.]
|
||||
expected: FAIL
|
||||
|
||||
[Meta color-scheme initially 'dark'.]
|
||||
expected: FAIL
|
||||
|
||||
[Set content attribute of meta color-scheme to an invalid value.]
|
||||
expected: FAIL
|
||||
|
||||
[Set content attribute of meta color-scheme to 'dark'.]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[meta-color-scheme-empty-content-value.html]
|
||||
[Meta color-scheme with empty content attribute has no effect.]
|
||||
expected: FAIL
|
||||
|
|
@ -4,7 +4,3 @@
|
|||
|
||||
[Inserted meta color-scheme before existing in head applies]
|
||||
expected: FAIL
|
||||
|
||||
[Initial color-scheme]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[meta-color-scheme-no-content-value.html]
|
||||
[Meta color-scheme without content attribute has no effect.]
|
||||
expected: FAIL
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
[meta-color-scheme-remove-head.html]
|
||||
[Initial value after removing head including meta color-scheme.]
|
||||
expected: FAIL
|
||||
|
||||
[Meta color-scheme applies.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
[meta-color-scheme-remove.html]
|
||||
[Initial color-scheme with both meta elements removed.]
|
||||
expected: FAIL
|
||||
|
||||
[Second meta applies after first one is removed.]
|
||||
expected: FAIL
|
||||
|
||||
[First meta applies.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[meta-color-scheme-single-value-in-shadow-tree.html]
|
||||
[Meta color-scheme in shadow tree does not apply.]
|
||||
expected: FAIL
|
||||
|
|
@ -251,8 +251,8 @@ STATIC_ATOMS = [
|
|||
Atom("collapse", "collapse"),
|
||||
Atom("collapsed", "collapsed"),
|
||||
Atom("color", "color"),
|
||||
Atom("colorIndex", "color-index"),
|
||||
Atom("colorScheme", "color-scheme"),
|
||||
Atom("color_index", "color-index"),
|
||||
Atom("color_scheme", "color-scheme"),
|
||||
Atom("cols", "cols"),
|
||||
Atom("colspan", "colspan"),
|
||||
Atom("combobox", "combobox"),
|
||||
|
|
Загрузка…
Ссылка в новой задаче