import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1157064 - implementation of font-display. r=heycam,khuey (43fe566f45)
- Bug 1235186 - fix small userfont logging nit. r=m_kato (d40bead913)
- Bug 1188802 - only rebuild local webfont rules when needed. r=heycam (f74200aeb2)
- Backout unrelated code landed in dee3e26cc1c0 by mistake. (5d254b78b6)
- Bug 1236506: Add support for "-webkit-filter" as an alias for CSS property "filter". r=heycam (1e7ac6554a)
- Bug 1230426 - Remove support for -webkit-border-image longhand CSS property aliases. r=dholbert (a1a2d5e82a)
- Bug 1246101 - Restore some auto-completion for the align-/justify-* properties. r=dholbert (a33dd2e7c2)
- Bug 1195142 patch 1 - Set CSS_PROPERTY_CREATES_STACKING_CONTEXT for the opacity property. r=BenWa (e547f7b420)
- Bug 1195142 patch 2 - Add reftests for will-change creating a stacking context. r=BenWa (3bb9dc17b9)
- Bug 1195142 patch 3 - Link to correct specification URLs so the CSSWG test suite system is happy. (a8121cdcf0)
- Bug 1234966 - nsStylePosition::MaxDifference should include nsChangeHint_NeutralChange because CalcDiffrence returns it. r=heycam (aa0bf89e54)
- Bug 1244166: Don't ignore stroke/fill properties in high-contrast mode, since doing so can produce icons that are invisible or whose colors are unrelated to the user's chosen high-contrast colors. r=longsonr (6448b05118)
- Bug 1157057 - Rewrite the handling of the nsITimer object in nrappkitTimerCallback; r=ekr (7cc88409b0)
- Bug 1117984: added proxy connection state enum. r=bwc (0c643ff34a)
- Bug 1231971 - Refactor the NAT simulator to use e10s sockets when appropriate. r=drno (c0722c431b)
- Bug 1231973 - Allow NAT simulator to be enabled with the pref system. r=drno (c92ca4fefa)
- Bug 1201209 - Extend the timeout on socket readiness in test_nr_socket_unittest. r=drno (e9e5400902)
- Bug 1216815 - fix memory leaks in test TCP STUN server. r=mjf (11219f41fc)
- Bug 1194385 - Add new unit tests which demonstrate the current behavior. r=bwc (900c621491)
- crashreporte (2ac99868b6)
- Bug 1150966: Check whether |streams_| is null on stats methods in NrIceMediaStream. r=drno (130a9ac2da)
- Bug 1241690: reduce logging output for unconnected PCs. r=bwc (aa236d7184)
- Bug 1224845 - close sockets on errors and don't connect to IPv4 TURN TCP from IPv6 sockets. r=jesup (f128a67692)
- Bug 1189961 - added DNS AAAA convertion to nICEr transport addr. r=bwc (30c14fe7dd)
- Bug 1247536 - Fix -Wunreachable-code warning in media/mtransport/. r=drno (f6768f8539)
- Bug 1194259: nsresult != NS_IMETHODIMP rs=bustage (3a922e6e14)
- Bug 1237909 part 1 - Remove unused TransportLayer::RunOnThread function. r=bwc (d2d219d63a)
- Bug 1237909 part 2 - Do not return value from task for sync dispatch. r=froydnj (c5ec2aecfc)
- Bug 1245035 - Move LOCAL_INCLUDES to moz.build in media/omx-plugin/lib/ics/libvideoeditorplayer. r=mshal (54c363c9f7)
- Bug 1232069 - Check box sizes before alloc&copy. r=jya (86cfe660e7)
- Bug 1234778: Mark all audio frames as keyframes. r=kentuckyfriedtakahe (5e4f1b54d5)
- Bug 1231169 - report rust mp4parse track status in telemetry. r=kinetik,vladan (260d0fed99)
- Bug 1238420 - Update mp4parse-rust invocations in MP4Metadata to match CAPI changes. r=rillian (64c5d6a1ef)
- Bug 1238420 - Report mp4parse-rust errors via Telemetry. r=rillian,vladan (ff72f8dead)
- Bug 1219452 - Update script for rust mp4parser. r=kinetik (9abc268b60)
- Bug 1220754 - Update rust mp4parse import script for v0.1.3. r=kinetik (7185657598)
- Bug 1224785, Part 1 - Implement alert favicons backend. r=wchen (665c44b0cb)
- Bug 1224785, Part 2 - Show the site favicon in OS X notifications. r=mstange (814ff022ba)
- Bug 1224785, Part 3 - Don't include ShowWith{Icon}Backend on Android. r=me (fe323c2960)
- Bug 1243418 - Fix up incorrect 'aOverwrite' usage and impl in GLUploadHelpers r=jgilbert (67677b4921)
- clarify comment (88003aaf96)
- Bug 1204284: Show paper size options in OS X print dialog. r=smichaud (8bb40b4349)
- Bug 1214511 - Show copies, page range selection, and more on the expanded OSX print dialog. r=mstange (301d5cdccc)
- Bug 1216478 - prefer tooltiptext on a XUL element over title attribute on a containing toolbaritem when determining accessible name, r=surkov (ec1dfcad37)
- Bug 1248838 - ARIA owns change may fail, r=yzen (d183be3f3c)
- Bug 1222531 - turn off -Wextra-tokens on clang-cl in accessible/ directories; r=tbsaunde (6dd4dcae20)
- bug 1241453 - add DocAccessibleParent::GetXPCAccessible() r=davidb (f243398399)
- Bug 1087608 - eliminating a pref observer leak and fixing test timeout overflow that cause intermittents. r=eeejay (413354c349)
- Bug 1238368 - Re-introduce workaround for Android tap gesture. r=yzen (04bb9cea5a)
- Bug 1233863 - ARM64: Disable tests that require ion.enable = 1. r=jimb (b268c03c22)
- Bug 1191976 - Intentionally crash if we hit an IPC FatalError in the  parent process. r=billm (b6e9d90d34)
- Bug 1194721: Add |DaemonRunnable8|, r=shuang (0b293cb8a5)
- Bug 1194721: Add PDU_ prefix to daemon PDU constants, r=shuang (834240b14b)
- Bug 1228546 - Implement peripheral mode support for GATT API. r=brsun, r=mrbkap (01a711cac6)
- Bug 1194721: Add helpers for Gonk sensors daemon, r=gsvelto (524d1d6792)
This commit is contained in:
2024-01-02 22:59:35 +08:00
parent c5205b44c8
commit 3f625686df
134 changed files with 3808 additions and 522 deletions
+54 -1
View File
@@ -815,9 +815,17 @@ Accessible::XULElmName(DocAccessible* aDocument,
nsIContent *bindingParent = aElm->GetBindingParent();
nsIContent* parent =
bindingParent? bindingParent->GetParent() : aElm->GetParent();
nsAutoString ancestorTitle;
while (parent) {
if (parent->IsXULElement(nsGkAtoms::toolbaritem) &&
parent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName)) {
parent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, ancestorTitle)) {
// Before returning this, check if the element itself has a tooltip:
if (aElm->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aName)) {
aName.CompressWhitespace();
return;
}
aName.Assign(ancestorTitle);
aName.CompressWhitespace();
return;
}
@@ -2116,6 +2124,51 @@ Accessible::RemoveChild(Accessible* aChild)
return true;
}
void
Accessible::MoveChild(uint32_t aNewIndex, Accessible* aChild)
{
MOZ_ASSERT(aChild, "No child was given");
MOZ_ASSERT(aChild->mParent == this, "A child from different subtree was given");
MOZ_ASSERT(aChild->mIndexInParent != -1, "Unbound child was given");
MOZ_ASSERT(static_cast<uint32_t>(aChild->mIndexInParent) != aNewIndex,
"No move, same index");
MOZ_ASSERT(aNewIndex <= mChildren.Length(), "Wrong new index was given");
#ifdef DEBUG
// AutoTreeMutation should update group info.
AssertInMutatingSubtree();
#endif
mEmbeddedObjCollector = nullptr;
mChildren.RemoveElementAt(aChild->mIndexInParent);
uint32_t startIdx = aNewIndex, endIdx = aChild->mIndexInParent;
// If the child is moved after its current position.
if (static_cast<uint32_t>(aChild->mIndexInParent) < aNewIndex) {
startIdx = aChild->mIndexInParent;
if (aNewIndex == mChildren.Length() + 1) {
// The child is moved to the end.
mChildren.AppendElement(aChild);
endIdx = mChildren.Length() - 1;
}
else {
mChildren.InsertElementAt(aNewIndex - 1, aChild);
endIdx = aNewIndex;
}
}
else {
// The child is moved prior its current position.
mChildren.InsertElementAt(aNewIndex, aChild);
}
for (uint32_t idx = startIdx; idx <= endIdx; idx++) {
mChildren[idx]->mIndexInParent = idx;
mChildren[idx]->mInt.mIndexOfEmbeddedChild = -1;
}
}
Accessible*
Accessible::GetChildAt(uint32_t aIndex) const
{
+5
View File
@@ -396,6 +396,11 @@ public:
virtual bool InsertChildAt(uint32_t aIndex, Accessible* aChild);
virtual bool RemoveChild(Accessible* aChild);
/**
* Reallocates the child withing its parent.
*/
void MoveChild(uint32_t aNewIndex, Accessible* aChild);
//////////////////////////////////////////////////////////////////////////////
// Accessible tree traverse methods
+6 -5
View File
@@ -2062,7 +2062,10 @@ DocAccessible::DoARIAOwnsRelocation(Accessible* aOwner)
}
if (child->Parent() == aOwner) {
MoveChild(child, insertIdx - 1);
if (child->IsRelocated()) {
children->RemoveElement(child);
}
MoveChild(child, insertIdx);
children->InsertElementAt(arrayIdx, child);
arrayIdx++;
@@ -2145,9 +2148,7 @@ DocAccessible::MoveChild(Accessible* aChild, int32_t aIdxInParent)
reorderEvent->AddSubMutationEvent(hideEvent);
AutoTreeMutation mut(parent);
parent->RemoveChild(aChild);
parent->InsertChildAt(aIdxInParent, aChild);
parent->MoveChild(aIdxInParent, aChild);
aChild->SetRelocated(true);
FireDelayedEvent(hideEvent);
@@ -2178,6 +2179,7 @@ DocAccessible::PutChildrenBack(nsTArray<RefPtr<Accessible> >* aChildren,
RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(owner);
RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(child, false);
reorderEvent->AddSubMutationEvent(hideEvent);
FireDelayedEvent(hideEvent);
{
AutoTreeMutation mut(owner);
@@ -2185,7 +2187,6 @@ DocAccessible::PutChildrenBack(nsTArray<RefPtr<Accessible> >* aChildren,
child->SetRelocated(false);
}
FireDelayedEvent(hideEvent);
MaybeNotifyOfValueChange(owner);
FireDelayedEvent(reorderEvent);
}
+8
View File
@@ -17,3 +17,11 @@ OS_LIBS += [
'ole32',
'oleaut32',
]
# The Windows MIDL code generator creates things like:
#
# #endif !_MIDL_USE_GUIDDEF_
#
# which clang-cl complains about. MSVC doesn't, so turn this warning off.
if CONFIG['CLANG_CL']:
CXXFLAGS += ['-Wno-extra-tokens']
+8
View File
@@ -25,3 +25,11 @@ OS_LIBS += [
'rpcrt4',
'oleaut32',
]
# The Windows MIDL code generator creates things like:
#
# #endif !_MIDL_USE_GUIDDEF_
#
# which clang-cl complains about. MSVC doesn't, so turn this warning off.
if CONFIG['CLANG_CL']:
CFLAGS += ['-Wno-extra-tokens']
+9
View File
@@ -9,6 +9,7 @@
#include "mozilla/a11y/Platform.h"
#include "ProxyAccessible.h"
#include "mozilla/dom/TabParent.h"
#include "xpcAccessibleDocument.h"
namespace mozilla {
namespace a11y {
@@ -292,5 +293,13 @@ DocAccessibleParent::CheckDocTree() const
return true;
}
xpcAccessibleGeneric*
DocAccessibleParent::GetXPCAccessible(ProxyAccessible* aProxy)
{
xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
MOZ_ASSERT(doc);
return doc->GetXPCAccessible(aProxy);
}
} // a11y
} // mozilla
+3
View File
@@ -17,6 +17,8 @@
namespace mozilla {
namespace a11y {
class xpcAccessibleGeneric;
/*
* These objects live in the main process and comunicate with and represent
* an accessible document in a content process.
@@ -159,6 +161,7 @@ private:
const nsTArray<AccessibleData>& aNewTree, uint32_t aIdx,
uint32_t aIdxInParent);
MOZ_WARN_UNUSED_RESULT bool CheckDocTree() const;
xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy);
nsTArray<DocAccessibleParent*> mChildDocs;
DocAccessibleParent* mParentDoc;
+12 -3
View File
@@ -46,7 +46,7 @@ this.AccessFu = { // jshint ignore:line
this._enableOrDisable();
});
aWindow.navigator.mozSettings.addObserver(
SCREENREADER_SETTING, this.handleEvent.bind(this));
SCREENREADER_SETTING, this.handleEvent);
}
}
@@ -68,12 +68,21 @@ this.AccessFu = { // jshint ignore:line
Services.obs.removeObserver(this, 'Accessibility:Settings');
} else if (Utils.win.navigator.mozSettings) {
Utils.win.navigator.mozSettings.removeObserver(
SCREENREADER_SETTING, this.handleEvent.bind(this));
SCREENREADER_SETTING, this.handleEvent);
}
delete this._activatePref;
Utils.uninit();
},
/**
* A lazy getter for event handler that binds the scope to AccessFu object.
*/
get handleEvent() {
delete this.handleEvent;
this.handleEvent = this._handleEvent.bind(this);
return this.handleEvent;
},
/**
* Start AccessFu mode, this primarily means controlling the virtual cursor
* with arrow keys.
@@ -344,7 +353,7 @@ this.AccessFu = { // jshint ignore:line
}
},
handleEvent: function handleEvent(aEvent) {
_handleEvent: function _handleEvent(aEvent) {
switch (aEvent.type) {
case 'TabOpen':
{
+20 -5
View File
@@ -79,6 +79,10 @@ const MOUSE_ID = 'mouse';
const EDGE = 0.1;
// Multiply timeouts by this constant, x2 works great too for slower users.
const TIMEOUT_MULTIPLIER = 1;
// A single pointer down/up sequence periodically precedes the tripple swipe
// gesture on Android. This delay acounts for that.
const IS_ANDROID = Utils.MozBuildApp === 'mobile/android' &&
Utils.AndroidSdkVersion >= 14;
/**
* A point object containing distance travelled data.
@@ -156,6 +160,14 @@ this.GestureSettings = { // jshint ignore:line
maxConsecutiveGestureDelay:
MAX_CONSECUTIVE_GESTURE_DELAY * TIMEOUT_MULTIPLIER,
/**
* A maximum time we wait for a next pointer down event to consider a sequence
* a multi-action gesture.
* @type {Number}
*/
maxGestureResolveTimeout:
MAX_CONSECUTIVE_GESTURE_DELAY * TIMEOUT_MULTIPLIER,
/**
* Delay before tap turns into dwell
* @type {Number}
@@ -194,13 +206,13 @@ this.GestureTracker = { // jshint ignore:line
* @param {Number} aTimeStamp A new pointer event timeStamp.
* @param {Function} aGesture A gesture constructor (default: Tap).
*/
_init: function GestureTracker__init(aDetail, aTimeStamp, aGesture = Tap) {
_init: function GestureTracker__init(aDetail, aTimeStamp, aGesture) {
// Only create a new gesture on |pointerdown| event.
if (aDetail.type !== 'pointerdown') {
return;
}
let points = aDetail.points;
let GestureConstructor = aGesture;
let GestureConstructor = aGesture || (IS_ANDROID ? DoubleTap : Tap);
this._create(GestureConstructor);
this._update(aDetail, aTimeStamp);
},
@@ -359,7 +371,7 @@ Gesture.prototype = {
let delay = this._getDelay(aTimeStamp);
let handler = () => {
Logger.gesture('timer handler');
delete this._timer;
this.clearTimer();
if (!this._inProgress) {
this._deferred.reject();
} else if (this._rejectToOnWait) {
@@ -502,6 +514,7 @@ Gesture.prototype = {
}
Logger.gesture('Resolving', this.id, 'gesture.');
this.isComplete = true;
this.clearTimer();
let detail = this.compile();
if (detail) {
this._emit(detail);
@@ -526,6 +539,7 @@ Gesture.prototype = {
}
Logger.gesture('Rejecting', this.id, 'gesture.');
this.isComplete = true;
this.clearTimer();
return {
id: this.id,
gestureType: aRejectTo
@@ -692,11 +706,12 @@ TapGesture.prototype.pointerup = function TapGesture_pointerup(aPoints) {
let complete = this._update(aPoints, 'pointerup', false, true);
if (complete) {
this.clearTimer();
if (GestureSettings.maxConsecutiveGestureDelay) {
if (GestureSettings.maxGestureResolveTimeout) {
this._pointerUpTimer = setTimeout(() => {
clearTimeout(this._pointerUpTimer);
delete this._pointerUpTimer;
this._deferred.resolve();
}, GestureSettings.maxConsecutiveGestureDelay);
}, GestureSettings.maxGestureResolveTimeout);
} else {
this._deferred.resolve();
}
+21
View File
@@ -110,6 +110,27 @@ function isLogged(aModule)
return gAccRetrieval.isLogged(aModule);
}
/**
* Dumps the accessible tree into console.
*/
function dumpTree(aId, aMsg)
{
function dumpTreeIntl(acc, indent)
{
dump(indent + prettyName(acc) + "\n");
var children = acc.children;
for (var i = 0; i < children.length; i++) {
var child = children.queryElementAt(i, nsIAccessible);
dumpTreeIntl(child, indent + " ");
}
}
dump(aMsg + "\n");
var root = getAccessible(aId);
dumpTreeIntl(root, " ");
}
/**
* Invokes the given function when document is loaded and focused. Preferable
* to mochitests 'addLoadEvent' function -- additionally ensures state of the
+8 -16
View File
@@ -4,12 +4,10 @@
SimpleTest, getBoundsForDOMElm, Point, Utils */
/* exported loadJSON, eventMap */
const Ci = Components.interfaces;
const Cu = Components.utils;
var Ci = Components.interfaces;
var Cu = Components.utils;
Cu.import('resource://gre/modules/accessibility/Utils.jsm');
Cu.import('resource://gre/modules/Geometry.jsm');
Cu.import("resource://gre/modules/accessibility/Gestures.jsm");
var win = getMainChromeWindow(window);
@@ -100,11 +98,6 @@ var eventMap = {
touchmove: sendTouchEvent
};
var originalDwellThreshold = GestureSettings.dwellThreshold;
var originalSwipeMaxDuration = GestureSettings.swipeMaxDuration;
var originalConsecutiveGestureDelay =
GestureSettings.maxConsecutiveGestureDelay;
/**
* Attach a listener for the mozAccessFuGesture event that tests its
* type.
@@ -158,9 +151,11 @@ function setTimers(aTimeStamp, aRemoveDwellThreshold, aRemoveSwipeMaxDuration) {
GestureTracker.current.startTimer(aTimeStamp);
}
function resetTimers() {
GestureSettings.dwellThreshold = originalDwellThreshold;
GestureSettings.swipeMaxDuration = originalSwipeMaxDuration;
function resetTimers(aRemoveGestureResolveDelay) {
GestureSettings.dwellThreshold = AccessFuTest.dwellThreshold;
GestureSettings.swipeMaxDuration = AccessFuTest.swipeMaxDuration;
GestureSettings.maxGestureResolveTimeout = aRemoveGestureResolveDelay ?
0 : AccessFuTest.maxGestureResolveTimeout;
}
/**
@@ -179,10 +174,7 @@ AccessFuTest.addSequence = function AccessFuTest_addSequence(aSequence) {
type: aEvent.type
};
var timeStamp = Date.now();
resetTimers();
GestureSettings.maxConsecutiveGestureDelay =
aEvent.removeConsecutiveGestureDelay ?
0 : originalConsecutiveGestureDelay;
resetTimers(aEvent.removeGestureResolveDelay);
GestureTracker.handle(event, timeStamp);
setTimers(timeStamp, aEvent.removeDwellThreshold,
aEvent.removeSwipeMaxDuration);
+7 -13
View File
@@ -3,7 +3,7 @@
"events": [
{"type": "pointerdown", "points": [{"x": 1, "y": 1, "identifier": 1}]},
{"type": "pointerup", "points": [{"x": 1, "y": 1, "identifier": 1}],
"removeConsecutiveGestureDelay": true }
"removeGestureResolveDelay": true }
],
"expectedGestures": [{ "type": "tap" }]
},
@@ -13,7 +13,7 @@
{"type": "pointermove",
"points": [{"x": 1.03, "y": 1.03, "identifier": 1}]},
{"type": "pointerup", "points": [{"x": 1.03, "y": 1.03, "identifier": 1}],
"removeConsecutiveGestureDelay": true }
"removeGestureResolveDelay": true }
],
"expectedGestures": [{ "type": "tap" }]
},
@@ -37,7 +37,7 @@
"points": [{"x": 0.97, "y": 1.01, "identifier": 1}]},
{"type": "pointerup",
"points": [{"x": 0.97, "y": 1.01, "identifier": 1}],
"removeConsecutiveGestureDelay": true }
"removeGestureResolveDelay": true }
],
"expectedGestures": [{ "type": "doubletap" }]
},
@@ -49,7 +49,7 @@
{"type": "pointerup", "points": [{"x": 1, "y": 1, "identifier": 1}]},
{"type": "pointerdown", "points": [{"x": 1, "y": 1, "identifier": 1}]},
{"type": "pointerup", "points": [{"x": 1, "y": 1, "identifier": 1}],
"removeConsecutiveGestureDelay": true }
"removeGestureResolveDelay": true }
],
"expectedGestures": [{ "type": "tripletap" }]
},
@@ -292,7 +292,7 @@
{"y": 1.30098, "x": 1.52602, "identifier": 0},
{"y": 1.94093, "x": 1.02672, "identifier": 1},
{"y": 2.67229, "x": 0.75246, "identifier": 2}], "type": "pointerup",
"removeConsecutiveGestureDelay": false}],
"removeGestureResolveDelay": true}],
"expectedGestures": [{ "type": "tripletap", "fingers": 3 }]
},
{
@@ -343,14 +343,8 @@
"points": [{"identifier": 0, "x": 1.4375, "y": 2.59375},
{"identifier": 2, "x": 2.15625, "y": 1.489583}]},
{"type": "pointerup",
"points": [{"identifier": 1, "x": 1.083333, "y": 3.71875}]},
{"type": "pointermove",
"points": [{"identifier": 0, "x": 1.427083, "y": 2.59375}]},
{"type": "pointerup",
"points": [{"identifier": 0, "x": 1.427083, "y": 2.59375}]},
{"type": "pointerup",
"points": [{"identifier": 2, "x": 2.15625, "y": 1.489583}],
"removeConsecutiveGestureDelay": false}
"points": [{"identifier": 1, "x": 1.083333, "y": 3.71875}],
"removeGestureResolveDelay": true}
],
"expectedGestures": [{ "type": "tripletap", "fingers": 3 }]
}
+21 -14
View File
@@ -19,17 +19,6 @@ Components.utils.import("resource://gre/modules/accessibility/Utils.jsm");
Components.utils.import("resource://gre/modules/accessibility/EventManager.jsm");
Components.utils.import("resource://gre/modules/accessibility/Gestures.jsm");
const dwellThreshold = GestureSettings.dwellThreshold;
const swipeMaxDuration = GestureSettings.swipeMaxDuration;
const maxConsecutiveGestureDelay = GestureSettings.maxConsecutiveGestureDelay;
// https://bugzilla.mozilla.org/show_bug.cgi?id=1001945 - sometimes
// SimpleTest.executeSoon timeout is bigger than the timer settings in
// GestureSettings that causes intermittents.
GestureSettings.dwellThreshold = dwellThreshold * 10;
GestureSettings.swipeMaxDuration = swipeMaxDuration * 10;
GestureSettings.maxConsecutiveGestureDelay = maxConsecutiveGestureDelay * 10;
var AccessFuTest = {
addFunc: function AccessFuTest_addFunc(aFunc) {
@@ -111,9 +100,13 @@ var AccessFuTest = {
Logger.test = false;
Logger.logLevel = Logger.INFO;
// Reset Gesture Settings.
GestureSettings.dwellThreshold = dwellThreshold;
GestureSettings.swipeMaxDuration = swipeMaxDuration;
GestureSettings.maxConsecutiveGestureDelay = maxConsecutiveGestureDelay;
GestureSettings.dwellThreshold = this.dwellThreshold =
this.originalDwellThreshold;
GestureSettings.swipeMaxDuration = this.swipeMaxDuration =
this.originalSwipeMaxDuration;
GestureSettings.maxGestureResolveTimeout =
this.maxGestureResolveTimeout =
this.originalMaxGestureResolveTimeout;
// Finish through idle callback to let AccessFu._disable complete.
SimpleTest.executeSoon(function () {
AccessFu.detach();
@@ -160,6 +153,20 @@ var AccessFuTest = {
['dom.mozSettings.enabled', true]];
prefs.push.apply(prefs, aAdditionalPrefs);
this.originalDwellThreshold = GestureSettings.dwellThreshold;
this.originalSwipeMaxDuration = GestureSettings.swipeMaxDuration;
this.originalMaxGestureResolveTimeout =
GestureSettings.maxGestureResolveTimeout;
// https://bugzilla.mozilla.org/show_bug.cgi?id=1001945 - sometimes
// SimpleTest.executeSoon timeout is bigger than the timer settings in
// GestureSettings that causes intermittents.
this.dwellThreshold = GestureSettings.dwellThreshold =
GestureSettings.dwellThreshold * 10;
this.swipeMaxDuration = GestureSettings.swipeMaxDuration =
GestureSettings.swipeMaxDuration * 10;
this.maxGestureResolveTimeout = GestureSettings.maxGestureResolveTimeout =
GestureSettings.maxGestureResolveTimeout * 10;
SpecialPowers.pushPrefEnv({ 'set': prefs }, function () {
if (AccessFuTest._waitForExplicitFinish) {
// Run all test functions asynchronously.
+1 -1
View File
@@ -1,4 +1,4 @@
const Cu = Components.utils;
var Cu = Components.utils;
const PREF_UTTERANCE_ORDER = "accessibility.accessfu.utterance";
Cu.import('resource://gre/modules/accessibility/Utils.jsm');
@@ -20,7 +20,7 @@
function stopAccessFu() {
SpecialPowers.setIntPref("accessibility.accessfu.activate", 0);
AccessFuTest.once_log("EventManager.stop", AccessFuTest.finish);
AccessFuTest.once_log("EventManager.stop", () => AccessFuTest.finish());
}
function hide(id) {
@@ -68,7 +68,7 @@
// Listen for initial 'EventManager.start' and disable AccessFu.
function prefStop() {
ok(AccessFu._enabled, "AccessFu was started via preference.");
AccessFuTest.once_log("EventManager.stop", AccessFuTest.finish);
AccessFuTest.once_log("EventManager.stop", () => AccessFuTest.finish());
SpecialPowers.setIntPref("accessibility.accessfu.activate", 0);
}
+1
View File
@@ -13,4 +13,5 @@ support-files =
[test_list.html]
[test_markup.html]
[test_svg.html]
[test_toolbaritem.xul]
[test_tree.xul]
@@ -0,0 +1,84 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<?xml-stylesheet href="general.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessibility Name Calculating Test.">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../name.js"></script>
<script type="application/javascript">
<![CDATA[
var gQueue = null;
function doTest() {
let ids = [];
for (let item of ["button", "textbox"]) {
ids.push(item + "withtooltip");
ids.push(item + "withouttooltip");
ids.push("nested" + item + "withtooltip");
ids.push("nested" + item + "withouttooltip");
}
for (let id of ids) {
if (id.endsWith("withtooltip")) {
testName(id, id, id + " should have individual name from its tooltip - ");
} else {
testName(id, "Toolbaritem title", id + " should have toolbaritem's title for a name - ");
}
}
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1216478"
title="Items with tooltips inside items with a label should use their own tooltip as an accessible name, not the ancestor's label">
Mozilla Bug 1216478
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<toolbox>
<toolbar>
<toolbaritem title="Toolbaritem title">
<toolbarbutton id="buttonwithtooltip" tooltiptext="buttonwithtooltip"/>
<toolbarbutton id="buttonwithouttooltip"/>
<textbox id="textboxwithtooltip" tooltiptext="textboxwithtooltip"/>
<textbox id="textboxwithouttooltip"/>
<vbox>
<toolbarbutton id="nestedbuttonwithtooltip" tooltiptext="nestedbuttonwithtooltip"/>
<toolbarbutton id="nestedbuttonwithouttooltip"/>
<textbox id="nestedtextboxwithtooltip" tooltiptext="nestedtextboxwithtooltip"/>
<textbox id="nestedtextboxwithouttooltip"/>
</vbox>
</toolbaritem>
</toolbar>
</toolbox>
</vbox> <!-- close tests area -->
</hbox> <!-- close main area -->
</window>
@@ -23,19 +23,21 @@
// Invokers
////////////////////////////////////////////////////////////////////////////
function removeARIAOwns()
function changeARIAOwns()
{
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getNode("t1_checkbox")),
new invokerChecker(EVENT_HIDE, getNode("t1_button")),
new invokerChecker(EVENT_SHOW, getNode("t1_button")),
new invokerChecker(EVENT_HIDE, getNode("t1_subdiv")),
new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
new invokerChecker(EVENT_HIDE, getNode("t1_checkbox")),
new invokerChecker(EVENT_SHOW, getNode("t1_checkbox")),
new invokerChecker(EVENT_REORDER, getNode("t1_container"))
];
this.invoke = function removeARIAOwns_invoke()
this.invoke = function setARIAOwns_invoke()
{
// children are swapped
// children are swapped by ARIA owns
var tree =
{ SECTION: [
{ CHECKBUTTON: [
@@ -45,6 +47,41 @@
] };
testAccessibleTree("t1_container", tree);
getNode("t1_container").
setAttribute("aria-owns", "t1_button t1_subdiv");
}
this.finalCheck = function setARIAOwns_finalCheck()
{
// children are swapped again, button and subdiv are appended to
// the children.
var tree =
{ SECTION: [
{ CHECKBUTTON: [ ] }, // checkbox, native order
{ PUSHBUTTON: [ ] }, // button, rearranged by ARIA own
{ SECTION: [ ] } // subdiv from the subtree, ARIA owned
] };
testAccessibleTree("t1_container", tree);
}
this.getID = function setARIAOwns_getID()
{
return "Change @aria-owns attribute";
}
}
function removeARIAOwns()
{
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getNode("t1_button")),
new invokerChecker(EVENT_HIDE, getNode("t1_subdiv")),
new invokerChecker(EVENT_SHOW, getNode("t1_button")),
new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
new invokerChecker(EVENT_REORDER, getNode("t1_container"))
];
this.invoke = function removeARIAOwns_invoke()
{
getNode("t1_container").removeAttribute("aria-owns");
}
@@ -418,6 +455,7 @@
gQueue = new eventQueue();
// test1
gQueue.push(new changeARIAOwns());
gQueue.push(new removeARIAOwns());
gQueue.push(new setARIAOwns());
gQueue.push(new addIdToARIAOwns());
+8
View File
@@ -50,4 +50,12 @@ FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
# The Windows MIDL code generator creates things like:
#
# #endif !_MIDL_USE_GUIDDEF_
#
# which clang-cl complains about. MSVC doesn't, so turn this warning off.
if CONFIG['CLANG_CL']:
CXXFLAGS += ['-Wno-extra-tokens']
include('/ipc/chromium/chromium-config.mozbuild')
+8
View File
@@ -58,6 +58,14 @@ LOCAL_INCLUDES += [
'/dom/base',
]
# The Windows MIDL code generator creates things like:
#
# #endif !_MIDL_USE_GUIDDEF_
#
# which clang-cl complains about. MSVC doesn't, so turn this warning off.
if CONFIG['CLANG_CL']:
CXXFLAGS += ['-Wno-extra-tokens']
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
@@ -588,9 +588,9 @@ nsresult
BluetoothDaemonGattModule::ClientSetAdvDataCmd(
int aServerIf, bool aIsScanRsp, bool aIsNameIncluded,
bool aIsTxPowerIncluded, int aMinInterval, int aMaxInterval, int aApperance,
uint16_t aManufacturerLen, char* aManufacturerData,
uint16_t aServiceDataLen, char* aServiceData,
uint16_t aServiceUuidLen, char* aServiceUuid,
const nsTArray<uint8_t>& aManufacturerData,
const nsTArray<uint8_t>& aServiceData,
const nsTArray<BluetoothUuid>& aServiceUuids,
BluetoothGattResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
@@ -598,6 +598,17 @@ BluetoothDaemonGattModule::ClientSetAdvDataCmd(
nsAutoPtr<DaemonSocketPDU> pdu(
new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_SET_ADV_DATA, 0));
uint16_t manufacturerDataByteLen =
aManufacturerData.Length() * sizeof(uint8_t);
uint16_t serviceDataByteLen = aServiceData.Length() * sizeof(uint8_t);
uint16_t serviceUuidsByteLen =
aServiceUuids.Length() * sizeof(BluetoothUuid::mUuid);
uint8_t* manufacturerData =
const_cast<uint8_t*>(aManufacturerData.Elements());
uint8_t* serviceData = const_cast<uint8_t*>(aServiceData.Elements());
BluetoothUuid* serviceUuids =
const_cast<BluetoothUuid*>(aServiceUuids.Elements());
nsresult rv = PackPDU(
PackConversion<int, int32_t>(aServerIf),
PackConversion<bool, uint8_t>(aIsScanRsp),
@@ -606,10 +617,12 @@ BluetoothDaemonGattModule::ClientSetAdvDataCmd(
PackConversion<int, int32_t>(aMinInterval),
PackConversion<int, int32_t>(aMaxInterval),
PackConversion<int, int32_t>(aApperance),
aManufacturerLen, aServiceDataLen, aServiceUuidLen,
PackArray<char>(aManufacturerData, aManufacturerLen),
PackArray<char>(aServiceData, aServiceDataLen),
PackArray<char>(aServiceUuid, aServiceUuidLen), *pdu);
manufacturerDataByteLen, serviceDataByteLen, serviceUuidsByteLen,
PackArray<uint8_t>(manufacturerData, aManufacturerData.Length()),
PackArray<uint8_t>(serviceData, aServiceData.Length()),
PackArray<PackReversed<BluetoothUuid>>(
serviceUuids, aServiceUuids.Length()),
*pdu);
if (NS_FAILED(rv)) {
return rv;
}
@@ -2415,17 +2428,17 @@ void
BluetoothDaemonGattInterface::SetAdvData(
int aServerIf, bool aIsScanRsp, bool aIsNameIncluded,
bool aIsTxPowerIncluded, int aMinInterval, int aMaxInterval, int aApperance,
uint16_t aManufacturerLen, char* aManufacturerData,
uint16_t aServiceDataLen, char* aServiceData,
uint16_t aServiceUUIDLen, char* aServiceUUID,
const nsTArray<uint8_t>& aManufacturerData,
const nsTArray<uint8_t>& aServiceData,
const nsTArray<BluetoothUuid>& aServiceUuids,
BluetoothGattResultHandler* aRes)
{
MOZ_ASSERT(mModule);
nsresult rv = mModule->ClientSetAdvDataCmd(
aServerIf, aIsScanRsp, aIsNameIncluded, aIsTxPowerIncluded, aMinInterval,
aMaxInterval, aApperance, aManufacturerLen, aManufacturerData,
aServiceDataLen, aServiceData, aServiceUUIDLen, aServiceUUID, aRes);
aMaxInterval, aApperance, aManufacturerData, aServiceData, aServiceUuids,
aRes);
if (NS_FAILED(rv)) {
DispatchError(aRes, rv);
@@ -203,12 +203,9 @@ public:
int aMinInterval,
int aMaxInterval,
int aApperance,
uint16_t aManufacturerLen,
char* aManufacturerData,
uint16_t aServiceDataLen,
char* aServiceData,
uint16_t aServiceUUIDLen,
char* aServiceUUID,
const nsTArray<uint8_t>& aManufacturerData,
const nsTArray<uint8_t>& aServiceData,
const nsTArray<BluetoothUuid>& aServiceUuids,
BluetoothGattResultHandler* aRes);
nsresult ClientTestCommandCmd(int aCommand,
@@ -908,9 +905,9 @@ public:
int aMinInterval,
int aMaxInterval,
int aApperance,
uint16_t aManufacturerLen, char* aManufacturerData,
uint16_t aServiceDataLen, char* aServiceData,
uint16_t aServiceUuidLen, char* aServiceUuid,
const nsTArray<uint8_t>& aManufacturerData,
const nsTArray<uint8_t>& aServiceData,
const nsTArray<BluetoothUuid>& aServiceUuids,
BluetoothGattResultHandler* aRes) override;
void TestCommand(int aCommand,
@@ -190,6 +190,8 @@ public:
int mClientIf;
int mConnId;
RefPtr<BluetoothReplyRunnable> mStartLeScanRunnable;
RefPtr<BluetoothReplyRunnable> mStartAdvertisingRunnable;
RefPtr<BluetoothReplyRunnable> mStopAdvertisingRunnable;
RefPtr<BluetoothReplyRunnable> mConnectRunnable;
RefPtr<BluetoothReplyRunnable> mDisconnectRunnable;
RefPtr<BluetoothReplyRunnable> mDiscoverRunnable;
@@ -203,6 +205,8 @@ public:
BluetoothGattClientReadDescState mReadDescriptorState;
BluetoothGattClientWriteDescState mWriteDescriptorState;
BluetoothGattAdvertisingData mAdvertisingData;
/**
* These temporary arrays are used only during discover operations.
* All of them are empty if there are no ongoing discover operations.
@@ -293,6 +297,7 @@ public:
*/
bool mIsRegistering;
RefPtr<BluetoothReplyRunnable> mRegisterServerRunnable;
RefPtr<BluetoothReplyRunnable> mConnectPeripheralRunnable;
RefPtr<BluetoothReplyRunnable> mDisconnectPeripheralRunnable;
RefPtr<BluetoothReplyRunnable> mUnregisterServerRunnable;
@@ -887,6 +892,195 @@ BluetoothGattManager::StopLeScan(const BluetoothUuid& aScanUuid,
new StopLeScanResultHandler(aRunnable, client->mClientIf));
}
class BluetoothGattManager::StartAdvertisingResultHandler final
: public BluetoothGattResultHandler
{
public:
StartAdvertisingResultHandler(BluetoothGattClient* aClient)
: mClient(aClient)
{
MOZ_ASSERT(mClient);
}
void Listen() override
{
MOZ_ASSERT(mClient->mStartAdvertisingRunnable);
DispatchReplySuccess(mClient->mStartAdvertisingRunnable);
mClient->mStartAdvertisingRunnable = nullptr;
}
void OnError(BluetoothStatus aStatus) override
{
BT_WARNING("BluetoothGattInterface::StartLeAdvertising failed: %d",
(int)aStatus);
MOZ_ASSERT(mClient->mStartAdvertisingRunnable);
// Unregister client if startAdvertising failed
if (mClient->mClientIf > 0) {
BluetoothGattManager* gattManager = BluetoothGattManager::Get();
NS_ENSURE_TRUE_VOID(gattManager);
RefPtr<BluetoothVoidReplyRunnable> result =
new BluetoothVoidReplyRunnable(nullptr);
gattManager->UnregisterClient(mClient->mClientIf, result);
}
DispatchReplyError(mClient->mStartAdvertisingRunnable, aStatus);
mClient->mStartAdvertisingRunnable = nullptr;
}
private:
RefPtr<BluetoothGattClient> mClient;
};
class BluetoothGattManager::SetAdvDataResultHandler final
: public BluetoothGattResultHandler
{
public:
SetAdvDataResultHandler(BluetoothGattClient* aClient)
: mClient(aClient)
{
MOZ_ASSERT(mClient);
}
void SetAdvData() override
{
sBluetoothGattInterface->Listen(
mClient->mClientIf,
true /* Start */,
new StartAdvertisingResultHandler(mClient));
}
void OnError(BluetoothStatus aStatus) override
{
BT_WARNING("BluetoothGattInterface::StartLeAdvertising failed: %d",
(int)aStatus);
MOZ_ASSERT(mClient->mStartAdvertisingRunnable);
// Unregister client if startAdvertising failed
if (mClient->mClientIf > 0) {
BluetoothGattManager* gattManager = BluetoothGattManager::Get();
NS_ENSURE_TRUE_VOID(gattManager);
RefPtr<BluetoothVoidReplyRunnable> result =
new BluetoothVoidReplyRunnable(nullptr);
gattManager->UnregisterClient(mClient->mClientIf, result);
}
DispatchReplyError(mClient->mStartAdvertisingRunnable, aStatus);
mClient->mStartAdvertisingRunnable = nullptr;
}
private:
RefPtr<BluetoothGattClient> mClient;
};
void
BluetoothGattManager::StartAdvertising(
const BluetoothUuid& aAppUuid,
const BluetoothGattAdvertisingData& aData,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
// Reject the startAdvertising request if the clientIf is being used.
if (NS_WARN_IF(index != sClients->NoIndex)) {
DispatchReplyError(aRunnable,
NS_LITERAL_STRING("start advertising failed"));
return;
}
index = sClients->Length();
sClients->AppendElement(new BluetoothGattClient(aAppUuid,
BluetoothAddress::ANY));
RefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
client->mStartAdvertisingRunnable = aRunnable;
client->mAdvertisingData = aData;
// 'startAdvertising' will be proceeded after client registered
sBluetoothGattInterface->RegisterClient(
aAppUuid, new RegisterClientResultHandler(client));
}
class BluetoothGattManager::StopAdvertisingResultHandler final
: public BluetoothGattResultHandler
{
public:
StopAdvertisingResultHandler(BluetoothGattClient* aClient)
: mClient(aClient)
{
MOZ_ASSERT(mClient);
}
void Listen() override
{
MOZ_ASSERT(mClient->mStopAdvertisingRunnable);
// Unregister client when stopLeScan succeeded
if (mClient->mClientIf > 0) {
BluetoothGattManager* gattManager = BluetoothGattManager::Get();
NS_ENSURE_TRUE_VOID(gattManager);
RefPtr<BluetoothVoidReplyRunnable> result =
new BluetoothVoidReplyRunnable(nullptr);
gattManager->UnregisterClient(mClient->mClientIf, result);
}
DispatchReplySuccess(mClient->mStopAdvertisingRunnable);
mClient->mStopAdvertisingRunnable = nullptr;
}
void OnError(BluetoothStatus aStatus) override
{
BT_WARNING("BluetoothGattInterface::StopAdvertising failed: %d",
(int)aStatus);
MOZ_ASSERT(mClient->mStopAdvertisingRunnable);
DispatchReplyError(mClient->mStopAdvertisingRunnable, aStatus);
mClient->mStopAdvertisingRunnable = nullptr;
}
private:
RefPtr<BluetoothGattClient> mClient;
};
void
BluetoothGattManager::StopAdvertising(const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
if (NS_WARN_IF(index == sClients->NoIndex)) {
// Reject the stop advertising request
DispatchReplyError(aRunnable, NS_LITERAL_STRING("StopAdvertising failed"));
return;
}
RefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
// Reject the stop advertising request if there is an ongoing one.
if (client->mStopAdvertisingRunnable) {
DispatchReplyError(aRunnable, STATUS_BUSY);
return;
}
client->mStopAdvertisingRunnable = aRunnable;
sBluetoothGattInterface->Listen(
client->mClientIf,
false /* Stop */,
new StopAdvertisingResultHandler(client));
}
class BluetoothGattManager::ConnectResultHandler final
: public BluetoothGattResultHandler
{
@@ -1642,6 +1836,12 @@ public:
mServer->mAddServiceState.Reset();
}
if (mServer->mRegisterServerRunnable) {
DispatchReplyError(mServer->mRegisterServerRunnable,
NS_LITERAL_STRING("Register GATT server failed"));
mServer->mRegisterServerRunnable = nullptr;
}
mServer->mIsRegistering = false;
sServers->RemoveElement(mServer);
}
@@ -1650,6 +1850,48 @@ private:
RefPtr<BluetoothGattServer> mServer;
};
void
BluetoothGattManager::RegisterServer(const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
ENSURE_GATT_INTF_IS_READY_VOID(aRunnable);
size_t index = sServers->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
if (index == sServers->NoIndex) {
index = sServers->Length();
sServers->AppendElement(new BluetoothGattServer(aAppUuid));
}
RefPtr<BluetoothGattServer> server = (*sServers)[index];
/**
* There are four cases here for handling aRunnable.
* 1) Server interface is already registered: Resolve the runnable.
* 2) Server interface is not registered, but there is
* an existing |RegisterServerRunnable|: Reject with STATUS_BUSY.
* 3) Server interface is registering without an existing
* |RegisterServerRunnable|: Save the runnable into |GattServer| and will
* resolve or reject it in |RegisterServerNotification| later.
* 4) Server interface is neither registered nor registering: Save the
* the runnable into |GattServer| and trigger a registration procedure.
* The runnable will be resolved or rejected in
* |RegisterServerNotification| later.
*/
if (server->mServerIf > 0) {
DispatchReplySuccess(aRunnable);
} else if (server->mRegisterServerRunnable) {
DispatchReplyError(aRunnable, STATUS_BUSY);
} else if (server->mIsRegistering) {
server->mRegisterServerRunnable = aRunnable;
} else {
server->mRegisterServerRunnable = aRunnable;
sBluetoothGattInterface->RegisterServer(
aAppUuid, new RegisterServerResultHandler(server));
}
}
class BluetoothGattManager::ConnectPeripheralResultHandler final
: public BluetoothGattResultHandler
{
@@ -2552,7 +2794,9 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
NS_LITERAL_STRING(
"StartLeScan failed due to registration failed"));
client->mStartLeScanRunnable = nullptr;
} else if (client->mConnectRunnable) {
}
if (client->mConnectRunnable) {
// Reject the connect request
DispatchReplyError(client->mConnectRunnable,
NS_LITERAL_STRING(
@@ -2560,6 +2804,15 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
client->mConnectRunnable = nullptr;
}
if (client->mStartAdvertisingRunnable) {
// Reject the start advertising request
DispatchReplyError(
client->mStartAdvertisingRunnable,
NS_LITERAL_STRING(
"StartAdvertising failed due to registration failed"));
client->mStartAdvertisingRunnable = nullptr;
}
sClients->RemoveElement(client);
return;
}
@@ -2577,7 +2830,9 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
sBluetoothGattInterface->Scan(
aClientIf, true /* start */,
new StartLeScanResultHandler(client));
} else if (client->mConnectRunnable) {
}
if (client->mConnectRunnable) {
// Client just registered, proceed remaining connect request.
ENSURE_GATT_INTF_IS_READY_VOID(client->mConnectRunnable);
sBluetoothGattInterface->Connect(
@@ -2585,6 +2840,17 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
TRANSPORT_AUTO,
new ConnectResultHandler(client));
}
if (client->mStartAdvertisingRunnable) {
// StartAdvertising request will be proceed after SetAdvData succeeded.
ENSURE_GATT_INTF_IS_READY_VOID(client->mStartAdvertisingRunnable);
BluetoothGattAdvertisingData* data = &(client->mAdvertisingData);
sBluetoothGattInterface->SetAdvData(
aClientIf, false /* isScanRsp */, data->mIncludeDevName,
data->mIncludeTxPower, 0 /* min interval */, 0 /* max interval */,
data->mAppearance, data->mManufacturerData, data->mServiceData,
data->mServiceUuids, new SetAdvDataResultHandler(client));
}
}
class BluetoothGattManager::ScanDeviceTypeResultHandler final
@@ -3355,6 +3621,14 @@ BluetoothGattManager::RegisterServerNotification(BluetoothGattStatus aStatus,
server->mAddServiceState.Reset();
}
if (server->mRegisterServerRunnable) {
// Reject the register server request
DispatchReplyError(
server->mRegisterServerRunnable,
NS_LITERAL_STRING("Register server failed"));
server->mRegisterServerRunnable = nullptr;
}
sServers->RemoveElement(server);
return;
}
@@ -3382,6 +3656,11 @@ BluetoothGattManager::RegisterServerNotification(BluetoothGattStatus aStatus,
server->mAddServiceState.mHandleCount,
new ServerAddServiceResultHandler(server));
}
if (server->mRegisterServerRunnable) {
DispatchReplySuccess(server->mRegisterServerRunnable);
server->mRegisterServerRunnable = nullptr;
}
}
void
@@ -35,6 +35,13 @@ public:
void StopLeScan(const BluetoothUuid& aScanUuid,
BluetoothReplyRunnable* aRunnable);
void StartAdvertising(const BluetoothUuid& aAppUuid,
const BluetoothGattAdvertisingData& aData,
BluetoothReplyRunnable* aRunnable);
void StopAdvertising(const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable);
void Connect(const BluetoothUuid& aAppUuid,
const BluetoothAddress& aDeviceAddr,
BluetoothReplyRunnable* aRunnable);
@@ -92,6 +99,9 @@ public:
const nsTArray<uint8_t>& aValue,
BluetoothReplyRunnable* aRunnable);
void RegisterServer(const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable);
void ConnectPeripheral(
const BluetoothUuid& aAppUuid,
const BluetoothAddress& aAddress,
@@ -176,6 +186,9 @@ private:
class UnregisterClientResultHandler;
class StartLeScanResultHandler;
class StopLeScanResultHandler;
class StartAdvertisingResultHandler;
class SetAdvDataResultHandler;
class StopAdvertisingResultHandler;
class ConnectResultHandler;
class DisconnectResultHandler;
class DiscoverResultHandler;
@@ -362,6 +362,35 @@ BluetoothServiceBluedroid::StopLeScanInternal(
gatt->StopLeScan(aScanUuid, aRunnable);
}
void
BluetoothServiceBluedroid::StartAdvertisingInternal(
const BluetoothUuid& aAppUuid,
const BluetoothGattAdvertisingData& aAdvData,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
ENSURE_BLUETOOTH_IS_ENABLED_VOID(aRunnable);
BluetoothGattManager* gatt = BluetoothGattManager::Get();
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
gatt->StartAdvertising(aAppUuid, aAdvData, aRunnable);
}
void
BluetoothServiceBluedroid::StopAdvertisingInternal(
const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
ENSURE_BLUETOOTH_IS_ENABLED_VOID(aRunnable);
BluetoothGattManager* gatt = BluetoothGattManager::Get();
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
gatt->StopAdvertising(aAppUuid, aRunnable);
}
void
BluetoothServiceBluedroid::ConnectGattClientInternal(
const BluetoothUuid& aAppUuid, const BluetoothAddress& aDeviceAddress,
@@ -543,6 +572,20 @@ BluetoothServiceBluedroid::GattClientWriteDescriptorValueInternal(
}
// GATT Server
void
BluetoothServiceBluedroid::GattServerRegisterInternal(
const BluetoothUuid& aAppUuid, BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
ENSURE_BLUETOOTH_IS_ENABLED_VOID(aRunnable);
BluetoothGattManager* gatt = BluetoothGattManager::Get();
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
gatt->RegisterServer(aAppUuid, aRunnable);
}
void
BluetoothServiceBluedroid::GattServerConnectPeripheralInternal(
const BluetoothUuid& aAppUuid, const BluetoothAddress& aAddress,
@@ -284,6 +284,15 @@ public:
virtual void StopLeScanInternal(const BluetoothUuid& aScanUuid,
BluetoothReplyRunnable* aRunnable);
virtual void StartAdvertisingInternal(
const BluetoothUuid& aAppUuid,
const BluetoothGattAdvertisingData& aAdvData,
BluetoothReplyRunnable* aRunnable) override;
virtual void StopAdvertisingInternal(
const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
ConnectGattClientInternal(const BluetoothUuid& aAppUuid,
const BluetoothAddress& aDeviceAddress,
@@ -354,6 +363,11 @@ public:
const nsTArray<uint8_t>& aValue,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattServerRegisterInternal(
const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattServerConnectPeripheralInternal(
const BluetoothUuid& aAppUuid,
@@ -4300,6 +4300,21 @@ BluetoothDBusService::StopLeScanInternal(
{
}
void
BluetoothDBusService::StartAdvertisingInternal(
const BluetoothUuid& aAppUuid,
const BluetoothGattAdvertisingData& aAdvData,
BluetoothReplyRunnable* aRunnable)
{
}
void
BluetoothDBusService::StopAdvertisingInternal(
const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable)
{
}
void
BluetoothDBusService::ConnectGattClientInternal(
const BluetoothUuid& aAppUuid, const BluetoothAddress& aDeviceAddress,
@@ -4512,6 +4527,12 @@ BluetoothDBusService::ReplyToMapMessageUpdate(long aMasId, bool aStatus,
{
}
void
BluetoothDBusService::GattServerRegisterInternal(
const BluetoothUuid& aAppUuid, BluetoothReplyRunnable* aRunnable)
{
}
void
BluetoothDBusService::GattServerConnectPeripheralInternal(
const BluetoothUuid& aAppUuid, const BluetoothAddress& aAddress,
@@ -292,6 +292,15 @@ public:
StopLeScanInternal(const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
StartAdvertisingInternal(const BluetoothUuid& aAppUuid,
const BluetoothGattAdvertisingData& aAdvData,
BluetoothReplyRunnable* aRunnable) override;
virtual void
StopAdvertisingInternal(const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
ConnectGattClientInternal(const BluetoothUuid& aAppUuid,
const BluetoothAddress& aDeviceAddress,
@@ -362,6 +371,11 @@ public:
const nsTArray<uint8_t>& aValue,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattServerRegisterInternal(
const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattServerConnectPeripheralInternal(
const BluetoothUuid& aAppUuid,
+56
View File
@@ -1306,6 +1306,62 @@ enum BluetoothGapDataType {
GAP_COMPLETE_NAME = 0X09, // Complete Local Name
};
struct BluetoothGattAdvertisingData {
/**
* Uuid value of Appearance characteristic of the GAP service which can be
* mapped to an icon or string that describes the physical representation of
* the device during the device discovery procedure.
*/
uint16_t mAppearance;
/**
* Whether to broadcast with device name or not.
*/
bool mIncludeDevName;
/**
* Whether to broadcast with TX power or not.
*/
bool mIncludeTxPower;
/**
* Byte array of custom manufacturer specific data.
*
* The first 2 octets contain the Company Identifier Code followed by
* additional manufacturer specific data. See Core Specification Supplement
* (CSS) v6 1.4 for more details.
*/
nsTArray<uint8_t> mManufacturerData;
/**
* Consists of a service UUID with the data associated with that service.
* Please see Core Specification Supplement (CSS) v6 1.11 for more details.
*/
nsTArray<uint8_t> mServiceData;
/**
* A list of Service or Service Class UUIDs.
* Please see Core Specification Supplement (CSS) v6 1.1 for more details.
*/
nsTArray<BluetoothUuid> mServiceUuids;
BluetoothGattAdvertisingData()
: mAppearance(0)
, mIncludeDevName(false)
, mIncludeTxPower(false)
{ }
bool operator==(const BluetoothGattAdvertisingData& aOther) const
{
return mIncludeDevName == aOther.mIncludeDevName &&
mIncludeTxPower == aOther.mIncludeTxPower &&
mAppearance == aOther.mAppearance &&
mManufacturerData == aOther.mManufacturerData &&
mServiceData == aOther.mServiceData &&
mServiceUuids == aOther.mServiceUuids;
}
};
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_BluetoothCommon_h
+3 -6
View File
@@ -1028,12 +1028,9 @@ public:
int aMinInterval,
int aMaxInterval,
int aApperance,
uint16_t aManufacturerLen,
char* aManufacturerData,
uint16_t aServiceDataLen,
char* aServiceData,
uint16_t aServiceUUIDLen,
char* aServiceUUID,
const nsTArray<uint8_t>& aManufacturerData,
const nsTArray<uint8_t>& aServiceData,
const nsTArray<BluetoothUuid>& aServiceUuids,
BluetoothGattResultHandler* aRes) = 0;
virtual void TestCommand(int aCommand,
+17
View File
@@ -239,6 +239,18 @@ public:
StartLeScanInternal(const nsTArray<BluetoothUuid>& aServiceUuids,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Start/Stop advertising.
*/
virtual void
StartAdvertisingInternal(const BluetoothUuid& aAppUuid,
const BluetoothGattAdvertisingData& aAdvData,
BluetoothReplyRunnable* aRunnable) { }
virtual void
StopAdvertisingInternal(const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable) { }
/**
* Set a property for the specified object
*
@@ -586,6 +598,11 @@ public:
const nsTArray<uint8_t>& aValue,
BluetoothReplyRunnable* aRunnable) = 0;
virtual void
GattServerRegisterInternal(
const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable) = 0;
virtual void
GattServerConnectPeripheralInternal(
const BluetoothUuid& aAppUuid,
+49
View File
@@ -9,6 +9,7 @@
#include "BluetoothService.h"
#include "jsapi.h"
#include "mozilla/dom/BluetoothGattCharacteristicBinding.h"
#include "mozilla/dom/BluetoothGattServerBinding.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "nsContentUtils.h"
@@ -413,7 +414,55 @@ GattPropertiesToBits(const GattCharacteristicProperties& aProperties,
}
}
nsresult
AdvertisingDataToGattAdvertisingData(
const BluetoothAdvertisingData& aAdvData,
BluetoothGattAdvertisingData& aGattAdvData)
{
aGattAdvData.mAppearance = aAdvData.mAppearance;
aGattAdvData.mIncludeDevName = aAdvData.mIncludeDevName;
aGattAdvData.mIncludeTxPower = aAdvData.mIncludeTxPower;
for (size_t i = 0; i < aAdvData.mServiceUuids.Length(); i++) {
BluetoothUuid uuid;
if (NS_WARN_IF(NS_FAILED(StringToUuid(aAdvData.mServiceUuids[i], uuid)))) {
return NS_ERROR_ILLEGAL_VALUE;
}
aGattAdvData.mServiceUuids.AppendElement(uuid);
}
if (!aAdvData.mManufacturerData.IsNull()) {
// First two bytes are manufacturer ID in little-endian.
LittleEndian::writeUint16(aGattAdvData.mManufacturerData.Elements(),
aAdvData.mManufacturerId);
// Concatenate custom manufacturer data.
const ArrayBuffer& manufacturerData = aAdvData.mManufacturerData.Value();
manufacturerData.ComputeLengthAndData();
aGattAdvData.mManufacturerData.AppendElements(manufacturerData.Data(),
manufacturerData.Length());
}
if (!aAdvData.mServiceData.IsNull()) {
BluetoothUuid uuid;
if (NS_WARN_IF(NS_FAILED(StringToUuid(aAdvData.mServiceUuid, uuid)))) {
return NS_ERROR_ILLEGAL_VALUE;
}
// First 16 bytes are service UUID in little-endian.
for (size_t i = 0; i < sizeof(uuid.mUuid); i++) {
aGattAdvData.mServiceData[i] = uuid.mUuid[sizeof(uuid.mUuid) - i - 1];
}
// Concatenate custom service data.
const ArrayBuffer& serviceData = aAdvData.mServiceData.Value();
serviceData.ComputeLengthAndData();
aGattAdvData.mServiceData.AppendElements(serviceData.Data(),
serviceData.Length());
}
return NS_OK;
}
void
GeneratePathFromGattId(const BluetoothGattId& aId,
+14
View File
@@ -14,6 +14,7 @@ namespace mozilla {
namespace dom {
class GattPermissions;
class GattCharacteristicProperties;
class BluetoothAdvertisingData;
}
}
@@ -175,6 +176,19 @@ void
GeneratePathFromGattId(const BluetoothGattId& aId,
nsAString& aPath);
/**
* Convert BluetoothAdvertisingData object used by applications to
* BluetoothGattAdvertisingData object used by gecko backend.
*
* @param aAdvData [in] BluetoothAdvertisingData object.
* @param aGattAdData [out] Target BluetoothGattAdvertisingData.
* @return NS_OK on success, NS_ERROR_ILLEGAL_VALUE otherwise.
*/
nsresult
AdvertisingDataToGattAdvertisingData(
const BluetoothAdvertisingData& aAdvData,
BluetoothGattAdvertisingData& aGattAdvData);
//
// Register/Unregister bluetooth signal handlers
//
@@ -374,6 +374,195 @@ BluetoothGattServer::Disconnect(const nsAString& aAddress, ErrorResult& aRv)
return promise.forget();
}
class BluetoothGattServer::StartAdvertisingTask final
: public BluetoothVoidReplyRunnable
{
public:
StartAdvertisingTask(BluetoothGattServer* aServer, Promise* aPromise)
: BluetoothVoidReplyRunnable(nullptr, aPromise)
, mServer(aServer)
{
MOZ_ASSERT(aServer);
MOZ_ASSERT(aPromise);
}
virtual void
ReleaseMembers() override
{
BluetoothReplyRunnable::ReleaseMembers();
mServer = nullptr;
}
protected:
virtual void OnErrorFired() override
{
mServer->mAdvertisingAppUuid.Clear();
}
private:
RefPtr<BluetoothGattServer> mServer;
};
class BluetoothGattServer::RegisterServerAndStartAdvertisingTask final
: public BluetoothVoidReplyRunnable
{
public:
RegisterServerAndStartAdvertisingTask(
BluetoothGattServer* aServer,
const BluetoothGattAdvertisingData& aAdvData,
Promise* aPromise)
: BluetoothVoidReplyRunnable(nullptr, nullptr)
/**
* aPromise is not managed by BluetoothVoidReplyRunnable. It would be
* passed to |StartAdvertisingTask| after this one executes successfully.
*/
, mServer(aServer)
, mAdvData(aAdvData)
, mPromise(aPromise)
{
MOZ_ASSERT(mServer);
MOZ_ASSERT(mPromise);
}
void ReleaseMembers() override
{
BluetoothReplyRunnable::ReleaseMembers();
mServer = nullptr;
mPromise = nullptr;
}
private:
virtual void OnSuccessFired() override
{
BluetoothService* bs = BluetoothService::Get();
if (NS_WARN_IF(!bs)) {
mPromise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
}
if (NS_WARN_IF(mServer->mAdvertisingAppUuid.IsCleared())) {
mPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
}
bs->StartAdvertisingInternal(
mServer->mAdvertisingAppUuid, mAdvData,
new StartAdvertisingTask(mServer, mPromise));
}
virtual void OnErrorFired() override
{
mServer->mAdvertisingAppUuid.Clear();
mPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
}
RefPtr<BluetoothGattServer> mServer;
BluetoothGattAdvertisingData mAdvData;
RefPtr<Promise> mPromise;
};
already_AddRefed<Promise>
BluetoothGattServer::StartAdvertising(const BluetoothAdvertisingData& aAdvData,
ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
BT_ENSURE_TRUE_REJECT(mValid, promise, NS_ERROR_NOT_AVAILABLE);
BT_ENSURE_TRUE_REJECT(mAdvertisingAppUuid.IsCleared(),
promise,
NS_ERROR_DOM_INVALID_STATE_ERR);
nsresult rv = GenerateUuid(mAdvertisingAppUuid);
BT_ENSURE_TRUE_REJECT(NS_SUCCEEDED(rv) && !mAdvertisingAppUuid.IsCleared(),
promise,
NS_ERROR_DOM_OPERATION_ERR);
BluetoothService* bs = BluetoothService::Get();
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
BluetoothGattAdvertisingData data;
rv = AdvertisingDataToGattAdvertisingData(aAdvData, data);
BT_ENSURE_TRUE_REJECT(NS_SUCCEEDED(rv), promise, rv);
BluetoothUuid appUuid;
rv = StringToUuid(mAppUuid, appUuid);
BT_ENSURE_TRUE_REJECT(NS_SUCCEEDED(rv), promise, rv);
bs->GattServerRegisterInternal(
appUuid,
new RegisterServerAndStartAdvertisingTask(this, data, promise));
return promise.forget();
}
class BluetoothGattServer::StopAdvertisingTask final
: public BluetoothVoidReplyRunnable
{
public:
StopAdvertisingTask(BluetoothGattServer* aServer, Promise* aPromise)
: BluetoothVoidReplyRunnable(nullptr, aPromise)
, mServer(aServer)
{
MOZ_ASSERT(aPromise);
MOZ_ASSERT(aServer);
}
virtual void
ReleaseMembers() override
{
BluetoothReplyRunnable::ReleaseMembers();
mServer = nullptr;
}
protected:
virtual void OnSuccessFired() override
{
mServer->mAdvertisingAppUuid.Clear();
}
virtual void OnErrorFired() override
{
mServer->mAdvertisingAppUuid.Clear();
}
private:
RefPtr<BluetoothGattServer> mServer;
};
already_AddRefed<Promise>
BluetoothGattServer::StopAdvertising(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
BT_ENSURE_TRUE_REJECT(mValid, promise, NS_ERROR_NOT_AVAILABLE);
if (mAdvertisingAppUuid.IsCleared()) {
promise->MaybeResolve(JS::UndefinedHandleValue);
return promise.forget();
}
BluetoothService* bs = BluetoothService::Get();
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
bs->StopAdvertisingInternal(mAdvertisingAppUuid,
new StopAdvertisingTask(this, promise));
return promise.forget();
}
class BluetoothGattServer::AddIncludedServiceTask final
: public BluetoothReplyTaskQueue::SubTask
{
@@ -19,6 +19,7 @@
namespace mozilla {
namespace dom {
class Promise;
struct BluetoothAdvertisingData;
}
}
@@ -57,10 +58,16 @@ public:
const nsAString& aAddress, ErrorResult& aRv);
already_AddRefed<Promise> Disconnect(
const nsAString& aAddress, ErrorResult& aRv);
already_AddRefed<Promise> StartAdvertising(
const BluetoothAdvertisingData& aAdvData, ErrorResult& aRv);
already_AddRefed<Promise> StopAdvertising(ErrorResult& aRv);
already_AddRefed<Promise> AddService(BluetoothGattService& aService,
ErrorResult& aRv);
already_AddRefed<Promise> RemoveService(BluetoothGattService& aService,
ErrorResult& aRv);
already_AddRefed<Promise> NotifyCharacteristicChanged(
const nsAString& aAddress,
BluetoothGattCharacteristic& aCharacteristic,
@@ -97,6 +104,9 @@ public:
private:
~BluetoothGattServer();
class StartAdvertisingTask;
class RegisterServerAndStartAdvertisingTask;
class StopAdvertisingTask;
class AddIncludedServiceTask;
class AddCharacteristicTask;
class AddDescriptorTask;
@@ -106,6 +116,9 @@ private:
class AddServiceTask;
class RemoveServiceTask;
friend class StartAdvertisingTask;
friend class RegisterServerAndStartAdvertisingTask;
friend class StopAdvertisingTask;
friend class AddIncludedServiceTask;
friend class AddCharacteristicTask;
friend class AddDescriptorTask;
@@ -171,6 +184,11 @@ private:
* Map request information from the request ID.
*/
nsClassHashtable<nsUint32HashKey, RequestData> mRequestMap;
/**
* AppUuid of the GATT client interface which is used to advertise.
*/
BluetoothUuid mAdvertisingAppUuid;
};
END_BLUETOOTH_NAMESPACE
+30
View File
@@ -323,6 +323,36 @@ struct ParamTraits<mozilla::dom::bluetooth::ControlPlayStatus>
}
};
template <>
struct ParamTraits<mozilla::dom::bluetooth::BluetoothGattAdvertisingData>
{
typedef mozilla::dom::bluetooth::BluetoothGattAdvertisingData paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mAppearance);
WriteParam(aMsg, aParam.mIncludeDevName);
WriteParam(aMsg, aParam.mIncludeTxPower);
WriteParam(aMsg, aParam.mManufacturerData);
WriteParam(aMsg, aParam.mServiceData);
WriteParam(aMsg, aParam.mServiceUuids);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
if (!ReadParam(aMsg, aIter, &(aResult->mAppearance)) ||
!ReadParam(aMsg, aIter, &(aResult->mIncludeDevName)) ||
!ReadParam(aMsg, aIter, &(aResult->mIncludeTxPower)) ||
!ReadParam(aMsg, aIter, &(aResult->mManufacturerData)) ||
!ReadParam(aMsg, aIter, &(aResult->mServiceData)) ||
!ReadParam(aMsg, aIter, &(aResult->mServiceUuids))) {
return false;
}
return true;
}
};
} // namespace IPC
#endif // mozilla_dom_bluetooth_ipc_BluetoothMessageUtils_h
+43
View File
@@ -206,6 +206,10 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
return actor->DoRequest(aRequest.get_StartLeScanRequest());
case Request::TStopLeScanRequest:
return actor->DoRequest(aRequest.get_StopLeScanRequest());
case Request::TStartAdvertisingRequest:
return actor->DoRequest(aRequest.get_StartAdvertisingRequest());
case Request::TStopAdvertisingRequest:
return actor->DoRequest(aRequest.get_StopAdvertisingRequest());
case Request::TPairRequest:
return actor->DoRequest(aRequest.get_PairRequest());
case Request::TUnpairRequest:
@@ -308,6 +312,9 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
case Request::TGattClientWriteDescriptorValueRequest:
return actor->DoRequest(
aRequest.get_GattClientWriteDescriptorValueRequest());
case Request::TGattServerRegisterRequest:
return actor->DoRequest(
aRequest.get_GattServerRegisterRequest());
case Request::TGattServerConnectPeripheralRequest:
return actor->DoRequest(
aRequest.get_GattServerConnectPeripheralRequest());
@@ -496,6 +503,30 @@ BluetoothRequestParent::DoRequest(const StopLeScanRequest& aRequest)
return true;
}
bool
BluetoothRequestParent::DoRequest(const StartAdvertisingRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TStartAdvertisingRequest);
mService->StartAdvertisingInternal(aRequest.appUuid(),
aRequest.data(),
mReplyRunnable.get());
return true;
}
bool
BluetoothRequestParent::DoRequest(const StopAdvertisingRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TStopAdvertisingRequest);
mService->StopAdvertisingInternal(aRequest.appUuid(), mReplyRunnable.get());
return true;
}
bool
BluetoothRequestParent::DoRequest(const PairRequest& aRequest)
{
@@ -1119,6 +1150,18 @@ BluetoothRequestParent::DoRequest(
return true;
}
bool
BluetoothRequestParent::DoRequest(const GattServerRegisterRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TGattServerRegisterRequest);
mService->GattServerRegisterInternal(aRequest.appUuid(),
mReplyRunnable.get());
return true;
}
bool
BluetoothRequestParent::DoRequest(
const GattServerConnectPeripheralRequest& aRequest)
+9
View File
@@ -152,6 +152,12 @@ protected:
bool
DoRequest(const StopLeScanRequest& aRequest);
bool
DoRequest(const StartAdvertisingRequest& aRequest);
bool
DoRequest(const StopAdvertisingRequest& aRequest);
bool
DoRequest(const PairRequest& aRequest);
@@ -295,6 +301,9 @@ protected:
bool
DoRequest(const GattClientWriteDescriptorValueRequest& aRequest);
bool
DoRequest(const GattServerRegisterRequest& aRequest);
bool
DoRequest(const GattServerConnectPeripheralRequest& aRequest);
@@ -177,6 +177,23 @@ BluetoothServiceChildProcess::StartLeScanInternal(
SendRequest(aRunnable, StartLeScanRequest(aServiceUuids));
}
void
BluetoothServiceChildProcess::StartAdvertisingInternal(
const BluetoothUuid& aAppUuid,
const BluetoothGattAdvertisingData& aAdvData,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, StartAdvertisingRequest(aAppUuid, aAdvData));
}
void
BluetoothServiceChildProcess::StopAdvertisingInternal(
const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, StopAdvertisingRequest(aAppUuid));
}
nsresult
BluetoothServiceChildProcess::SetProperty(BluetoothObjectType aType,
const BluetoothNamedValue& aValue,
@@ -668,6 +685,14 @@ BluetoothServiceChildProcess::GattClientWriteDescriptorValueInternal(
aValue));
}
void
BluetoothServiceChildProcess::GattServerRegisterInternal(
const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable,GattServerRegisterRequest(aAppUuid));
}
void
BluetoothServiceChildProcess::GattServerConnectPeripheralInternal(
const BluetoothUuid& aAppUuid,
@@ -67,6 +67,15 @@ public:
StartLeScanInternal(const nsTArray<BluetoothUuid>& aServiceUuids,
BluetoothReplyRunnable* aRunnable) override;
virtual void
StartAdvertisingInternal(const BluetoothUuid& aAppUuid,
const BluetoothGattAdvertisingData& aAdvData,
BluetoothReplyRunnable* aRunnable) override;
virtual void
StopAdvertisingInternal(const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual nsresult
SetProperty(BluetoothObjectType aType,
const BluetoothNamedValue& aValue,
@@ -353,6 +362,11 @@ public:
const nsTArray<uint8_t>& aValue,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattServerRegisterInternal(
const BluetoothUuid& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattServerConnectPeripheralInternal(
const BluetoothUuid& aAppUuid,
+21
View File
@@ -14,6 +14,8 @@ include "mozilla/dom/bluetooth/ipc/BluetoothMessageUtils.h";
using mozilla::dom::bluetooth::BluetoothAddress
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothGattAdvertisingData
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothObjectType
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothPinCode
@@ -70,6 +72,17 @@ struct StopLeScanRequest
BluetoothUuid scanUuid;
};
struct StartAdvertisingRequest
{
BluetoothUuid appUuid;
BluetoothGattAdvertisingData data;
};
struct StopAdvertisingRequest
{
BluetoothUuid appUuid;
};
struct PairRequest
{
BluetoothAddress address;
@@ -348,6 +361,11 @@ struct GattClientWriteDescriptorValueRequest
uint8_t[] value;
};
struct GattServerRegisterRequest
{
BluetoothUuid appUuid;
};
struct GattServerConnectPeripheralRequest
{
BluetoothUuid appUuid;
@@ -444,6 +462,8 @@ union Request
StopDiscoveryRequest;
StartLeScanRequest;
StopLeScanRequest;
StartAdvertisingRequest;
StopAdvertisingRequest;
PairRequest;
UnpairRequest;
PinReplyRequest;
@@ -491,6 +511,7 @@ union Request
GattClientWriteCharacteristicValueRequest;
GattClientReadDescriptorValueRequest;
GattClientWriteDescriptorValueRequest;
GattServerRegisterRequest;
GattServerConnectPeripheralRequest;
GattServerDisconnectPeripheralRequest;
UnregisterGattServerRequest;
+76
View File
@@ -4,6 +4,68 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
dictionary BluetoothAdvertisingData
{
/**
* Uuid value of Appearance characteristic of the GAP service which can be
* mapped to an icon or string that describes the physical representation of
* the device during the device discovery procedure.
*/
unsigned short appearance = 0;
/**
* Whether to broadcast with device name or not.
*/
boolean includeDevName = false;
/**
* Whether to broadcast with TX power or not.
*/
boolean includeTxPower = false;
/**
* Company Identifier Code for manufacturer data.
*
* This ID will be combined with |manufacturerData| byte array specified
* below as the broadcasting manufacturer data. Please see Core Specification
* Supplement (CSS) v6 1.4 for more details.
*/
unsigned short manufacturerId = 0;
/**
* Byte array of custom manufacturer specific data.
*
* These bytes will be appended to |manufacturerId| specified above as the
* broadcasting manufacturer data. Please see Core Specification Supplement
* (CSS) v6 1.4 for more details.
*/
ArrayBuffer? manufacturerData = null;
/**
* 128-bit Service UUID for service data.
*
* This UUID will be combinded with |serviceData| specified below as the
* broadcasting service data. Please see Core Specification Supplement (CSS)
* v6 1.11 for more details.
*/
DOMString serviceUuid = "";
/**
* Data associated with |serviceUuid|.
*
* These bytes will be appended to |serviceUuid| specified above as the
* broadcasting manufacturer data. Please see Core Specification Supplement
* (CSS) v6 1.11 for more details.
*/
ArrayBuffer? serviceData = null;
/**
* A list of Service or Service Class UUIDs.
* Please see Core Specification Supplement (CSS) v6 1.1 for more details.
*/
sequence<DOMString> serviceUuids = [];
};
[CheckAnyPermissions="bluetooth"]
interface BluetoothGattServer : EventTarget
{
@@ -28,6 +90,20 @@ interface BluetoothGattServer : EventTarget
[NewObject]
Promise<void> disconnect(DOMString address);
/**
* Start or stop advertising data to nearby devices.
*
* Application may customize the advertising data by passing advData to
* |startAdvertising|. By performing |startAdvertising|, remote central
* devices can then discover and initiate a connection with our local device.
* A 'connectionstatechanged' event will be fired when a remote central
* device connects to the local device.
*/
[NewObject]
Promise<void> startAdvertising(optional BluetoothAdvertisingData advData);
[NewObject]
Promise<void> stopAdvertising();
/**
* Add a BLE service to the local GATT server.
*
+2
View File
@@ -19,6 +19,7 @@ dictionary FontFaceDescriptors {
DOMString unicodeRange = "U+0-10FFFF";
DOMString variant = "normal";
DOMString featureSettings = "normal";
DOMString display = "auto";
};
enum FontFaceLoadStatus { "unloaded", "loading", "loaded", "error" };
@@ -37,6 +38,7 @@ interface FontFace {
[SetterThrows] attribute DOMString unicodeRange;
[SetterThrows] attribute DOMString variant;
[SetterThrows] attribute DOMString featureSettings;
[SetterThrows, Pref="layout.css.font-display.enabled"] attribute DOMString display;
readonly attribute FontFaceLoadStatus status;
+4 -2
View File
@@ -173,6 +173,7 @@ BasicTextureImage::EndUpdate()
RefPtr<gfx::DataSourceSurface> updateData = updateSnapshot->GetDataSurface();
bool relative = FinishedSurfaceUpdate();
bool needInit = mTextureState == Created;
size_t uploadSize;
mTextureFormat =
UploadSurfaceToTexture(mGLContext,
@@ -180,7 +181,7 @@ BasicTextureImage::EndUpdate()
mUpdateRegion,
mTexture,
&uploadSize,
mTextureState == Created,
needInit,
mUpdateOffset,
relative);
FinishedSurfaceUpload();
@@ -230,13 +231,14 @@ BasicTextureImage::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion
}
size_t uploadSize;
bool needInit = mTextureState == Created;
mTextureFormat =
UploadSurfaceToTexture(mGLContext,
aSurf,
region,
mTexture,
&uploadSize,
mTextureState == Created,
needInit,
bounds.TopLeft() + IntPoint(aFrom.x, aFrom.y),
false);
if (uploadSize > 0) {
+4 -4
View File
@@ -434,12 +434,12 @@ UploadImageDataToTexture(GLContext* gl,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
size_t* aOutUploadSize,
bool aOverwrite,
bool aNeedInit,
bool aPixelBuffer,
GLenum aTextureUnit,
GLenum aTextureTarget)
{
bool textureInited = aOverwrite ? false : true;
bool textureInited = aNeedInit ? false : true;
gl->MakeCurrent();
gl->fActiveTexture(aTextureUnit);
@@ -612,7 +612,7 @@ UploadSurfaceToTexture(GLContext* gl,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
size_t* aOutUploadSize,
bool aOverwrite,
bool aNeedInit,
const gfx::IntPoint& aSrcPoint,
bool aPixelBuffer,
GLenum aTextureUnit,
@@ -624,7 +624,7 @@ UploadSurfaceToTexture(GLContext* gl,
data += DataOffset(aSrcPoint, stride, format);
return UploadImageDataToTexture(gl, data, stride, format,
aDstRegion, aTexture, aOutUploadSize,
aOverwrite, aPixelBuffer, aTextureUnit,
aNeedInit, aPixelBuffer, aTextureUnit,
aTextureTarget);
}
+2 -2
View File
@@ -61,7 +61,7 @@ UploadImageDataToTexture(GLContext* gl,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
size_t* aOutUploadSize = nullptr,
bool aOverwrite = false,
bool aNeedInit = false,
bool aPixelBuffer = false,
GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
@@ -75,7 +75,7 @@ UploadSurfaceToTexture(GLContext* gl,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
size_t* aOutUploadSize = nullptr,
bool aOverwrite = false,
bool aNeedInit = false,
const gfx::IntPoint& aSrcPoint = gfx::IntPoint(0, 0),
bool aPixelBuffer = false,
GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
+2 -1
View File
@@ -207,6 +207,7 @@ TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion&
region = aRegion;
}
bool needInit = mTextureState == Created;
size_t uploadSize = 0;
mTextureFormat =
UploadSurfaceToTexture(mGLContext,
@@ -214,7 +215,7 @@ TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion&
region,
mTexture,
&uploadSize,
mTextureState == Created,
needInit,
bounds.TopLeft() + gfx::IntPoint(aFrom.x, aFrom.y),
false);
if (uploadSize > 0) {
+31 -15
View File
@@ -111,11 +111,13 @@ gfxUserFontEntry::gfxUserFontEntry(gfxUserFontSet* aFontSet,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
: gfxFontEntry(NS_LITERAL_STRING("userfont")),
mUserFontLoadState(STATUS_NOT_LOADED),
mFontDataLoadingState(NOT_LOADING),
mUnsupportedFormat(false),
mFontDisplay(aFontDisplay),
mLoader(nullptr),
mFontSet(aFontSet)
{
@@ -146,7 +148,8 @@ gfxUserFontEntry::Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
{
return mWeight == aWeight &&
mStretch == aStretch &&
@@ -154,6 +157,7 @@ gfxUserFontEntry::Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
mFeatureSettings == aFeatureSettings &&
mLanguageOverride == aLanguageOverride &&
mSrcList == aFontFaceSrcList &&
mFontDisplay == aFontDisplay &&
((!aUnicodeRanges && !mCharacterMap) ||
(aUnicodeRanges && mCharacterMap && mCharacterMap->Equals(aUnicodeRanges)));
}
@@ -732,7 +736,8 @@ gfxUserFontEntry::FontDataDownloadComplete(const uint8_t* aFontData,
mLoader = nullptr;
// download successful, make platform font using font data
if (NS_SUCCEEDED(aDownloadStatus)) {
if (NS_SUCCEEDED(aDownloadStatus) &&
mFontDataLoadingState != LOADING_TIMED_OUT) {
bool loaded = LoadPlatformFont(aFontData, aLength);
aFontData = nullptr;
@@ -744,7 +749,9 @@ gfxUserFontEntry::FontDataDownloadComplete(const uint8_t* aFontData,
} else {
// download failed
mFontSet->LogMessage(this,
"download failed", nsIScriptError::errorFlag,
(mFontDataLoadingState != LOADING_TIMED_OUT ?
"download failed" : "download timed out"),
nsIScriptError::errorFlag,
aDownloadStatus);
}
@@ -752,8 +759,10 @@ gfxUserFontEntry::FontDataDownloadComplete(const uint8_t* aFontData,
moz_free((void*)aFontData);
}
// error occurred, load next src
LoadNextSrc();
// error occurred, load next src if load not yet timed out
if (mFontDataLoadingState != LOADING_TIMED_OUT) {
LoadNextSrc();
}
// We ignore the status returned by LoadNext();
// even if loading failed, we need to bump the font-set generation
@@ -773,6 +782,7 @@ gfxUserFontEntry::GetUserFontSets(nsTArray<gfxUserFontSet*>& aResult)
gfxUserFontSet::gfxUserFontSet()
: mFontFamilies(4),
mLocalRulesUsed(false),
mRebuildLocalRules(false),
mDownloadCount(0),
mDownloadSize(0)
{
@@ -800,7 +810,8 @@ gfxUserFontSet::FindOrCreateUserFontEntry(
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
{
RefPtr<gfxUserFontEntry> entry;
@@ -815,13 +826,14 @@ gfxUserFontSet::FindOrCreateUserFontEntry(
entry = FindExistingUserFontEntry(family, aFontFaceSrcList, aWeight,
aStretch, aStyle,
aFeatureSettings, aLanguageOverride,
aUnicodeRanges);
aUnicodeRanges, aFontDisplay);
}
if (!entry) {
entry = CreateUserFontEntry(aFontFaceSrcList, aWeight, aStretch,
aStyle, aFeatureSettings,
aLanguageOverride, aUnicodeRanges);
aLanguageOverride, aUnicodeRanges,
aFontDisplay);
entry->mFamilyName = aFamilyName;
}
@@ -836,13 +848,14 @@ gfxUserFontSet::CreateUserFontEntry(
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
{
RefPtr<gfxUserFontEntry> userFontEntry =
new gfxUserFontEntry(this, aFontFaceSrcList, aWeight,
aStretch, aStyle, aFeatureSettings,
aLanguageOverride, aUnicodeRanges);
aLanguageOverride, aUnicodeRanges, aFontDisplay);
return userFontEntry.forget();
}
@@ -855,7 +868,8 @@ gfxUserFontSet::FindExistingUserFontEntry(
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
{
MOZ_ASSERT(aWeight != 0,
"aWeight must not be 0; use NS_FONT_WEIGHT_NORMAL instead");
@@ -872,7 +886,7 @@ gfxUserFontSet::FindExistingUserFontEntry(
if (!existingUserFontEntry->Matches(aFontFaceSrcList,
aWeight, aStretch, aStyle,
aFeatureSettings, aLanguageOverride,
aUnicodeRanges)) {
aUnicodeRanges, aFontDisplay)) {
continue;
}
@@ -891,11 +905,12 @@ gfxUserFontSet::AddUserFontEntry(const nsAString& aFamilyName,
if (LOG_ENABLED()) {
LOG(("userfonts (%p) added to \"%s\" (%p) style: %s weight: %d "
"stretch: %d",
"stretch: %d display: %d",
this, NS_ConvertUTF16toUTF8(aFamilyName).get(), aUserFontEntry,
(aUserFontEntry->IsItalic() ? "italic" :
(aUserFontEntry->IsOblique() ? "oblique" : "normal")),
aUserFontEntry->Weight(), aUserFontEntry->Stretch()));
aUserFontEntry->Weight(), aUserFontEntry->Stretch(),
aUserFontEntry->GetFontDisplay()));
}
}
@@ -942,6 +957,7 @@ void
gfxUserFontSet::RebuildLocalRules()
{
if (mLocalRulesUsed) {
mRebuildLocalRules = true;
DoRebuildUserFontSet();
}
}
+17 -5
View File
@@ -214,7 +214,8 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges) = 0;
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay) = 0;
// creates a font face for the specified family, or returns an existing
// matching entry on the family if there is one
@@ -226,7 +227,8 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges);
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay);
// add in a font face for which we have the gfxUserFontEntry already
void AddUserFontEntry(const nsAString& aFamilyName,
@@ -508,7 +510,8 @@ protected:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges);
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay);
// creates a new gfxUserFontFamily in mFontFamilies, or returns an existing
// family if there is one
@@ -523,6 +526,9 @@ protected:
// true when local names have been looked up, false otherwise
bool mLocalRulesUsed;
// true when rules using local names need to be redone
bool mRebuildLocalRules;
// performance stats
uint32_t mDownloadCount;
uint64_t mDownloadSize;
@@ -551,7 +557,8 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges);
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay);
virtual ~gfxUserFontEntry();
@@ -562,7 +569,8 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges);
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay);
virtual gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle,
bool aNeedsBold);
@@ -591,6 +599,8 @@ public:
return mCharacterMap.get();
}
uint8_t GetFontDisplay() const { return mFontDisplay; }
// load the font - starts the loading of sources which continues until
// a valid font resource is found or all sources fail
void Load();
@@ -665,11 +675,13 @@ protected:
// so keep hiding fallback font
LOADING_SLOWLY, // timeout happened and we're not nearly done,
// so use the fallback font
LOADING_TIMED_OUT, // font load took too long
LOADING_FAILED // failed to load any source: use fallback
};
FontDataLoadingState mFontDataLoadingState;
bool mUnsupportedFormat;
uint8_t mFontDisplay; // timing of userfont fallback
RefPtr<gfxFontEntry> mPlatformFontEntry;
nsTArray<gfxFontFaceSrc> mSrcList;
+112
View File
@@ -0,0 +1,112 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 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 "GonkSensorsHelpers.h"
namespace mozilla {
namespace hal {
//
// Unpacking
//
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut)
{
nsresult rv = UnpackPDU(aPDU, aOut.mType);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(aPDU, aOut.mTimestamp);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(aPDU, aOut.mStatus);
if (NS_FAILED(rv)) {
return rv;
}
size_t i = 0;
switch (aOut.mType) {
case SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
case SENSORS_TYPE_GYROSCOPE_UNCALIBRATED:
/* 6 data values */
rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
if (NS_FAILED(rv)) {
return rv;
}
/* fall through */
case SENSORS_TYPE_ROTATION_VECTOR:
case SENSORS_TYPE_GAME_ROTATION_VECTOR:
case SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
/* 5 data values */
rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
if (NS_FAILED(rv)) {
return rv;
}
/* fall through */
case SENSORS_TYPE_ACCELEROMETER:
case SENSORS_TYPE_GEOMAGNETIC_FIELD:
case SENSORS_TYPE_ORIENTATION:
case SENSORS_TYPE_GYROSCOPE:
case SENSORS_TYPE_GRAVITY:
case SENSORS_TYPE_LINEAR_ACCELERATION:
/* 3 data values */
rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
if (NS_FAILED(rv)) {
return rv;
}
/* fall through */
case SENSORS_TYPE_LIGHT:
case SENSORS_TYPE_PRESSURE:
case SENSORS_TYPE_TEMPERATURE:
case SENSORS_TYPE_PROXIMITY:
case SENSORS_TYPE_RELATIVE_HUMIDITY:
case SENSORS_TYPE_AMBIENT_TEMPERATURE:
case SENSORS_TYPE_HEART_RATE:
case SENSORS_TYPE_TILT_DETECTOR:
case SENSORS_TYPE_WAKE_GESTURE:
case SENSORS_TYPE_GLANCE_GESTURE:
case SENSORS_TYPE_PICK_UP_GESTURE:
case SENSORS_TYPE_WRIST_TILT_GESTURE:
case SENSORS_TYPE_SIGNIFICANT_MOTION:
case SENSORS_TYPE_STEP_DETECTED:
/* 1 data value */
rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
if (NS_FAILED(rv)) {
return rv;
}
break;
case SENSORS_TYPE_STEP_COUNTER:
/* 1 data value */
rv = UnpackPDU(aPDU, aOut.mData.mUint[0]);
if (NS_FAILED(rv)) {
return rv;
}
break;
default:
if (MOZ_HAL_IPC_UNPACK_WARN_IF(true, SensorsEvent)) {
return NS_ERROR_ILLEGAL_VALUE;
}
}
rv = UnpackPDU(aPDU, aOut.mDeliveryMode);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
} // namespace hal
} // namespace mozilla
+226
View File
@@ -0,0 +1,226 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 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 hal_gonk_GonkSensorsHelpers_h
#define hal_gonk_GonkSensorsHelpers_h
#include <mozilla/ipc/DaemonSocketPDU.h>
#include <mozilla/ipc/DaemonSocketPDUHelpers.h>
#include "SensorsTypes.h"
namespace mozilla {
namespace hal {
using mozilla::ipc::DaemonSocketPDU;
using mozilla::ipc::DaemonSocketPDUHeader;
using mozilla::ipc::DaemonSocketPDUHelpers::Convert;
using mozilla::ipc::DaemonSocketPDUHelpers::PackPDU;
using mozilla::ipc::DaemonSocketPDUHelpers::UnpackPDU;
using namespace mozilla::ipc::DaemonSocketPDUHelpers;
//
// Conversion
//
// The functions below convert the input value to the output value's
// type and perform extension tests on the validity of the result. On
// success the output value will be returned in |aOut|. The functions
// return NS_OK on success, or an XPCOM error code otherwise.
//
// See the documentation of the HAL IPC framework for more information
// on conversion functions.
//
nsresult
Convert(int32_t aIn, SensorsStatus& aOut)
{
static const uint8_t sStatus[] = {
[0] = SENSORS_STATUS_NO_CONTACT, // '-1'
[1] = SENSORS_STATUS_UNRELIABLE, // '0'
[2] = SENSORS_STATUS_ACCURACY_LOW, // '1'
[3] = SENSORS_STATUS_ACCURACY_MEDIUM, // '2'
[4] = SENSORS_STATUS_ACCURACY_HIGH // '3'
};
static const int8_t sOffset = -1; // '-1' is the lower bound of the status
if (MOZ_HAL_IPC_CONVERT_WARN_IF(aIn < sOffset, int32_t, SensorsStatus) ||
MOZ_HAL_IPC_CONVERT_WARN_IF(
aIn >= (static_cast<ssize_t>(MOZ_ARRAY_LENGTH(sStatus)) + sOffset),
int32_t, SensorsStatus)) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = static_cast<SensorsStatus>(sStatus[aIn - sOffset]);
return NS_OK;
}
nsresult
Convert(uint8_t aIn, SensorsDeliveryMode& aOut)
{
static const uint8_t sMode[] = {
[0x00] = SENSORS_DELIVERY_MODE_BEST_EFFORT,
[0x01] = SENSORS_DELIVERY_MODE_IMMEDIATE
};
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsDeliveryMode)) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = static_cast<SensorsDeliveryMode>(sMode[aIn]);
return NS_OK;
}
nsresult
Convert(uint8_t aIn, SensorsError& aOut)
{
static const uint8_t sError[] = {
[0x00] = SENSORS_ERROR_NONE,
[0x01] = SENSORS_ERROR_FAIL,
[0x02] = SENSORS_ERROR_NOT_READY,
[0x03] = SENSORS_ERROR_NOMEM,
[0x04] = SENSORS_ERROR_BUSY,
[0x05] = SENSORS_ERROR_DONE,
[0x06] = SENSORS_ERROR_UNSUPPORTED,
[0x07] = SENSORS_ERROR_PARM_INVALID
};
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
aIn >= MOZ_ARRAY_LENGTH(sError), uint8_t, SensorsError)) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = static_cast<SensorsError>(sError[aIn]);
return NS_OK;
}
nsresult
Convert(uint8_t aIn, SensorsTriggerMode& aOut)
{
static const uint8_t sMode[] = {
[0x00] = SENSORS_TRIGGER_MODE_CONTINUOUS,
[0x01] = SENSORS_TRIGGER_MODE_ON_CHANGE,
[0x02] = SENSORS_TRIGGER_MODE_ONE_SHOT,
[0x03] = SENSORS_TRIGGER_MODE_SPECIAL
};
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsTriggerMode)) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = static_cast<SensorsTriggerMode>(sMode[aIn]);
return NS_OK;
}
nsresult
Convert(uint32_t aIn, SensorsType& aOut)
{
static const uint8_t sType[] = {
[0x00] = 0, // invalid, required by gcc
[0x01] = SENSORS_TYPE_ACCELEROMETER,
[0x02] = SENSORS_TYPE_GEOMAGNETIC_FIELD,
[0x03] = SENSORS_TYPE_ORIENTATION,
[0x04] = SENSORS_TYPE_GYROSCOPE,
[0x05] = SENSORS_TYPE_LIGHT,
[0x06] = SENSORS_TYPE_PRESSURE,
[0x07] = SENSORS_TYPE_TEMPERATURE,
[0x08] = SENSORS_TYPE_PROXIMITY,
[0x09] = SENSORS_TYPE_GRAVITY,
[0x0a] = SENSORS_TYPE_LINEAR_ACCELERATION,
[0x0b] = SENSORS_TYPE_ROTATION_VECTOR,
[0x0c] = SENSORS_TYPE_RELATIVE_HUMIDITY,
[0x0d] = SENSORS_TYPE_AMBIENT_TEMPERATURE,
[0x0e] = SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
[0x0f] = SENSORS_TYPE_GAME_ROTATION_VECTOR,
[0x10] = SENSORS_TYPE_GYROSCOPE_UNCALIBRATED,
[0x11] = SENSORS_TYPE_SIGNIFICANT_MOTION,
[0x12] = SENSORS_TYPE_STEP_DETECTED,
[0x13] = SENSORS_TYPE_STEP_COUNTER,
[0x14] = SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR,
[0x15] = SENSORS_TYPE_HEART_RATE,
[0x16] = SENSORS_TYPE_TILT_DETECTOR,
[0x17] = SENSORS_TYPE_WAKE_GESTURE,
[0x18] = SENSORS_TYPE_GLANCE_GESTURE,
[0x19] = SENSORS_TYPE_PICK_UP_GESTURE,
[0x1a] = SENSORS_TYPE_WRIST_TILT_GESTURE
};
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
!aIn, uint32_t, SensorsType) ||
MOZ_HAL_IPC_CONVERT_WARN_IF(
aIn >= MOZ_ARRAY_LENGTH(sType), uint32_t, SensorsType)) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = static_cast<SensorsType>(sType[aIn]);
return NS_OK;
}
nsresult
Convert(nsresult aIn, SensorsError& aOut)
{
if (NS_SUCCEEDED(aIn)) {
aOut = SENSORS_ERROR_NONE;
} else if (aIn == NS_ERROR_OUT_OF_MEMORY) {
aOut = SENSORS_ERROR_NOMEM;
} else if (aIn == NS_ERROR_ILLEGAL_VALUE) {
aOut = SENSORS_ERROR_PARM_INVALID;
} else {
aOut = SENSORS_ERROR_FAIL;
}
return NS_OK;
}
//
// Packing
//
// Pack functions store a value in PDU. See the documentation of the
// HAL IPC framework for more information.
//
// There are currently no sensor-specific pack functions necessary. If
// you add one, put it below.
//
//
// Unpacking
//
// Unpack function retrieve a value from a PDU. The functions return
// NS_OK on success, or an XPCOM error code otherwise. On sucess, the
// returned value is stored in the second argument |aOut|.
//
// See the documentation of the HAL IPC framework for more information
// on unpack functions.
//
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, SensorsDeliveryMode& aOut)
{
return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsDeliveryMode>(aOut));
}
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, SensorsError& aOut)
{
return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsError>(aOut));
}
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut);
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, SensorsStatus& aOut)
{
return UnpackPDU(aPDU, UnpackConversion<int32_t, SensorsStatus>(aOut));
}
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, SensorsTriggerMode& aOut)
{
return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsTriggerMode>(aOut));
}
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, SensorsType& aOut)
{
return UnpackPDU(aPDU, UnpackConversion<uint32_t, SensorsType>(aOut));
}
} // namespace hal
} // namespace mozilla
#endif // hal_gonk_GonkSensorsHelpers_h
+140
View File
@@ -0,0 +1,140 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 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 hal_gonk_SensorsTypes_h
#define hal_gonk_SensorsTypes_h
namespace mozilla {
namespace hal {
enum SensorsDeliveryMode {
SENSORS_DELIVERY_MODE_BEST_EFFORT,
SENSORS_DELIVERY_MODE_IMMEDIATE
};
enum SensorsError {
SENSORS_ERROR_NONE,
SENSORS_ERROR_FAIL,
SENSORS_ERROR_NOT_READY,
SENSORS_ERROR_NOMEM,
SENSORS_ERROR_BUSY,
SENSORS_ERROR_DONE,
SENSORS_ERROR_UNSUPPORTED,
SENSORS_ERROR_PARM_INVALID
};
enum SensorsStatus {
SENSORS_STATUS_NO_CONTACT,
SENSORS_STATUS_UNRELIABLE,
SENSORS_STATUS_ACCURACY_LOW,
SENSORS_STATUS_ACCURACY_MEDIUM,
SENSORS_STATUS_ACCURACY_HIGH
};
enum SensorsTriggerMode {
SENSORS_TRIGGER_MODE_CONTINUOUS,
SENSORS_TRIGGER_MODE_ON_CHANGE,
SENSORS_TRIGGER_MODE_ONE_SHOT,
SENSORS_TRIGGER_MODE_SPECIAL
};
enum SensorsType {
SENSORS_TYPE_ACCELEROMETER,
SENSORS_TYPE_GEOMAGNETIC_FIELD,
SENSORS_TYPE_ORIENTATION,
SENSORS_TYPE_GYROSCOPE,
SENSORS_TYPE_LIGHT,
SENSORS_TYPE_PRESSURE,
SENSORS_TYPE_TEMPERATURE,
SENSORS_TYPE_PROXIMITY,
SENSORS_TYPE_GRAVITY,
SENSORS_TYPE_LINEAR_ACCELERATION,
SENSORS_TYPE_ROTATION_VECTOR,
SENSORS_TYPE_RELATIVE_HUMIDITY,
SENSORS_TYPE_AMBIENT_TEMPERATURE,
SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
SENSORS_TYPE_GAME_ROTATION_VECTOR,
SENSORS_TYPE_GYROSCOPE_UNCALIBRATED,
SENSORS_TYPE_SIGNIFICANT_MOTION,
SENSORS_TYPE_STEP_DETECTED,
SENSORS_TYPE_STEP_COUNTER,
SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR,
SENSORS_TYPE_HEART_RATE,
SENSORS_TYPE_TILT_DETECTOR,
SENSORS_TYPE_WAKE_GESTURE,
SENSORS_TYPE_GLANCE_GESTURE,
SENSORS_TYPE_PICK_UP_GESTURE,
SENSORS_TYPE_WRIST_TILT_GESTURE,
SENSORS_NUM_TYPES
};
struct SensorsEvent {
SensorsType mType;
SensorsStatus mStatus;
SensorsDeliveryMode mDeliveryMode;
int64_t mTimestamp;
union {
float mFloat[6];
uint64_t mUint[1];
} mData;
};
/**
* |SensorsSensor| represents a device sensor; either single or composite.
*/
struct SensorsSensor {
SensorsSensor(int32_t aId, SensorsType aType,
float aRange, float aResolution,
float aPower, int32_t aMinPeriod,
int32_t aMaxPeriod,
SensorsTriggerMode aTriggerMode,
SensorsDeliveryMode aDeliveryMode)
: mId(aId)
, mType(aType)
, mRange(aRange)
, mResolution(aResolution)
, mPower(aPower)
, mMinPeriod(aMinPeriod)
, mMaxPeriod(aMaxPeriod)
, mTriggerMode(aTriggerMode)
, mDeliveryMode(aDeliveryMode)
{ }
int32_t mId;
SensorsType mType;
float mRange;
float mResolution;
float mPower;
int32_t mMinPeriod;
int32_t mMaxPeriod;
SensorsTriggerMode mTriggerMode;
SensorsDeliveryMode mDeliveryMode;
};
/**
* |SensorClass| represents the status of a specific sensor type.
*/
struct SensorsSensorClass {
SensorsSensorClass()
: mActivated(0)
, mMinValue(0)
, mMaxValue(0)
{ }
void UpdateFromSensor(const SensorsSensor& aSensor)
{
mMaxValue = std::max(aSensor.mRange, mMaxValue);
}
uint32_t mActivated;
float mMinValue;
float mMaxValue;
};
} // namespace hal
} // namespace mozilla
#endif // hal_gonk_SensorsTypes_h
+1
View File
@@ -48,6 +48,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
'gonk/GonkDiskSpaceWatcher.cpp',
'gonk/GonkFMRadio.cpp',
'gonk/GonkSensor.cpp',
'gonk/GonkSensorsHelpers.cpp',
'gonk/GonkSwitch.cpp',
'gonk/UeventPoller.cpp',
'linux/LinuxMemory.cpp',
+11 -13
View File
@@ -315,20 +315,18 @@ FatalError(const char* aProtocolName, const char* aMsg,
formattedMessage.AppendLiteral("]: \"");
formattedMessage.AppendASCII(aMsg);
if (aIsParent) {
formattedMessage.AppendLiteral("\". Killing child side as a result.");
#ifdef MOZ_CRASHREPORTER
// We're going to crash the parent process because at this time
// there's no other really nice way of getting a minidump out of
// this process if we're off the main thread.
formattedMessage.AppendLiteral("\". Intentionally crashing.");
NS_ERROR(formattedMessage.get());
if (aOtherPid != kInvalidProcessId && aOtherPid != base::GetCurrentProcId()) {
ScopedProcessHandle otherProcessHandle;
if (base::OpenProcessHandle(aOtherPid, &otherProcessHandle.rwget())) {
if (!base::KillProcess(otherProcessHandle,
base::PROCESS_END_KILLED_BY_USER, false)) {
NS_ERROR("May have failed to kill child!");
}
} else {
NS_ERROR("Failed to open child process when attempting kill.");
}
}
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IPCFatalErrorProtocol"),
nsDependentCString(aProtocolName));
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IPCFatalErrorMsg"),
nsDependentCString(aMsg));
#endif
MOZ_CRASH("IPC FatalError in the parent process!");
} else {
formattedMessage.AppendLiteral("\". abort()ing as a result.");
NS_RUNTIMEABORT(formattedMessage.get());
+88
View File
@@ -713,6 +713,94 @@ private:
Tin6 mArg6;
};
template <typename ObjectWrapper, typename Res,
typename Tin1, typename Tin2, typename Tin3,
typename Tin4, typename Tin5, typename Tin6,
typename Tin7, typename Tin8,
typename Arg1=Tin1, typename Arg2=Tin2, typename Arg3=Tin3,
typename Arg4=Tin4, typename Arg5=Tin5, typename Arg6=Tin6,
typename Arg7=Tin7, typename Arg8=Tin8>
class DaemonNotificationRunnable8 final : public nsRunnable
{
public:
typedef typename ObjectWrapper::ObjectType ObjectType;
typedef DaemonNotificationRunnable8<ObjectWrapper, Res,
Tin1, Tin2, Tin3, Tin4, Tin5, Tin6, Tin7, Tin8,
Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8> SelfType;
template <typename InitOp>
static already_AddRefed<SelfType> Create(
Res (ObjectType::*aMethod)(
Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8),
const InitOp& aInitOp)
{
RefPtr<SelfType> runnable(new SelfType(aMethod));
if (NS_FAILED(runnable->Init(aInitOp))) {
return nullptr;
}
return runnable.forget();
}
template <typename InitOp>
static void
Dispatch(
Res (ObjectType::*aMethod)(
Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8),
const InitOp& aInitOp)
{
RefPtr<SelfType> runnable = Create(aMethod, aInitOp);
if (!runnable) {
return;
}
Unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable)));
}
NS_IMETHODIMP Run() override
{
MOZ_ASSERT(NS_IsMainThread());
ObjectType* obj = ObjectWrapper::GetInstance();
if (!obj) {
NS_WARNING("Notification handler not initialized");
} else {
((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4,
mArg5, mArg6, mArg7, mArg8);
}
return NS_OK;
}
private:
DaemonNotificationRunnable8(
Res (ObjectType::*aMethod)(
Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8))
: mMethod(aMethod)
{
MOZ_ASSERT(mMethod);
}
template<typename InitOp>
nsresult Init(const InitOp& aInitOp)
{
nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4,
mArg5, mArg6, mArg7, mArg8);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
Res (ObjectType::*mMethod)(
Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8);
Tin1 mArg1;
Tin2 mArg2;
Tin3 mArg3;
Tin4 mArg4;
Tin5 mArg5;
Tin6 mArg6;
Tin7 mArg7;
Tin8 mArg8;
};
template <typename ObjectWrapper, typename Res,
typename Tin1, typename Tin2, typename Tin3,
typename Tin4, typename Tin5, typename Tin6,
+1 -1
View File
@@ -103,7 +103,7 @@ DaemonSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer)
if (!mPDU) {
/* There's only one PDU for receiving. We reuse it every time. */
mPDU = new DaemonSocketPDU(DaemonSocketPDU::MAX_PAYLOAD_LENGTH);
mPDU = new DaemonSocketPDU(DaemonSocketPDU::PDU_MAX_PAYLOAD_LENGTH);
}
*aBuffer = mPDU.get();
+13 -13
View File
@@ -35,17 +35,17 @@ DaemonSocketPDU::DaemonSocketPDU(uint8_t aService, uint8_t aOpcode,
MOZ_COUNT_CTOR_INHERITED(DaemonSocketPDU, UnixSocketIOBuffer);
// Allocate memory
size_t availableSpace = HEADER_SIZE + aPayloadSize;
size_t availableSpace = PDU_HEADER_SIZE + aPayloadSize;
ResetBuffer(new uint8_t[availableSpace], 0, 0, availableSpace);
// Reserve PDU header
uint8_t* data = Append(HEADER_SIZE);
uint8_t* data = Append(PDU_HEADER_SIZE);
MOZ_ASSERT(data);
// Setup PDU header
data[OFF_SERVICE] = aService;
data[OFF_OPCODE] = aOpcode;
memcpy(data + OFF_LENGTH, &aPayloadSize, sizeof(aPayloadSize));
data[PDU_OFF_SERVICE] = aService;
data[PDU_OFF_OPCODE] = aOpcode;
memcpy(data + PDU_OFF_LENGTH, &aPayloadSize, sizeof(aPayloadSize));
}
DaemonSocketPDU::DaemonSocketPDU(size_t aPayloadSize)
@@ -53,7 +53,7 @@ DaemonSocketPDU::DaemonSocketPDU(size_t aPayloadSize)
{
MOZ_COUNT_CTOR_INHERITED(DaemonSocketPDU, UnixSocketIOBuffer);
size_t availableSpace = HEADER_SIZE + aPayloadSize;
size_t availableSpace = PDU_HEADER_SIZE + aPayloadSize;
ResetBuffer(new uint8_t[availableSpace], 0, 0, availableSpace);
}
@@ -69,9 +69,9 @@ void
DaemonSocketPDU::GetHeader(uint8_t& aService, uint8_t& aOpcode,
uint16_t& aPayloadSize)
{
memcpy(&aService, GetData(OFF_SERVICE), sizeof(aService));
memcpy(&aOpcode, GetData(OFF_OPCODE), sizeof(aOpcode));
memcpy(&aPayloadSize, GetData(OFF_LENGTH), sizeof(aPayloadSize));
memcpy(&aService, GetData(PDU_OFF_SERVICE), sizeof(aService));
memcpy(&aOpcode, GetData(PDU_OFF_OPCODE), sizeof(aOpcode));
memcpy(&aPayloadSize, GetData(PDU_OFF_LENGTH), sizeof(aPayloadSize));
}
ssize_t
@@ -164,12 +164,12 @@ nsresult
DaemonSocketPDU::UpdateHeader()
{
size_t len = GetPayloadSize();
if (len >= MAX_PAYLOAD_LENGTH) {
if (len >= PDU_MAX_PAYLOAD_LENGTH) {
return NS_ERROR_ILLEGAL_VALUE;
}
uint16_t len16 = static_cast<uint16_t>(len);
memcpy(GetData(OFF_LENGTH), &len16, sizeof(len16));
memcpy(GetData(PDU_OFF_LENGTH), &len16, sizeof(len16));
return NS_OK;
}
@@ -177,9 +177,9 @@ DaemonSocketPDU::UpdateHeader()
size_t
DaemonSocketPDU::GetPayloadSize() const
{
MOZ_ASSERT(GetSize() >= HEADER_SIZE);
MOZ_ASSERT(GetSize() >= PDU_HEADER_SIZE);
return GetSize() - HEADER_SIZE;
return GetSize() - PDU_HEADER_SIZE;
}
void
+6 -6
View File
@@ -39,12 +39,12 @@ class DaemonSocketPDU final : public UnixSocketIOBuffer
{
public:
enum {
OFF_SERVICE = 0,
OFF_OPCODE = 1,
OFF_LENGTH = 2,
OFF_PAYLOAD = 4,
HEADER_SIZE = OFF_PAYLOAD,
MAX_PAYLOAD_LENGTH = 1 << 16
PDU_OFF_SERVICE = 0,
PDU_OFF_OPCODE = 1,
PDU_OFF_LENGTH = 2,
PDU_OFF_PAYLOAD = 4,
PDU_HEADER_SIZE = PDU_OFF_PAYLOAD,
PDU_MAX_PAYLOAD_LENGTH = 1 << 16
};
DaemonSocketPDU(uint8_t aService, uint8_t aOpcode, uint16_t aPayloadSize);
+166
View File
@@ -349,6 +349,42 @@ PackPDU(const PackReversed<PackArray<U>>& aIn, DaemonSocketPDU& aPDU)
return NS_OK;
}
/* |PackArray<PackReversed<U>>| is a helper for packing data of each element in
* the reversed order. Pass an instance of this structure as the first argument
* to |PackPDU| to pack data of each array element in the reversed order.
*
* Unlike |PackReversed<PackArray<U>>| which packed array elements in the
* reversed order, here we use |PackReversed<U>| to pack data of each element
* of |PackArray| in the reversed order.
*/
template<typename U>
struct PackArray<PackReversed<U>>
{
PackArray(const U* aData, size_t aLength)
: mData(aData)
, mLength(aLength)
{ }
const U* mData;
size_t mLength;
};
/* This implementation of |PackPDU| packs data of each element in |PackArray|
* in the reversed order. (ex. reversed GATT UUID, see bug 1171866)
*/
template<typename U>
inline nsresult
PackPDU(const PackArray<PackReversed<U>>& aIn, DaemonSocketPDU& aPDU)
{
for (size_t i = 0; i < aIn.mLength; ++i) {
nsresult rv = PackPDU(PackReversed<U>(aIn.mData[i]), aPDU);
if (NS_FAILED(rv)) {
return rv;
}
}
return NS_OK;
}
template <typename T1, typename T2>
inline nsresult
PackPDU(const T1& aIn1, const T2& aIn2, DaemonSocketPDU& aPDU)
@@ -1106,6 +1142,136 @@ public:
WarnAboutTrailingData();
return NS_OK;
}
template<typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7>
nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4,
T5& aArg5, T6& aArg6, T7& aArg7) const
{
DaemonSocketPDU& pdu = GetPDU();
nsresult rv = UnpackPDU(pdu, aArg1);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg2);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg3);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg4);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg5);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg6);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg7);
if (NS_FAILED(rv)) {
return rv;
}
WarnAboutTrailingData();
return NS_OK;
}
template<typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8>
nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4,
T5& aArg5, T6& aArg6, T7& aArg7, T8& aArg8) const
{
DaemonSocketPDU& pdu = GetPDU();
nsresult rv = UnpackPDU(pdu, aArg1);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg2);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg3);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg4);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg5);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg6);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg7);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg8);
if (NS_FAILED(rv)) {
return rv;
}
WarnAboutTrailingData();
return NS_OK;
}
template<typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9>
nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4,
T5& aArg5, T6& aArg6, T7& aArg7, T8& aArg8,
T9& aArg9) const
{
DaemonSocketPDU& pdu = GetPDU();
nsresult rv = UnpackPDU(pdu, aArg1);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg2);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg3);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg4);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg5);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg6);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg7);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg8);
if (NS_FAILED(rv)) {
return rv;
}
rv = UnpackPDU(pdu, aArg9);
if (NS_FAILED(rv)) {
return rv;
}
WarnAboutTrailingData();
return NS_OK;
}
};
} // namespace DaemonSocketPDUHelpers
+6
View File
@@ -9,6 +9,12 @@ function jitTogglesMatch(opts) {
if (k.indexOf(".enable") > 0 && opts[k] != currentOpts[k])
return false;
}
// ARM64 does not yet have an Ion code generator, so return false if
// ion.enable is requested.
if (getBuildConfiguration()['arm64-simulator'] && opts['ion.enable'])
return false;
return true;
}
-1
View File
@@ -219,7 +219,6 @@ class CodeGeneratorShared : public LElementVisitor
inline Operand ToOperand(const LDefinition* def);
protected:
#ifdef CHECK_OSIPOINT_REGISTERS
void resetOsiPointRegs(LSafepoint* safepoint);
bool shouldVerifyOsiPointRegs(LSafepoint* safepoint);
@@ -75,3 +75,6 @@ include values3/reftest.list
# Variables Level 1
include variables/reftest.list
# CSS will-change Level 1
include will-change/reftest.list
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change reference</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px; background: green }
</style>
<body>
<div></div>
</body>
@@ -0,0 +1,12 @@
== will-change-stacking-context-clip-path-1.html green-square-100-by-100-ref.html
== will-change-stacking-context-filter-1.html green-square-100-by-100-ref.html
== will-change-stacking-context-height-1.html green-square-100-by-100-ref.html
== will-change-stacking-context-isolation-1.html green-square-100-by-100-ref.html
== will-change-stacking-context-mask-1.html green-square-100-by-100-ref.html
== will-change-stacking-context-mix-blend-mode-1.html green-square-100-by-100-ref.html
== will-change-stacking-context-opacity-1.html green-square-100-by-100-ref.html
== will-change-stacking-context-perspective-1.html green-square-100-by-100-ref.html
== will-change-stacking-context-position-1.html green-square-100-by-100-ref.html
== will-change-stacking-context-transform-1.html green-square-100-by-100-ref.html
== will-change-stacking-context-transform-style-1.html green-square-100-by-100-ref.html
== will-change-stacking-context-z-index-1.html green-square-100-by-100-ref.html
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: clip-path' creates a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="help" href="http://www.w3.org/TR/css-masking/#the-clip-path">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: clip-path; background: red }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: green }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: filter' creates a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="help" href="http://www.w3.org/TR/filter-effects/#FilterProperty">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: filter; background: red }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: green }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: height' does not create a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: height; background: green }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: red }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: isolation' creates a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="help" href="http://www.w3.org/TR/compositing-1/#isolation">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: isolation; background: red }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: green }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: mask' creates a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="help" href="http://www.w3.org/TR/css-masking/#the-mask-image">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: mask; background: red }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: green }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: mix-blend-mode' creates a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="help" href="http://www.w3.org/TR/compositing-1/#mix-blend-mode">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: mix-blend-mode; background: red }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: green }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: opacity' creates a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="help" href="https://drafts.csswg.org/css-color-3/#transparency">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: opacity; background: red }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: green }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: perspective' creates a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="help" href="http://www.w3.org/TR/css3-transforms/#perspective-property">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: perspective; background: red }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: green }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: position' creates a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="help" href="http://www.w3.org/TR/css3-positioning/#sticky-pos">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: position; background: red }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: green }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: transform' creates a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="help" href="http://www.w3.org/TR/css3-transforms/#transform-property">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: transform; background: red }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: green }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: transform-style' creates a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="help" href="http://www.w3.org/TR/css3-transforms/#transform-style-property">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: transform-style; background: red }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: green }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS will-change: 'will-change: z-index' creates a stacking context</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
<link rel="help" href="http://www.w3.org/TR/css3-positioning/#layered-presentation">
<link rel="match" href="green-square-100-by-100-ref.html">
<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element.">
<style>
html, body { margin: 0; padding: 0; }
div { width: 100px; height: 100px }
#wc { will-change: z-index; background: red }
#child { position: absolute; top: 0; left: 0; z-index: -1; background: green }
</style>
<body>
<div id="wc">
<div id="child">
</div>
</div>
</body>
+25 -1
View File
@@ -355,6 +355,20 @@ FontFace::SetFeatureSettings(const nsAString& aValue, ErrorResult& aRv)
SetDescriptor(eCSSFontDesc_FontFeatureSettings, aValue, aRv);
}
void
FontFace::GetDisplay(nsString& aResult)
{
mFontFaceSet->FlushUserFontSet();
GetDesc(eCSSFontDesc_Display, eCSSProperty_UNKNOWN, aResult);
}
void
FontFace::SetDisplay(const nsAString& aValue, ErrorResult& aRv)
{
mFontFaceSet->FlushUserFontSet();
SetDescriptor(eCSSFontDesc_Display, aValue, aRv);
}
FontFaceLoadStatus
FontFace::Status()
{
@@ -548,7 +562,10 @@ FontFace::SetDescriptors(const nsAString& aFamily,
mDescriptors->mUnicodeRange) ||
!ParseDescriptor(eCSSFontDesc_FontFeatureSettings,
aDescriptors.mFeatureSettings,
mDescriptors->mFontFeatureSettings)) {
mDescriptors->mFontFeatureSettings) ||
!ParseDescriptor(eCSSFontDesc_Display,
aDescriptors.mDisplay,
mDescriptors->mDisplay)) {
// XXX Handle font-variant once we support it (bug 1055385).
// If any of the descriptors failed to parse, none of them should be set
@@ -584,6 +601,7 @@ FontFace::GetDesc(nsCSSFontDesc aDescID,
nsString& aResult) const
{
MOZ_ASSERT(aDescID == eCSSFontDesc_UnicodeRange ||
aDescID == eCSSFontDesc_Display ||
aPropID != eCSSProperty_UNKNOWN,
"only pass eCSSProperty_UNKNOWN for eCSSFontDesc_UnicodeRange");
@@ -596,6 +614,8 @@ FontFace::GetDesc(nsCSSFontDesc aDescID,
if (value.GetUnit() == eCSSUnit_Null) {
if (aDescID == eCSSFontDesc_UnicodeRange) {
aResult.AssignLiteral("U+0-10FFFF");
} else if (aDescID == eCSSFontDesc_Display) {
aResult.AssignLiteral("auto");
} else if (aDescID != eCSSFontDesc_Family &&
aDescID != eCSSFontDesc_Src) {
aResult.AssignLiteral("normal");
@@ -607,6 +627,10 @@ FontFace::GetDesc(nsCSSFontDesc aDescID,
// Since there's no unicode-range property, we can't use
// nsCSSValue::AppendToString to serialize this descriptor.
nsStyleUtil::AppendUnicodeRange(value, aResult);
} else if (aDescID == eCSSFontDesc_Display) {
AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(value.GetIntValue(),
nsCSSProps::kFontDisplayKTable),
aResult);
} else {
value.AppendToString(aPropID, aResult, nsCSSValue::eNormalized);
}
+5 -2
View File
@@ -47,10 +47,11 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
: gfxUserFontEntry(aFontSet, aFontFaceSrcList, aWeight, aStretch,
aStyle, aFeatureSettings, aLanguageOverride,
aUnicodeRanges) {}
aUnicodeRanges, aFontDisplay) {}
virtual void SetLoadState(UserFontLoadState aLoadState) override;
virtual void GetUserFontSets(nsTArray<gfxUserFontSet*>& aResult) override;
@@ -150,6 +151,8 @@ public:
void SetVariant(const nsAString& aValue, mozilla::ErrorResult& aRv);
void GetFeatureSettings(nsString& aResult);
void SetFeatureSettings(const nsAString& aValue, mozilla::ErrorResult& aRv);
void GetDisplay(nsString& aResult);
void SetDisplay(const nsAString& aValue, mozilla::ErrorResult& aRv);
mozilla::dom::FontFaceLoadStatus Status();
mozilla::dom::Promise* Load(mozilla::ErrorResult& aRv);
+25 -8
View File
@@ -789,14 +789,17 @@ FontFaceSet::UpdateRules(const nsTArray<nsFontFaceRuleContainer>& aRules)
CheckLoadingFinished();
}
// local rules have been rebuilt, so clear the flag
mUserFontSet->mLocalRulesUsed = false;
// if local rules needed to be rebuilt, they have been rebuilt at this point
if (mUserFontSet->mRebuildLocalRules) {
mUserFontSet->mLocalRulesUsed = false;
mUserFontSet->mRebuildLocalRules = false;
}
if (LOG_ENABLED() && !mRuleFaces.IsEmpty()) {
LOG(("userfonts (%p) userfont rules update (%s) rule count: %" PRIuSIZE,
LOG(("userfonts (%p) userfont rules update (%s) rule count: %d",
mUserFontSet.get(),
(modified ? "modified" : "not modified"),
mRuleFaces.Length()));
(int)(mRuleFaces.Length())));
}
return modified;
@@ -875,7 +878,8 @@ FontFaceSet::InsertRuleFontFace(FontFace* aFontFace, SheetType aSheetType,
// if local rules were used, don't use the old font entry
// for rules containing src local usage
if (mUserFontSet->mLocalRulesUsed) {
if (mUserFontSet->mLocalRulesUsed &&
mUserFontSet->mRebuildLocalRules) {
nsCSSValue val;
aFontFace->GetDesc(eCSSFontDesc_Src, val);
nsCSSUnit unit = val.GetUnit();
@@ -978,6 +982,7 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(const nsAString& aFamilyName,
int32_t stretch = NS_STYLE_FONT_STRETCH_NORMAL;
uint8_t italicStyle = NS_STYLE_FONT_STYLE_NORMAL;
uint32_t languageOverride = NO_FONT_LANGUAGE_OVERRIDE;
uint8_t fontDisplay = NS_FONT_DISPLAY_AUTO;
// set up weight
aFontFace->GetDesc(eCSSFontDesc_Weight, val);
@@ -1018,6 +1023,16 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(const nsAString& aFamilyName,
"@font-face style has unexpected unit");
}
// set up font display
aFontFace->GetDesc(eCSSFontDesc_Display, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Enumerated) {
fontDisplay = val.GetIntValue();
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face style has unexpected unit");
}
// set up font features
nsTArray<gfxFontFeature> featureSettings;
aFontFace->GetDesc(eCSSFontDesc_FontFeatureSettings, val);
@@ -1163,7 +1178,7 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(const nsAString& aFamilyName,
stretch, italicStyle,
featureSettings,
languageOverride,
unicodeRanges);
unicodeRanges, fontDisplay);
return entry.forget();
}
@@ -1807,11 +1822,13 @@ FontFaceSet::UserFontSet::CreateUserFontEntry(
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
{
RefPtr<gfxUserFontEntry> entry =
new FontFace::Entry(this, aFontFaceSrcList, aWeight, aStretch, aStyle,
aFeatureSettings, aLanguageOverride, aUnicodeRanges);
aFeatureSettings, aLanguageOverride, aUnicodeRanges,
aFontDisplay);
return entry.forget();
}
+2 -1
View File
@@ -89,7 +89,8 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges) override;
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay) override;
private:
RefPtr<FontFaceSet> mFontFaceSet;
+4 -20
View File
@@ -220,6 +220,10 @@ CSS_PROP_ALIAS(-webkit-animation-timing-function,
WebkitAnimationTimingFunction,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-filter,
filter,
WebkitFilter,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-text-size-adjust,
text_size_adjust,
WebkitTextSizeAdjust,
@@ -313,26 +317,6 @@ CSS_PROP_ALIAS(-webkit-border-image,
border_image,
WebkitBorderImage,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-border-image-outset,
border_image_outset,
WebkitBorderImageOutset,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-border-image-repeat,
border_image_repeat,
WebkitBorderImageRepeat,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-border-image-slice,
border_image_slice,
WebkitBorderImageSlice,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-border-image-source,
border_image_source,
WebkitBorderImageSource,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-border-image-width,
border_image_width,
WebkitBorderImageWidth,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-box-shadow,
box_shadow,
+17 -17
View File
@@ -1589,8 +1589,8 @@ CSS_PROP_POSITION(
AlignContent,
CSS_PROPERTY_PARSE_FUNCTION,
"",
0,
nullptr,
VARIANT_HK,
kAutoCompletionAlignJustifyContent,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_POSITION(
@@ -1599,8 +1599,8 @@ CSS_PROP_POSITION(
AlignItems,
CSS_PROPERTY_PARSE_FUNCTION,
"",
0,
nullptr,
VARIANT_HK,
kAutoCompletionAlignItems,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_POSITION(
@@ -1609,8 +1609,8 @@ CSS_PROP_POSITION(
AlignSelf,
CSS_PROPERTY_PARSE_FUNCTION,
"",
0,
nullptr,
VARIANT_HK,
kAutoCompletionAlignJustifySelf,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SHORTHAND(
@@ -1720,8 +1720,8 @@ CSS_PROP_POSITION(
JustifyContent,
CSS_PROPERTY_PARSE_FUNCTION,
"",
0,
nullptr,
VARIANT_HK,
kAutoCompletionAlignJustifyContent,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_POSITION(
@@ -1730,8 +1730,9 @@ CSS_PROP_POSITION(
JustifyItems,
CSS_PROPERTY_PARSE_FUNCTION,
"",
0,
nullptr,
VARIANT_HK,
// for auto-completion we use same values as justify-self:
kAutoCompletionAlignJustifySelf,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_POSITION(
@@ -1740,8 +1741,8 @@ CSS_PROP_POSITION(
JustifySelf,
CSS_PROPERTY_PARSE_FUNCTION,
"",
0,
nullptr,
VARIANT_HK,
kAutoCompletionAlignJustifySelf,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_DISPLAY(
@@ -2724,7 +2725,8 @@ CSS_PROP_DISPLAY(
Opacity,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR,
CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR |
CSS_PROPERTY_CREATES_STACKING_CONTEXT,
"",
VARIANT_HN,
nullptr,
@@ -3959,8 +3961,7 @@ CSS_PROP_SVG(
fill,
fill,
Fill,
CSS_PROPERTY_PARSE_FUNCTION |
CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED,
CSS_PROPERTY_PARSE_FUNCTION,
"",
0,
kContextPatternKTable,
@@ -4217,8 +4218,7 @@ CSS_PROP_SVG(
stroke,
stroke,
Stroke,
CSS_PROPERTY_PARSE_FUNCTION |
CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED,
CSS_PROPERTY_PARSE_FUNCTION,
"",
0,
kContextPatternKTable,
+57
View File
@@ -1383,6 +1383,63 @@ const KTableEntry nsCSSProps::kAlignContentPosition[] = {
{ eCSSKeyword_UNKNOWN, -1 }
};
// <NOTE> these are only used for auto-completion, not parsing:
const KTableEntry nsCSSProps::kAutoCompletionAlignJustifySelf[] = {
{ eCSSKeyword_auto, NS_STYLE_ALIGN_AUTO },
{ eCSSKeyword_normal, NS_STYLE_ALIGN_NORMAL },
{ eCSSKeyword_stretch, NS_STYLE_ALIGN_STRETCH },
{ eCSSKeyword_baseline, NS_STYLE_ALIGN_BASELINE },
{ eCSSKeyword_last_baseline, NS_STYLE_ALIGN_LAST_BASELINE },
{ eCSSKeyword_start, NS_STYLE_ALIGN_START },
{ eCSSKeyword_end, NS_STYLE_ALIGN_END },
{ eCSSKeyword_flex_start, NS_STYLE_ALIGN_FLEX_START },
{ eCSSKeyword_flex_end, NS_STYLE_ALIGN_FLEX_END },
{ eCSSKeyword_center, NS_STYLE_ALIGN_CENTER },
{ eCSSKeyword_left, NS_STYLE_ALIGN_LEFT },
{ eCSSKeyword_right, NS_STYLE_ALIGN_RIGHT },
{ eCSSKeyword_self_start, NS_STYLE_ALIGN_SELF_START },
{ eCSSKeyword_self_end, NS_STYLE_ALIGN_SELF_END },
{ eCSSKeyword_UNKNOWN, -1 }
};
const KTableEntry nsCSSProps::kAutoCompletionAlignItems[] = {
// Intentionally no 'auto' here.
{ eCSSKeyword_normal, NS_STYLE_ALIGN_NORMAL },
{ eCSSKeyword_stretch, NS_STYLE_ALIGN_STRETCH },
{ eCSSKeyword_baseline, NS_STYLE_ALIGN_BASELINE },
{ eCSSKeyword_last_baseline, NS_STYLE_ALIGN_LAST_BASELINE },
{ eCSSKeyword_start, NS_STYLE_ALIGN_START },
{ eCSSKeyword_end, NS_STYLE_ALIGN_END },
{ eCSSKeyword_flex_start, NS_STYLE_ALIGN_FLEX_START },
{ eCSSKeyword_flex_end, NS_STYLE_ALIGN_FLEX_END },
{ eCSSKeyword_center, NS_STYLE_ALIGN_CENTER },
{ eCSSKeyword_left, NS_STYLE_ALIGN_LEFT },
{ eCSSKeyword_right, NS_STYLE_ALIGN_RIGHT },
{ eCSSKeyword_self_start, NS_STYLE_ALIGN_SELF_START },
{ eCSSKeyword_self_end, NS_STYLE_ALIGN_SELF_END },
{ eCSSKeyword_UNKNOWN, -1 }
};
const KTableEntry nsCSSProps::kAutoCompletionAlignJustifyContent[] = {
// Intentionally no 'auto' here.
{ eCSSKeyword_normal, NS_STYLE_ALIGN_NORMAL },
{ eCSSKeyword_baseline, NS_STYLE_ALIGN_BASELINE },
{ eCSSKeyword_last_baseline, NS_STYLE_ALIGN_LAST_BASELINE },
{ eCSSKeyword_stretch, NS_STYLE_ALIGN_STRETCH },
{ eCSSKeyword_space_between, NS_STYLE_ALIGN_SPACE_BETWEEN },
{ eCSSKeyword_space_around, NS_STYLE_ALIGN_SPACE_AROUND },
{ eCSSKeyword_space_evenly, NS_STYLE_ALIGN_SPACE_EVENLY },
{ eCSSKeyword_start, NS_STYLE_ALIGN_START },
{ eCSSKeyword_end, NS_STYLE_ALIGN_END },
{ eCSSKeyword_flex_start, NS_STYLE_ALIGN_FLEX_START },
{ eCSSKeyword_flex_end, NS_STYLE_ALIGN_FLEX_END },
{ eCSSKeyword_center, NS_STYLE_ALIGN_CENTER },
{ eCSSKeyword_left, NS_STYLE_ALIGN_LEFT },
{ eCSSKeyword_right, NS_STYLE_ALIGN_RIGHT },
{ eCSSKeyword_UNKNOWN, -1 }
};
// </NOTE>
const KTableEntry nsCSSProps::kFlexDirectionKTable[] = {
{ eCSSKeyword_row, NS_STYLE_FLEX_DIRECTION_ROW },
{ eCSSKeyword_row_reverse, NS_STYLE_FLEX_DIRECTION_ROW_REVERSE },
+5 -3
View File
@@ -726,7 +726,7 @@ public:
static KTableEntry kDisplayKTable[];
static const KTableEntry kElevationKTable[];
static const KTableEntry kEmptyCellsKTable[];
// -- tables for the align-/justify-content/items/self properties --
// -- tables for parsing the {align,justify}-{content,items,self} properties --
static const KTableEntry kAlignAllKeywords[];
static const KTableEntry kAlignOverflowPosition[]; // <overflow-position>
static const KTableEntry kAlignSelfPosition[]; // <self-position>
@@ -737,8 +737,10 @@ public:
static const KTableEntry kAlignNormalBaseline[]; // 'normal/baseline/last-baseline'
static const KTableEntry kAlignContentDistribution[]; // <content-distribution>
static const KTableEntry kAlignContentPosition[]; // <content-position>
static const KTableEntry kAlignSelfKTable[];
static const KTableEntry kJustifyContentKTable[];
// -- tables for auto-completion of the {align,justify}-{content,items,self} properties --
static const KTableEntry kAutoCompletionAlignJustifySelf[];
static const KTableEntry kAutoCompletionAlignItems[];
static const KTableEntry kAutoCompletionAlignJustifyContent[];
// ------------------------------------------------------------------
static const KTableEntry kFlexDirectionKTable[];
static const KTableEntry kFlexWrapKTable[];
+101 -29
View File
@@ -31,6 +31,18 @@ using namespace mozilla::dom;
#define LOG_ENABLED() MOZ_LOG_TEST(gfxUserFontSet::GetUserFontsLog(), \
LogLevel::Debug)
static uint32_t
GetFallbackDelay()
{
return Preferences::GetInt("gfx.downloadable_fonts.fallback_delay", 3000);
}
static uint32_t
GetShortFallbackDelay()
{
return Preferences::GetInt("gfx.downloadable_fonts.fallback_delay_short", 100);
}
nsFontFaceLoader::nsFontFaceLoader(gfxUserFontEntry* aUserFontEntry,
nsIURI* aFontURI,
FontFaceSet* aFontFaceSet,
@@ -60,8 +72,15 @@ nsFontFaceLoader::~nsFontFaceLoader()
void
nsFontFaceLoader::StartedLoading(nsIStreamLoader* aStreamLoader)
{
int32_t loadTimeout =
Preferences::GetInt("gfx.downloadable_fonts.fallback_delay", 3000);
int32_t loadTimeout;
uint8_t fontDisplay = GetFontDisplay();
if (fontDisplay == NS_FONT_DISPLAY_AUTO ||
fontDisplay == NS_FONT_DISPLAY_BLOCK) {
loadTimeout = GetFallbackDelay();
} else {
loadTimeout = GetShortFallbackDelay();
}
if (loadTimeout > 0) {
mLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mLoadTimer) {
@@ -87,39 +106,72 @@ nsFontFaceLoader::LoadTimerCallback(nsITimer* aTimer, void* aClosure)
}
gfxUserFontEntry* ufe = loader->mUserFontEntry.get();
bool updateUserFontSet = true;
uint8_t fontDisplay = loader->GetFontDisplay();
// If the entry is loading, check whether it's >75% done; if so,
// we allow another timeout period before showing a fallback font.
if (ufe->mFontDataLoadingState == gfxUserFontEntry::LOADING_STARTED) {
int64_t contentLength;
uint32_t numBytesRead;
if (NS_SUCCEEDED(loader->mChannel->GetContentLength(&contentLength)) &&
contentLength > 0 &&
contentLength < UINT32_MAX &&
NS_SUCCEEDED(loader->mStreamLoader->GetNumBytesRead(&numBytesRead)) &&
numBytesRead > 3 * (uint32_t(contentLength) >> 2))
{
// More than 3/4 the data has been downloaded, so allow 50% extra
// time and hope the remainder will arrive before the additional
// time expires.
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_ALMOST_DONE;
uint32_t delay;
loader->mLoadTimer->GetDelay(&delay);
loader->mLoadTimer->InitWithFuncCallback(LoadTimerCallback,
static_cast<void*>(loader),
delay >> 1,
nsITimer::TYPE_ONE_SHOT);
updateUserFontSet = false;
LOG(("userfonts (%p) 75%% done, resetting timer\n", loader));
// Depending upon the value of the font-display descriptor for the font,
// their may be one or two timeouts associated with each font. The LOADING_SLOWLY
// state indicates that the fallback font is shown. The LOADING_TIMED_OUT
// state indicates that the fallback font is shown *and* the downloaded font
// resource will not replace the fallback font when the load completes.
bool updateUserFontSet = true;
switch (fontDisplay) {
case NS_FONT_DISPLAY_AUTO:
case NS_FONT_DISPLAY_BLOCK:
// If the entry is loading, check whether it's >75% done; if so,
// we allow another timeout period before showing a fallback font.
if (ufe->mFontDataLoadingState == gfxUserFontEntry::LOADING_STARTED) {
int64_t contentLength;
uint32_t numBytesRead;
if (NS_SUCCEEDED(loader->mChannel->GetContentLength(&contentLength)) &&
contentLength > 0 &&
contentLength < UINT32_MAX &&
NS_SUCCEEDED(loader->mStreamLoader->GetNumBytesRead(&numBytesRead)) &&
numBytesRead > 3 * (uint32_t(contentLength) >> 2))
{
// More than 3/4 the data has been downloaded, so allow 50% extra
// time and hope the remainder will arrive before the additional
// time expires.
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_ALMOST_DONE;
uint32_t delay;
loader->mLoadTimer->GetDelay(&delay);
loader->mLoadTimer->InitWithFuncCallback(LoadTimerCallback,
static_cast<void*>(loader),
delay >> 1,
nsITimer::TYPE_ONE_SHOT);
updateUserFontSet = false;
LOG(("userfonts (%p) 75%% done, resetting timer\n", loader));
}
}
if (updateUserFontSet) {
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
}
break;
case NS_FONT_DISPLAY_SWAP:
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
break;
case NS_FONT_DISPLAY_FALLBACK: {
if (ufe->mFontDataLoadingState == gfxUserFontEntry::LOADING_STARTED) {
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
} else {
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_TIMED_OUT;
updateUserFontSet = false;
}
break;
}
case NS_FONT_DISPLAY_OPTIONAL:
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_TIMED_OUT;
break;
default:
NS_NOTREACHED("strange font-display value");
break;
}
// If the font is not 75% loaded, or if we've already timed out once
// before, we mark this entry as "loading slowly", so the fallback
// font will be used in the meantime, and tell the context to refresh.
if (updateUserFontSet) {
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
nsTArray<gfxUserFontSet*> fontSets;
ufe->GetUserFontSets(fontSets);
for (gfxUserFontSet* fontSet : fontSets) {
@@ -127,8 +179,8 @@ nsFontFaceLoader::LoadTimerCallback(nsITimer* aTimer, void* aClosure)
if (ctx) {
fontSet->IncrementGeneration();
ctx->UserFontSetUpdated(ufe);
LOG(("userfonts (%p) timeout reflow for pres context %p\n",
loader, ctx));
LOG(("userfonts (%p) timeout reflow for pres context %p display %d\n",
loader, ctx, fontDisplay));
}
}
}
@@ -155,6 +207,16 @@ nsFontFaceLoader::OnStreamComplete(nsIStreamLoader* aLoader,
uint32_t downloadTimeMS = uint32_t(downloadTime.ToMilliseconds());
Telemetry::Accumulate(Telemetry::WEBFONT_DOWNLOAD_TIME, downloadTimeMS);
if (GetFontDisplay() == NS_FONT_DISPLAY_FALLBACK) {
uint32_t loadTimeout = GetFallbackDelay();
if (downloadTimeMS > loadTimeout &&
(mUserFontEntry->mFontDataLoadingState ==
gfxUserFontEntry::LOADING_SLOWLY)) {
mUserFontEntry->mFontDataLoadingState =
gfxUserFontEntry::LOADING_TIMED_OUT;
}
}
if (LOG_ENABLED()) {
nsAutoCString fontURI;
mFontURI->GetSpec(fontURI);
@@ -271,3 +333,13 @@ nsFontFaceLoader::CheckLoadAllowed(nsIPrincipal* aSourcePrincipal,
return NS_OK;
}
uint8_t
nsFontFaceLoader::GetFontDisplay()
{
uint8_t fontDisplay = NS_FONT_DISPLAY_AUTO;
if (Preferences::GetBool("layout.css.font-display.enabled")) {
fontDisplay = mUserFontEntry->GetFontDisplay();
}
return fontDisplay;
}
+3
View File
@@ -50,6 +50,9 @@ public:
protected:
virtual ~nsFontFaceLoader();
// helper method for determining the font-display value
uint8_t GetFontDisplay();
private:
RefPtr<gfxUserFontEntry> mUserFontEntry;
nsCOMPtr<nsIURI> mFontURI;
+2 -1
View File
@@ -2456,7 +2456,8 @@ struct nsStylePosition
const nsStyleVisibility* aOldStyleVisibility) const;
static nsChangeHint MaxDifference() {
return NS_CombineHint(NS_STYLE_HINT_REFLOW,
nsChangeHint(nsChangeHint_RecomputePosition |
nsChangeHint(nsChangeHint_NeutralChange |
nsChangeHint_RecomputePosition |
nsChangeHint_UpdateParentOverflow |
nsChangeHint_UpdateComputedBSize));
}
+5
View File
@@ -63,5 +63,10 @@ var gCSSFontFaceDescriptors = {
domProp: null,
values: [ "U+0-10FFFF", "U+3-7B3", "U+3??", "U+6A", "U+3????", "U+???", "U+302-302", "U+0-7,U+A-C", "U+100-17F,U+200-17F", "U+3??, U+500-513 ,U+612 , U+4????", "U+1FFF,U+200-27F" ],
invalid_values: [ "U+1????-2????", "U+0-7,A-C", "U+100-17F,200-17F", "U+6A!important", "U+6A)" ]
},
"font-display": {
domProp: null,
values: [ "auto", "block", "swap", "fallback", "optional" ],
invalid_values: [ "normal", "initial" ]
}
}
+7 -35
View File
@@ -7006,6 +7006,13 @@ if (IsCSSPropertyPrefEnabled("layout.css.prefixes.webkit")) {
alias_for: "animation-timing-function",
subproperties: [ "animation-timing-function" ],
};
gCSSProperties["-webkit-filter"] = {
domProp: "webkitFilter",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "filter",
subproperties: [ "filter" ],
};
gCSSProperties["-webkit-text-size-adjust"] = {
domProp: "webkitTextSizeAdjust",
inherited: true,
@@ -7160,41 +7167,6 @@ if (IsCSSPropertyPrefEnabled("layout.css.prefixes.webkit")) {
alias_for: "border-image",
subproperties: [ "border-image-source", "border-image-slice", "border-image-width", "border-image-outset", "border-image-repeat" ],
};
gCSSProperties["-webkit-border-image-outset"] = {
domProp: "webkitBorderImageOutset",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "border-image-outset",
subproperties: [ "border-image-outset" ],
};
gCSSProperties["-webkit-border-image-repeat"] = {
domProp: "webkitBorderImageRepeat",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "border-image-repeat",
subproperties: [ "border-image-repeat" ],
};
gCSSProperties["-webkit-border-image-slice"] = {
domProp: "webkitBorderImageSlice",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "border-image-slice",
subproperties: [ "border-image-slice" ],
};
gCSSProperties["-webkit-border-image-source"] = {
domProp: "webkitBorderImageSource",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "border-image-source",
subproperties: [ "border-image-source" ],
};
gCSSProperties["-webkit-border-image-width"] = {
domProp: "webkitBorderImageWidth",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "border-image-width",
subproperties: [ "border-image-width" ],
};
gCSSProperties["-webkit-box-shadow"] = {
domProp: "webkitBoxShadow",
inherited: false,
+18 -10
View File
@@ -91,19 +91,27 @@ function test_descriptor(descriptor)
// To avoid triggering the slow script dialog, we have to test one
// descriptor at a time.
SimpleTest.waitForExplicitFinish();
var descs = [];
for (var desc in gCSSFontFaceDescriptors)
descs.push(desc);
descs = descs.reverse();
function do_one() {
if (descs.length == 0) {
SimpleTest.finish();
return;
function runTest() {
var descs = [];
for (var desc in gCSSFontFaceDescriptors)
descs.push(desc);
descs = descs.reverse();
function do_one() {
if (descs.length == 0) {
SimpleTest.finish();
return;
}
test_descriptor(descs.pop());
SimpleTest.executeSoon(do_one);
}
test_descriptor(descs.pop());
SimpleTest.executeSoon(do_one);
}
SimpleTest.executeSoon(do_one);
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(5);
SpecialPowers.pushPrefEnv({ set: [["layout.css.font-display.enabled", true]] },
runTest);
</script>
</pre>
+14 -7
View File
@@ -19,7 +19,8 @@ var descriptorNames = {
stretch: "font-stretch",
unicodeRange: "unicode-range",
variant: "font-variant",
featureSettings: "font-feature-settings"
featureSettings: "font-feature-settings",
display: "font-display"
};
// Default values for the FontFace descriptor attributes other than family, as
@@ -30,7 +31,8 @@ var defaultValues = {
stretch: "normal",
unicodeRange: "U+0-10FFFF",
variant: "normal",
featureSettings: "normal"
featureSettings: "normal",
display: "auto"
};
// Non-default values for the FontFace descriptor attributes other than family
@@ -42,7 +44,8 @@ var nonDefaultValues = {
stretch: ["Ultra-Condensed", "ultra-condensed"],
unicodeRange: ["U+3??", "U+300-3FF"],
variant: ["Small-Caps", "small-caps"],
featureSettings: ["'dlig' on", "\"dlig\""]
featureSettings: ["'dlig' on", "\"dlig\""],
display: ["Block", "block"]
};
// Invalid values for the FontFace descriptor attributes other than family.
@@ -52,7 +55,8 @@ var invalidValues = {
stretch: "wider",
unicodeRange: "U+1????-2????",
variant: "inherit",
featureSettings: "dlig"
featureSettings: "dlig",
display: "normal"
};
// Invalid font family names.
@@ -159,8 +163,6 @@ function awaitRefresh() {
}
function runTest() {
SimpleTest.waitForExplicitFinish();
// Document and window from inside the display:none iframe.
var nframe = document.getElementById("n");
var ndocument = nframe.contentDocument;
@@ -1859,11 +1861,16 @@ function runTest() {
function start() {
if (SpecialPowers.getBoolPref("layout.css.font-loading-api.enabled")) {
runTest();
SpecialPowers.pushPrefEnv({ set: [["layout.css.font-display.enabled", true]] },
runTest);
} else {
ok(true, "CSS Font Loading API is not enabled.");
}
}
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(5);
</script>
<style></style>
+6 -2
View File
@@ -13,6 +13,10 @@ using namespace mozilla;
namespace mp4_demuxer {
// Limit reads to 32MiB max.
// static
const uint64_t Box::kMAX_BOX_READ = 32 * 1024 * 1024;
// Returns the offset from the start of the body of a box of type |aType|
// to the start of its first child.
static uint32_t
@@ -149,8 +153,8 @@ Box::Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange)
int64_t length;
if (!mContext->mSource->Length(&length)) {
// The HTTP server didn't give us a length to work with.
// Limit the read to 32MiB max.
length = std::min(aRange.mEnd - mChildOffset, uint64_t(32 * 1024 * 1024));
// Limit the read to kMAX_BOX_READ max.
length = std::min(aRange.mEnd - mChildOffset, kMAX_BOX_READ);
} else {
length = aRange.mEnd - mChildOffset;
}
+2 -2
View File
@@ -254,7 +254,7 @@ Index::Index(const nsTArray<Indice>& aIndex,
int64_t lastOffset = 0;
for (size_t i = 0; i < aIndex.Length(); i++) {
const Indice& indice = aIndex[i];
if (indice.sync) {
if (indice.sync || mIsAudio) {
haveSync = true;
}
if (!haveSync) {
@@ -267,7 +267,7 @@ Index::Index(const nsTArray<Indice>& aIndex,
sample.mCompositionRange = Interval<Microseconds>(indice.start_composition,
indice.end_composition);
sample.mDecodeTime = indice.start_decode;
sample.mSync = indice.sync;
sample.mSync = indice.sync || mIsAudio;
// FIXME: Make this infallible after bug 968520 is done.
MOZ_ALWAYS_TRUE(mIndex.AppendElement(sample, fallible));
if (indice.start_offset < lastOffset) {
+24 -9
View File
@@ -112,7 +112,7 @@ MP4Metadata::~MP4Metadata()
#ifdef MOZ_RUST_MP4PARSE
// Helper to test the rust parser on a data source.
static bool try_rust(const UniquePtr<mp4parse_state, FreeMP4ParseState>& aRustState, RefPtr<Stream> aSource, int32_t* aCount)
static bool try_rust(const UniquePtr<mp4parse_state, FreeMP4ParseState>& aRustState, RefPtr<Stream> aSource)
{
static LazyLogModule sLog("MP4Metadata");
int64_t length;
@@ -129,9 +129,7 @@ static bool try_rust(const UniquePtr<mp4parse_state, FreeMP4ParseState>& aRustSt
MOZ_LOG(sLog, LogLevel::Warning, ("Error copying mp4 data"));
return false;
}
*aCount = mp4parse_read(aRustState.get(), buffer.data(), bytes_read);
MOZ_LOG(sLog, LogLevel::Info, ("rust parser found %d tracks", int(*aCount)));
return true;
return mp4parse_read(aRustState.get(), buffer.data(), bytes_read);
}
#endif
@@ -139,12 +137,18 @@ uint32_t
MP4Metadata::GetNumberTracks(mozilla::TrackInfo::TrackType aType) const
{
#ifdef MOZ_RUST_MP4PARSE
static LazyLogModule sLog("MP4Metadata");
// Try in rust first.
mRustState.reset(mp4parse_new());
int32_t rust_tracks = 0;
bool rust_mp4parse_success = try_rust(mRustState, mSource, &rust_tracks);
int32_t rust_mp4parse_success = try_rust(mRustState, mSource);
Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_SUCCESS,
rust_mp4parse_success);
rust_mp4parse_success == 0);
if (rust_mp4parse_success < 0) {
Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_ERROR_CODE,
-rust_mp4parse_success);
}
uint32_t rust_tracks = mp4parse_get_track_count(mRustState.get());
MOZ_LOG(sLog, LogLevel::Info, ("rust parser found %u tracks", rust_tracks));
#endif
size_t tracks = mPrivate->mMetadataExtractor->countTracks();
uint32_t total = 0;
@@ -176,7 +180,7 @@ MP4Metadata::GetNumberTracks(mozilla::TrackInfo::TrackType aType) const
uint32_t rust_total = 0;
const char* rust_track_type = nullptr;
if (rust_mp4parse_success && rust_tracks > 0) {
for (int32_t i = 0; i < rust_tracks; ++i) {
for (uint32_t i = 0; i < rust_tracks; ++i) {
mp4parse_track_info track_info;
int32_t r = mp4parse_get_track_info(mRustState.get(), i, &track_info);
switch (aType) {
@@ -197,9 +201,20 @@ MP4Metadata::GetNumberTracks(mozilla::TrackInfo::TrackType aType) const
}
}
}
static LazyLogModule sLog("MP4Metadata");
MOZ_LOG(sLog, LogLevel::Info, ("%s tracks found: stagefright=%u rust=%u",
rust_track_type, total, rust_total));
switch (aType) {
case mozilla::TrackInfo::kAudioTrack:
Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_TRACK_MATCH_AUDIO,
rust_total == total);
break;
case mozilla::TrackInfo::kVideoTrack:
Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_TRACK_MATCH_VIDEO,
rust_total == total);
break;
default:
break;
}
#endif
return total;
}
+3 -1
View File
@@ -182,7 +182,9 @@ MoofParser::Metadata()
MediaByteRange ftyp;
MediaByteRange moov;
ScanForMetadata(ftyp, moov);
if (!ftyp.Length() || !moov.Length()) {
if (!ftyp.Length() || !moov.Length() ||
ftyp.Length() > Box::kMAX_BOX_READ || moov.Length() > Box::kMAX_BOX_READ) {
// No ftyp or moov, or trying to read bigger-that-readable box (32MB).
return nullptr;
}
RefPtr<MediaByteBuffer> metadata = new MediaByteBuffer();
@@ -0,0 +1,37 @@
diff --git a/media/libstagefright/binding/byteorder/mod.rs b/media/libstagefright/binding/byteorder/mod.rs
index 59ba692..9d2d1d5 100644
--- a/media/libstagefright/binding/byteorder/mod.rs
+++ b/media/libstagefright/binding/byteorder/mod.rs
@@ -36,16 +36,16 @@ assert_eq!(wtr, vec![5, 2, 0, 3]);
```
*/
-#![crate_name = "byteorder"]
#![doc(html_root_url = "http://burntsushi.net/rustdoc/byteorder")]
#![deny(missing_docs)]
use std::mem::transmute;
-pub use new::{ReadBytesExt, WriteBytesExt, Error, Result};
+pub use byteorder::new::{ReadBytesExt, WriteBytesExt, Error, Result};
-mod new;
+// Re-export new so gecko can build us as a mod intead of a crate.
+pub mod new;
#[inline]
fn extend_sign(val: u64, nbytes: usize) -> i64 {
diff --git a/media/libstagefright/binding/byteorder/new.rs b/media/libstagefright/binding/byteorder/new.rs
index bbef0cd..a2e5393 100644
--- a/media/libstagefright/binding/byteorder/new.rs
+++ b/media/libstagefright/binding/byteorder/new.rs
@@ -3,7 +3,7 @@ use std::fmt;
use std::io;
use std::result;
-use ByteOrder;
+use byteorder::ByteOrder;
/// A short-hand for `result::Result<T, byteorder::Error>`.
pub type Result<T> = result::Result<T, Error>;
@@ -51,6 +51,8 @@ public:
bool Read(nsTArray<uint8_t>* aDest);
bool Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange);
static const uint64_t kMAX_BOX_READ;
private:
bool Contains(MediaByteRange aRange) const;
BoxContext* mContext;
@@ -0,0 +1,13 @@
diff --git a/media/libstagefright/binding/MP4Metadata.rs b/media/libstagefright/binding/MP4Metadata.rs
index 2f1b873..d2ad827 100644
--- a/media/libstagefright/binding/MP4Metadata.rs
+++ b/media/libstagefright/binding/MP4Metadata.rs
@@ -4,7 +4,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
-extern crate byteorder;
+mod byteorder; // 'extern crate' upstream.
use byteorder::ReadBytesExt;
use std::error::Error as ErrorTrait; // For Err(e) => e.description().
use std::io::{Read, BufRead, Take};
@@ -0,0 +1,37 @@
#!/bin/sh
# Script to update mp4parse-rust sources to latest upstream
# Default version.
VER=v0.1.3
# Accept version or commit from the command line.
if test -n "$1"; then
VER=$1
fi
echo "Fetching sources..."
rm -rf _upstream
git clone https://github.com/mozilla/mp4parse-rust _upstream/mp4parse
pushd _upstream/mp4parse
git checkout ${VER}
popd
cp _upstream/mp4parse/src/lib.rs MP4Metadata.rs
cp _upstream/mp4parse/src/capi.rs .
# TODO: download deps from crates.io.
git clone https://github.com/BurntSushi/byteorder _upstream/byteorder
pushd _upstream/byteorder
git checkout 0.3.13
popd
cp _upstream/byteorder/src/lib.rs byteorder/mod.rs
cp _upstream/byteorder/src/new.rs byteorder/new.rs
echo "Applying patches..."
patch -p4 < byteorder-mod.patch
patch -p4 < mp4parse-mod.patch
echo "Cleaning up..."
rm -rf _upstream
echo "Updated to ${VER}."

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