Merge inbound to mozilla-central. a=merge

This commit is contained in:
Gurzau Raul 2018-07-28 12:45:44 +03:00
commit db79375c66
101 changed files with 2202 additions and 741 deletions

View File

@ -47,6 +47,7 @@ AccessibleNode::AccessibleNode(nsINode* aNode) :
mIntProperties(3),
mUIntProperties(6),
mBooleanProperties(0),
mRelationProperties(3),
mStringProperties(16),
mDOMNode(aNode)
{

View File

@ -51,6 +51,17 @@ struct ParentObject;
SetProperty(AOMStringProperty::e##name, a##name); \
} \
#define ANODE_RELATION_FUNC(name) \
already_AddRefed<AccessibleNode> Get##name() \
{ \
return GetProperty(AOMRelationProperty::e##name); \
} \
\
void Set##name(AccessibleNode* a##name) \
{ \
SetProperty(AOMRelationProperty::e##name, a##name); \
} \
#define ANODE_PROPS(typeName, type, ...) \
enum class AOM##typeName##Property { \
MOZ_FOR_EACH(ANODE_ENUM, (), (__VA_ARGS__)) \
@ -63,6 +74,12 @@ struct ParentObject;
}; \
MOZ_FOR_EACH(ANODE_STRING_FUNC, (), (__VA_ARGS__)) \
#define ANODE_RELATION_PROPS(...) \
enum class AOMRelationProperty { \
MOZ_FOR_EACH(ANODE_ENUM, (), (__VA_ARGS__)) \
}; \
MOZ_FOR_EACH(ANODE_RELATION_FUNC, (), (__VA_ARGS__)) \
#define ANODE_ACCESSOR_MUTATOR(typeName, type, defVal) \
nsDataHashtable<nsUint32HashKey, type> m##typeName##Properties; \
\
@ -164,6 +181,12 @@ public:
ValueNow
)
ANODE_RELATION_PROPS(
ActiveDescendant,
Details,
ErrorMessage
)
protected:
AccessibleNode(const AccessibleNode& aCopy) = delete;
AccessibleNode& operator=(const AccessibleNode& aCopy) = delete;
@ -213,9 +236,29 @@ protected:
ANODE_ACCESSOR_MUTATOR(Int, int32_t, 0)
ANODE_ACCESSOR_MUTATOR(UInt, uint32_t, 0)
already_AddRefed<AccessibleNode> GetProperty(AOMRelationProperty aProperty)
{
RefPtr<AccessibleNode> data;
if (mRelationProperties.Get(static_cast<int>(aProperty), &data)) {
return data.forget();
}
return nullptr;
}
void SetProperty(AOMRelationProperty aProperty,
AccessibleNode* aValue)
{
if (!aValue) {
mRelationProperties.Remove(static_cast<int>(aProperty));
} else {
mRelationProperties.Put(static_cast<int>(aProperty), aValue);
}
}
// The 2k'th bit indicates whether the k'th boolean property is used(1) or not(0)
// and 2k+1'th bit contains the property's value(1:true, 0:false)
uint32_t mBooleanProperties;
nsDataHashtable<nsUint32HashKey, RefPtr<AccessibleNode> > mRelationProperties;
nsDataHashtable<nsUint32HashKey, nsString> mStringProperties;
RefPtr<a11y::Accessible> mIntl;

View File

@ -29,6 +29,13 @@ const GECKOVIEW_MESSAGE = {
CLIPBOARD: "GeckoView:AccessibilityClipboard",
};
const ACCESSFU_MESSAGE = {
PRESENT: "AccessFu:Present",
DOSCROLL: "AccessFu:DoScroll",
};
const FRAME_SCRIPT = "chrome://global/content/accessibility/content-script.js";
var AccessFu = {
/**
* A lazy getter for event handler that binds the scope to AccessFu object.
@ -64,11 +71,6 @@ var AccessFu = {
this._attachWindow(windows.getNext());
}
if (this.readyCallback) {
this.readyCallback();
delete this.readyCallback;
}
Logger.info("AccessFu:Enabled");
},
@ -107,17 +109,10 @@ var AccessFu = {
});
switch (aMessage.name) {
case "AccessFu:Ready":
let mm = Utils.getMessageManager(aMessage.target);
if (this._enabled) {
mm.sendAsyncMessage("AccessFu:Start",
{method: "start", buildApp: Utils.MozBuildApp});
}
break;
case "AccessFu:Present":
case ACCESSFU_MESSAGE.PRESENT:
this._output(aMessage.json, aMessage.target);
break;
case "AccessFu:DoScroll":
case ACCESSFU_MESSAGE.DOSCROLL:
this.Input.doScroll(aMessage.json, aMessage.target);
break;
}
@ -130,13 +125,13 @@ var AccessFu = {
return;
}
for (let mm of Utils.getAllMessageManagers(win)) {
this._addMessageListeners(mm);
this._loadFrameScript(mm);
// Set up frame script
let mm = win.messageManager;
for (let messageName of Object.values(ACCESSFU_MESSAGE)) {
mm.addMessageListener(messageName, this);
}
mm.loadFrameScript(FRAME_SCRIPT, true);
win.addEventListener("TabOpen", this);
win.addEventListener("TabClose", this);
win.addEventListener("TabSelect", this);
if (win.WindowEventDispatcher) {
// desktop mochitests don't have this.
@ -146,13 +141,13 @@ var AccessFu = {
},
_detachWindow: function _detachWindow(win) {
for (let mm of Utils.getAllMessageManagers(win)) {
mm.sendAsyncMessage("AccessFu:Stop");
this._removeMessageListeners(mm);
let mm = win.messageManager;
mm.broadcastAsyncMessage("AccessFu:Stop");
mm.removeDelayedFrameScript(FRAME_SCRIPT);
for (let messageName of Object.values(ACCESSFU_MESSAGE)) {
mm.removeMessageListener(messageName, this);
}
win.removeEventListener("TabOpen", this);
win.removeEventListener("TabClose", this);
win.removeEventListener("TabSelect", this);
if (win.WindowEventDispatcher) {
// desktop mochitests don't have this.
@ -193,38 +188,6 @@ var AccessFu = {
}
},
_loadFrameScript: function _loadFrameScript(aMessageManager) {
if (!this._processedMessageManagers.includes(aMessageManager)) {
aMessageManager.loadFrameScript(
"chrome://global/content/accessibility/content-script.js", true);
this._processedMessageManagers.push(aMessageManager);
} else if (this._enabled) {
// If the content-script is already loaded and AccessFu is enabled,
// send an AccessFu:Start message.
aMessageManager.sendAsyncMessage("AccessFu:Start",
{method: "start", buildApp: Utils.MozBuildApp});
}
},
_addMessageListeners: function _addMessageListeners(aMessageManager) {
aMessageManager.addMessageListener("AccessFu:Present", this);
aMessageManager.addMessageListener("AccessFu:Ready", this);
aMessageManager.addMessageListener("AccessFu:DoScroll", this);
},
_removeMessageListeners: function _removeMessageListeners(aMessageManager) {
aMessageManager.removeMessageListener("AccessFu:Present", this);
aMessageManager.removeMessageListener("AccessFu:Ready", this);
aMessageManager.removeMessageListener("AccessFu:DoScroll", this);
},
_handleMessageManager: function _handleMessageManager(aMessageManager) {
if (this._enabled) {
this._addMessageListeners(aMessageManager);
}
this._loadFrameScript(aMessageManager);
},
onEvent(event, data, callback) {
switch (event) {
case GECKOVIEW_MESSAGE.SETTINGS:
@ -280,19 +243,11 @@ var AccessFu = {
observe: function observe(aSubject, aTopic, aData) {
switch (aTopic) {
case "remote-browser-shown":
case "inprocess-browser-shown":
{
// Ignore notifications that aren't from a Browser
let frameLoader = aSubject;
if (!frameLoader.ownerIsMozBrowserFrame) {
return;
}
this._handleMessageManager(frameLoader.messageManager);
break;
}
case "domwindowopened": {
this._attachWindow(aSubject.QueryInterface(Ci.nsIDOMWindow));
let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
win.addEventListener("load", () => {
this._attachWindow(win);
}, { once: true });
break;
}
}
@ -300,22 +255,6 @@ var AccessFu = {
_handleEvent: function _handleEvent(aEvent) {
switch (aEvent.type) {
case "TabOpen":
{
let mm = Utils.getMessageManager(aEvent.target);
this._handleMessageManager(mm);
break;
}
case "TabClose":
{
let mm = Utils.getMessageManager(aEvent.target);
let mmIndex = this._processedMessageManagers.indexOf(mm);
if (mmIndex > -1) {
this._removeMessageListeners(mm);
this._processedMessageManagers.splice(mmIndex, 1);
}
break;
}
case "TabSelect":
{
if (this._focused) {
@ -350,10 +289,6 @@ var AccessFu = {
// Layerview is focused
_focused: false,
// Keep track of message managers tha already have a 'content-script.js'
// injected.
_processedMessageManagers: [],
/**
* Adjusts the given bounds that are defined in device display pixels
* to client-relative CSS pixels of the chrome window.
@ -413,18 +348,6 @@ var Input = {
mm.sendAsyncMessage("AccessFu:Activate", { offset: 0 });
},
// XXX: This is here for backwards compatability with screen reader simulator
// it should be removed when the extension is updated on amo.
scroll: function scroll(aPage, aHorizontal) {
this.sendScrollMessage(aPage, aHorizontal);
},
sendScrollMessage: function sendScrollMessage(aPage, aHorizontal) {
const mm = Utils.getMessageManager();
mm.sendAsyncMessage("AccessFu:Scroll",
{page: aPage, horizontal: aHorizontal, origin: "top"});
},
doScroll: function doScroll(aDetails, aBrowser) {
let horizontal = aDetails.horizontal;
let page = aDetails.page;

View File

@ -25,9 +25,8 @@ ChromeUtils.defineModuleGetter(this, "setTimeout",
var EXPORTED_SYMBOLS = ["EventManager"];
function EventManager(aContentScope, aContentControl) {
function EventManager(aContentScope) {
this.contentScope = aContentScope;
this.contentControl = aContentControl;
this.addEventListener = this.contentScope.addEventListener.bind(
this.contentScope);
this.removeEventListener = this.contentScope.removeEventListener.bind(
@ -85,6 +84,10 @@ this.EventManager.prototype = {
}
},
get contentControl() {
return this.contentScope._jsat_contentControl;
},
handleEvent: function handleEvent(aEvent) {
Logger.debug(() => {
return ["DOMEvent", aEvent.type];
@ -247,7 +250,7 @@ this.EventManager.prototype = {
this.present(Presentation.focused(acc));
if (this.inTest) {
if (Utils.inTest) {
this.sendMsgFunc("AccessFu:Focused");
}
break;

View File

@ -82,41 +82,6 @@ var Utils = { // jshint ignore:line
return win.document.querySelector("browser[type=content][primary=true]");
},
getAllMessageManagers: function getAllMessageManagers(aWindow) {
let messageManagers = new Set();
function collectLeafMessageManagers(mm) {
for (let i = 0; i < mm.childCount; i++) {
let childMM = mm.getChildAt(i);
if ("sendAsyncMessage" in childMM) {
messageManagers.add(childMM);
} else {
collectLeafMessageManagers(childMM);
}
}
}
collectLeafMessageManagers(aWindow.messageManager);
let browser = this.getCurrentBrowser(aWindow);
let document = browser ? browser.contentDocument : null;
if (document) {
let remoteframes = document.querySelectorAll("iframe");
for (let i = 0; i < remoteframes.length; ++i) {
let mm = this.getMessageManager(remoteframes[i]);
if (mm) {
messageManagers.add(mm);
}
}
}
return messageManagers;
},
get isContentProcess() {
delete this.isContentProcess;
this.isContentProcess =
@ -418,7 +383,8 @@ var Logger = { // jshint ignore:line
logLevel: 1, // INFO;
test: false,
// Note: used for testing purposes. If true, also log to the console service.
useConsoleService: false,
log: function log(aLogLevel) {
if (aLogLevel < this.logLevel) {
@ -430,9 +396,7 @@ var Logger = { // jshint ignore:line
message = "[" + Utils.ScriptName + "] " + this._LEVEL_NAMES[aLogLevel + 1] +
" " + message + "\n";
dump(message);
// Note: used for testing purposes. If |this.test| is true, also log to
// the console service.
if (this.test) {
if (this.useConsoleService) {
try {
Services.console.logStringMessage(message);
} catch (ex) {

View File

@ -6,129 +6,49 @@
ChromeUtils.defineModuleGetter(this, "Logger",
"resource://gre/modules/accessibility/Utils.jsm");
ChromeUtils.defineModuleGetter(this, "Presentation",
"resource://gre/modules/accessibility/Presentation.jsm");
ChromeUtils.defineModuleGetter(this, "Utils",
"resource://gre/modules/accessibility/Utils.jsm");
ChromeUtils.defineModuleGetter(this, "EventManager",
"resource://gre/modules/accessibility/EventManager.jsm");
ChromeUtils.defineModuleGetter(this, "ContentControl",
"resource://gre/modules/accessibility/ContentControl.jsm");
ChromeUtils.defineModuleGetter(this, "Roles",
"resource://gre/modules/accessibility/Constants.jsm");
ChromeUtils.defineModuleGetter(this, "States",
"resource://gre/modules/accessibility/Constants.jsm");
Logger.info("content-script.js", content.document.location);
var eventManager = null;
var contentControl = null;
function onStop(m) {
Logger.debug("AccessFu:Stop");
function forwardToParent(aMessage) {
// XXX: This is a silly way to make a deep copy
let newJSON = JSON.parse(JSON.stringify(aMessage.json));
newJSON.origin = "child";
sendAsyncMessage(aMessage.name, newJSON);
removeMessageListener("AccessFu:Stop", onStop);
this._jsat_eventManager.stop();
this._jsat_contentControl.stop();
}
function forwardToChild(aMessage, aListener, aVCPosition) {
let acc = aVCPosition || Utils.getVirtualCursor(content.document).position;
addMessageListener("AccessFu:Stop", onStop);
if (!Utils.isAliveAndVisible(acc) || acc.role != Roles.INTERNAL_FRAME) {
return false;
}
Logger.debug(() => {
return ["forwardToChild", Logger.accessibleToString(acc),
aMessage.name, JSON.stringify(aMessage.json, null, " ")];
});
let mm = Utils.getMessageManager(acc.DOMNode);
if (aListener) {
mm.addMessageListener(aMessage.name, aListener);
}
// XXX: This is a silly way to make a deep copy
let newJSON = JSON.parse(JSON.stringify(aMessage.json));
newJSON.origin = "parent";
if (Utils.isContentProcess) {
// XXX: OOP content's screen offset is 0,
// so we remove the real screen offset here.
newJSON.x -= content.mozInnerScreenX;
newJSON.y -= content.mozInnerScreenY;
}
mm.sendAsyncMessage(aMessage.name, newJSON);
return true;
if (!this._jsat_contentControl) {
this._jsat_contentControl = new ContentControl(this);
}
this._jsat_contentControl.start();
function presentCaretChange(aText, aOldOffset, aNewOffset) {
if (aOldOffset !== aNewOffset) {
let msg = Presentation.textSelectionChanged(aText, aNewOffset, aNewOffset,
aOldOffset, aOldOffset, true);
sendAsyncMessage("AccessFu:Present", msg);
if (!this._jsat_eventManager) {
this._jsat_eventManager = new EventManager(this);
}
this._jsat_eventManager.start();
function contentStarted() {
let accDoc = Utils.AccService.getAccessibleFor(content.document);
if (accDoc && !Utils.getState(accDoc).contains(States.BUSY)) {
sendAsyncMessage("AccessFu:ContentStarted");
} else {
content.setTimeout(contentStarted, 0);
}
}
function scroll(aMessage) {
let position = Utils.getVirtualCursor(content.document).position;
if (!forwardToChild(aMessage, scroll, position)) {
sendAsyncMessage("AccessFu:DoScroll",
{ bounds: Utils.getBounds(position),
page: aMessage.json.page,
horizontal: aMessage.json.horizontal });
}
if (Utils.inTest) {
// During a test we want to wait for the document to finish loading for
// consistency.
contentStarted();
}
addMessageListener(
"AccessFu:Start",
function(m) {
if (m.json.logLevel) {
Logger.logLevel = Logger[m.json.logLevel];
}
Logger.debug("AccessFu:Start");
if (m.json.buildApp)
Utils.MozBuildApp = m.json.buildApp;
addMessageListener("AccessFu:Scroll", scroll);
if (!contentControl) {
contentControl = new ContentControl(this);
}
contentControl.start();
if (!eventManager) {
eventManager = new EventManager(this, contentControl);
}
eventManager.inTest = m.json.inTest;
eventManager.start();
function contentStarted() {
let accDoc = Utils.AccService.getAccessibleFor(content.document);
if (accDoc && !Utils.getState(accDoc).contains(States.BUSY)) {
sendAsyncMessage("AccessFu:ContentStarted");
} else {
content.setTimeout(contentStarted, 0);
}
}
if (m.json.inTest) {
// During a test we want to wait for the document to finish loading for
// consistency.
contentStarted();
}
});
addMessageListener(
"AccessFu:Stop",
function(m) {
Logger.debug("AccessFu:Stop");
removeMessageListener("AccessFu:Scroll", scroll);
eventManager.stop();
contentControl.stop();
});
sendAsyncMessage("AccessFu:Ready");

View File

@ -84,6 +84,13 @@
is(anode[prop], null, `anode.${prop} was assigned null`);
}
function testRelationProp(anode, node, prop) {
is(anode[prop], null, `anode.${prop} should be null`);
anode[prop] = node.accessibleNode;
is(anode[prop], node.accessibleNode, `anode.${prop} was assigned AccessibleNode`);
anode[prop] = null;
is(anode[prop], null, `anode.${prop} was assigned null`);
}
// Check that the WebIDL is as expected.
function checkImplementation(ifrDoc) {
let anode = ifrDoc.accessibleNode;
@ -188,6 +195,12 @@
let adopted_node = anotherDoc.adoptNode(node);
is(anode, adopted_node.accessibleNode, "adopting node to another document doesn't change node.accessibleNode");
const relationProps = ["activeDescendant", "details", "errorMessage"];
for (const relationProp of relationProps) {
testRelationProp(anode, node, relationProp);
}
finish();
}
</script>

View File

@ -105,7 +105,7 @@ var AccessFuTest = {
finish: function AccessFuTest_finish() {
// Disable the console service logging.
Logger.test = false;
Logger.useConsoleService = false;
Logger.logLevel = Logger.INFO;
// Finish through idle callback to let AccessFu._disable complete.
SimpleTest.executeSoon(function() {
@ -116,13 +116,15 @@ var AccessFuTest = {
},
nextTest: function AccessFuTest_nextTest() {
var result = gIterator.next();
if (result.done) {
this.finish();
return;
}
var testFunc = result.value;
testFunc();
SimpleTest.executeSoon(() => {
var result = gIterator.next();
if (result.done) {
this.finish();
return;
}
var testFunc = result.value;
testFunc();
});
},
runTests: function AccessFuTest_runTests(aAdditionalPrefs) {
@ -139,15 +141,12 @@ var AccessFuTest = {
}
})();
Logger.useConsoleService = true;
Logger.logLevel = Logger.DEBUG;
// Start AccessFu and put it in stand-by.
ChromeUtils.import("resource://gre/modules/accessibility/AccessFu.jsm");
AccessFu.readyCallback = function readyCallback() {
// Enable logging to the console service.
Logger.test = true;
Logger.logLevel = Logger.DEBUG;
};
var prefs = [["accessibility.accessfu.notify_output", 1]];
prefs.push.apply(prefs, aAdditionalPrefs);
@ -216,6 +215,10 @@ class AccessFuContentTestRunner {
async setupMessageManager(aMessageManager) {
function contentScript() {
ChromeUtils.import("resource://gre/modules/accessibility/Utils.jsm");
Logger.logLevel = "DEBUG";
Utils.inTest = true;
addMessageListener("AccessFuTest:Focus", aMessage => {
var elem = content.document.querySelector(aMessage.data.selector);
if (elem) {
@ -231,23 +234,12 @@ class AccessFuContentTestRunner {
aMessageManager.loadFrameScript(
"data:,(" + contentScript.toString() + ")();", false);
let readyPromise = new Promise(resolve =>
aMessageManager.addMessageListener("AccessFu:Ready", resolve));
aMessageManager.loadFrameScript(
"chrome://global/content/accessibility/content-script.js", false);
await readyPromise;
let startedPromise = new Promise(resolve =>
aMessageManager.addMessageListener("AccessFu:ContentStarted", resolve));
aMessageManager.sendAsyncMessage("AccessFu:Start",
{ buildApp: "browser",
androidSdkVersion: Utils.AndroidSdkVersion,
logLevel: "DEBUG",
inTest: true });
await startedPromise;
aMessageManager.addMessageListener("AccessFu:Present", this);

View File

@ -1376,6 +1376,9 @@ var gBrowserInit = {
// make sure it has a docshell
gBrowser.docShell;
// Remove the speculative focus from the urlbar to let the url be formatted.
gURLBar.removeAttribute("focused");
try {
gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, tabToAdopt);
} catch (e) {

View File

@ -8,7 +8,7 @@
* Color the boxes in the treemap
*/
const TYPES = [ "objects", "other", "strings", "scripts" ];
const TYPES = [ "objects", "other", "strings", "scripts", "domNode" ];
// The factors determine how much the hue shifts
const TYPE_FACTOR = TYPES.length * 3;

View File

@ -122,6 +122,7 @@ actions.RESIZE_SHORTEST_PATHS = "resize-shortest-paths";
const COUNT = Object.freeze({ by: "count", count: true, bytes: true });
const INTERNAL_TYPE = Object.freeze({ by: "internalType", then: COUNT });
const DESCRIPTIVE_TYPE = Object.freeze({ by: "descriptiveType", then: COUNT });
const ALLOCATION_STACK = Object.freeze({
by: "allocationStack", then: COUNT,
noStack: COUNT
@ -137,6 +138,7 @@ const COARSE_TYPE = Object.freeze({
noFilename: INTERNAL_TYPE
},
other: INTERNAL_TYPE,
domNode: DESCRIPTIVE_TYPE,
});
exports.censusDisplays = Object.freeze({
@ -186,6 +188,7 @@ const DOMINATOR_TREE_LABEL_COARSE_TYPE = Object.freeze({
}),
strings: INTERNAL_TYPE,
other: INTERNAL_TYPE,
domNode: DESCRIPTIVE_TYPE,
});
exports.labelDisplays = Object.freeze({

View File

@ -32,8 +32,8 @@ add_task(async function() {
};
drawBox(ctx, node, borderWidth, dragZoom, padding);
ok(true, JSON.stringify([ctx, fillRectValues, strokeRectValues]));
equal(ctx.fillStyle, "hsl(210,60%,70%)", "The fillStyle is set");
equal(ctx.strokeStyle, "hsl(210,60%,35%)", "The strokeStyle is set");
equal(ctx.fillStyle, "hsl(204,60%,70%)", "The fillStyle is set");
equal(ctx.strokeStyle, "hsl(204,60%,35%)", "The strokeStyle is set");
equal(ctx.lineWidth, 1, "The lineWidth is set");
deepEqual(fillRectValues, [10.5, 20.5, 49, 69], "Draws a filled rectangle");
deepEqual(strokeRectValues, [10.5, 20.5, 49, 69], "Draws a stroked rectangle");

View File

@ -80,6 +80,14 @@ EDGES.internalType = function(breakdown, report) {
}));
};
EDGES.descriptiveType = function(breakdown, report) {
return Object.keys(report).map(key => ({
edge: key,
referent: report[key],
breakdown: breakdown.then
}));
};
EDGES.objectClass = function(breakdown, report) {
return Object.keys(report).map(key => ({
edge: key,
@ -94,6 +102,7 @@ EDGES.coarseType = function(breakdown, report) {
{ edge: "scripts", referent: report.scripts, breakdown: breakdown.scripts },
{ edge: "strings", referent: report.strings, breakdown: breakdown.strings },
{ edge: "other", referent: report.other, breakdown: breakdown.other },
{ edge: "domNode", referent: report.domNode, breakdown: breakdown.domNode },
];
};

View File

@ -48,6 +48,8 @@ public:
::google::protobuf::uint64 jsobjectclassnameref_;
::google::protobuf::internal::ArenaStringPtr scriptfilename_;
::google::protobuf::uint64 scriptfilenameref_;
::google::protobuf::internal::ArenaStringPtr descriptivetypename_;
::google::protobuf::uint64 descriptivetypenameref_;
} _Node_default_instance_;
class EdgeDefaultTypeInternal {
public:
@ -1749,6 +1751,8 @@ const int Node::kJsObjectClassNameRefFieldNumber;
const int Node::kCoarseTypeFieldNumber;
const int Node::kScriptFilenameFieldNumber;
const int Node::kScriptFilenameRefFieldNumber;
const int Node::kDescriptiveTypeNameFieldNumber;
const int Node::kDescriptiveTypeNameRefFieldNumber;
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
Node::Node()
@ -1816,6 +1820,20 @@ Node::Node(const Node& from)
break;
}
}
clear_has_descriptiveTypeNameOrRef();
switch (from.descriptiveTypeNameOrRef_case()) {
case kDescriptiveTypeName: {
set_descriptivetypename(from.descriptivetypename());
break;
}
case kDescriptiveTypeNameRef: {
set_descriptivetypenameref(from.descriptivetypenameref());
break;
}
case DESCRIPTIVETYPENAMEORREF_NOT_SET: {
break;
}
}
// @@protoc_insertion_point(copy_constructor:mozilla.devtools.protobuf.Node)
}
@ -1827,6 +1845,7 @@ void Node::SharedCtor() {
clear_has_TypeNameOrRef();
clear_has_JSObjectClassNameOrRef();
clear_has_ScriptFilenameOrRef();
clear_has_descriptiveTypeNameOrRef();
}
Node::~Node() {
@ -1845,6 +1864,9 @@ void Node::SharedDtor() {
if (has_ScriptFilenameOrRef()) {
clear_ScriptFilenameOrRef();
}
if (has_descriptiveTypeNameOrRef()) {
clear_descriptiveTypeNameOrRef();
}
}
void Node::SetCachedSize(int size) const {
@ -1919,6 +1941,24 @@ void Node::clear_ScriptFilenameOrRef() {
_oneof_case_[2] = SCRIPTFILENAMEORREF_NOT_SET;
}
void Node::clear_descriptiveTypeNameOrRef() {
// @@protoc_insertion_point(one_of_clear_start:mozilla.devtools.protobuf.Node)
switch (descriptiveTypeNameOrRef_case()) {
case kDescriptiveTypeName: {
descriptiveTypeNameOrRef_.descriptivetypename_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
break;
}
case kDescriptiveTypeNameRef: {
// No need to clear
break;
}
case DESCRIPTIVETYPENAMEORREF_NOT_SET: {
break;
}
}
_oneof_case_[3] = DESCRIPTIVETYPENAMEORREF_NOT_SET;
}
void Node::Clear() {
// @@protoc_insertion_point(message_clear_start:mozilla.devtools.protobuf.Node)
@ -1940,6 +1980,7 @@ void Node::Clear() {
clear_TypeNameOrRef();
clear_JSObjectClassNameOrRef();
clear_ScriptFilenameOrRef();
clear_descriptiveTypeNameOrRef();
_has_bits_.Clear();
_internal_metadata_.Clear();
}
@ -2107,6 +2148,33 @@ bool Node::MergePartialFromCodedStream(
break;
}
// optional bytes descriptiveTypeName = 12;
case 12: {
if (static_cast< ::google::protobuf::uint8>(tag) ==
static_cast< ::google::protobuf::uint8>(98u /* 98 & 0xFF */)) {
DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
input, this->mutable_descriptivetypename()));
} else {
goto handle_unusual;
}
break;
}
// optional uint64 descriptiveTypeNameRef = 13;
case 13: {
if (static_cast< ::google::protobuf::uint8>(tag) ==
static_cast< ::google::protobuf::uint8>(104u /* 104 & 0xFF */)) {
clear_descriptiveTypeNameOrRef();
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
input, &descriptiveTypeNameOrRef_.descriptivetypenameref_)));
set_has_descriptivetypenameref();
} else {
goto handle_unusual;
}
break;
}
default: {
handle_unusual:
if (tag == 0) {
@ -2192,6 +2260,16 @@ void Node::SerializeWithCachedSizes(
break;
default: ;
}
switch (descriptiveTypeNameOrRef_case()) {
case kDescriptiveTypeName:
::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
12, this->descriptivetypename(), output);
break;
case kDescriptiveTypeNameRef:
::google::protobuf::internal::WireFormatLite::WriteUInt64(13, this->descriptivetypenameref(), output);
break;
default: ;
}
output->WriteRaw(_internal_metadata_.unknown_fields().data(),
static_cast<int>(_internal_metadata_.unknown_fields().size()));
// @@protoc_insertion_point(serialize_end:mozilla.devtools.protobuf.Node)
@ -2301,6 +2379,25 @@ size_t Node::ByteSizeLong() const {
break;
}
}
switch (descriptiveTypeNameOrRef_case()) {
// optional bytes descriptiveTypeName = 12;
case kDescriptiveTypeName: {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::BytesSize(
this->descriptivetypename());
break;
}
// optional uint64 descriptiveTypeNameRef = 13;
case kDescriptiveTypeNameRef: {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::UInt64Size(
this->descriptivetypenameref());
break;
}
case DESCRIPTIVETYPENAMEORREF_NOT_SET: {
break;
}
}
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = cached_size;
@ -2376,6 +2473,19 @@ void Node::MergeFrom(const Node& from) {
break;
}
}
switch (from.descriptiveTypeNameOrRef_case()) {
case kDescriptiveTypeName: {
set_descriptivetypename(from.descriptivetypename());
break;
}
case kDescriptiveTypeNameRef: {
set_descriptivetypenameref(from.descriptivetypenameref());
break;
}
case DESCRIPTIVETYPENAMEORREF_NOT_SET: {
break;
}
}
}
void Node::CopyFrom(const Node& from) {
@ -2406,6 +2516,8 @@ void Node::InternalSwap(Node* other) {
swap(_oneof_case_[1], other->_oneof_case_[1]);
swap(ScriptFilenameOrRef_, other->ScriptFilenameOrRef_);
swap(_oneof_case_[2], other->_oneof_case_[2]);
swap(descriptiveTypeNameOrRef_, other->descriptiveTypeNameOrRef_);
swap(_oneof_case_[3], other->_oneof_case_[3]);
swap(_has_bits_[0], other->_has_bits_[0]);
_internal_metadata_.Swap(&other->_internal_metadata_);
swap(_cached_size_, other->_cached_size_);
@ -2938,6 +3050,130 @@ void Node::set_scriptfilenameref(::google::protobuf::uint64 value) {
// @@protoc_insertion_point(field_set:mozilla.devtools.protobuf.Node.scriptFilenameRef)
}
// optional bytes descriptiveTypeName = 12;
bool Node::has_descriptivetypename() const {
return descriptiveTypeNameOrRef_case() == kDescriptiveTypeName;
}
void Node::set_has_descriptivetypename() {
_oneof_case_[3] = kDescriptiveTypeName;
}
void Node::clear_descriptivetypename() {
if (has_descriptivetypename()) {
descriptiveTypeNameOrRef_.descriptivetypename_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_descriptiveTypeNameOrRef();
}
}
const ::std::string& Node::descriptivetypename() const {
// @@protoc_insertion_point(field_get:mozilla.devtools.protobuf.Node.descriptiveTypeName)
if (has_descriptivetypename()) {
return descriptiveTypeNameOrRef_.descriptivetypename_.GetNoArena();
}
return *&::google::protobuf::internal::GetEmptyStringAlreadyInited();
}
void Node::set_descriptivetypename(const ::std::string& value) {
// @@protoc_insertion_point(field_set:mozilla.devtools.protobuf.Node.descriptiveTypeName)
if (!has_descriptivetypename()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
descriptiveTypeNameOrRef_.descriptivetypename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:mozilla.devtools.protobuf.Node.descriptiveTypeName)
}
#if LANG_CXX11
void Node::set_descriptivetypename(::std::string&& value) {
// @@protoc_insertion_point(field_set:mozilla.devtools.protobuf.Node.descriptiveTypeName)
if (!has_descriptivetypename()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
descriptiveTypeNameOrRef_.descriptivetypename_.SetNoArena(
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
// @@protoc_insertion_point(field_set_rvalue:mozilla.devtools.protobuf.Node.descriptiveTypeName)
}
#endif
void Node::set_descriptivetypename(const char* value) {
GOOGLE_DCHECK(value != NULL);
if (!has_descriptivetypename()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
descriptiveTypeNameOrRef_.descriptivetypename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
::std::string(value));
// @@protoc_insertion_point(field_set_char:mozilla.devtools.protobuf.Node.descriptiveTypeName)
}
void Node::set_descriptivetypename(const void* value, size_t size) {
if (!has_descriptivetypename()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
descriptiveTypeNameOrRef_.descriptivetypename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:mozilla.devtools.protobuf.Node.descriptiveTypeName)
}
::std::string* Node::mutable_descriptivetypename() {
if (!has_descriptivetypename()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
// @@protoc_insertion_point(field_mutable:mozilla.devtools.protobuf.Node.descriptiveTypeName)
return descriptiveTypeNameOrRef_.descriptivetypename_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Node::release_descriptivetypename() {
// @@protoc_insertion_point(field_release:mozilla.devtools.protobuf.Node.descriptiveTypeName)
if (has_descriptivetypename()) {
clear_has_descriptiveTypeNameOrRef();
return descriptiveTypeNameOrRef_.descriptivetypename_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
} else {
return NULL;
}
}
void Node::set_allocated_descriptivetypename(::std::string* descriptivetypename) {
if (!has_descriptivetypename()) {
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
clear_descriptiveTypeNameOrRef();
if (descriptivetypename != NULL) {
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
descriptivetypename);
}
// @@protoc_insertion_point(field_set_allocated:mozilla.devtools.protobuf.Node.descriptiveTypeName)
}
// optional uint64 descriptiveTypeNameRef = 13;
bool Node::has_descriptivetypenameref() const {
return descriptiveTypeNameOrRef_case() == kDescriptiveTypeNameRef;
}
void Node::set_has_descriptivetypenameref() {
_oneof_case_[3] = kDescriptiveTypeNameRef;
}
void Node::clear_descriptivetypenameref() {
if (has_descriptivetypenameref()) {
descriptiveTypeNameOrRef_.descriptivetypenameref_ = GOOGLE_ULONGLONG(0);
clear_has_descriptiveTypeNameOrRef();
}
}
::google::protobuf::uint64 Node::descriptivetypenameref() const {
// @@protoc_insertion_point(field_get:mozilla.devtools.protobuf.Node.descriptiveTypeNameRef)
if (has_descriptivetypenameref()) {
return descriptiveTypeNameOrRef_.descriptivetypenameref_;
}
return GOOGLE_ULONGLONG(0);
}
void Node::set_descriptivetypenameref(::google::protobuf::uint64 value) {
if (!has_descriptivetypenameref()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypenameref();
}
descriptiveTypeNameOrRef_.descriptivetypenameref_ = value;
// @@protoc_insertion_point(field_set:mozilla.devtools.protobuf.Node.descriptiveTypeNameRef)
}
bool Node::has_TypeNameOrRef() const {
return TypeNameOrRef_case() != TYPENAMEORREF_NOT_SET;
}
@ -2956,6 +3192,12 @@ bool Node::has_ScriptFilenameOrRef() const {
void Node::clear_has_ScriptFilenameOrRef() {
_oneof_case_[2] = SCRIPTFILENAMEORREF_NOT_SET;
}
bool Node::has_descriptiveTypeNameOrRef() const {
return descriptiveTypeNameOrRef_case() != DESCRIPTIVETYPENAMEORREF_NOT_SET;
}
void Node::clear_has_descriptiveTypeNameOrRef() {
_oneof_case_[3] = DESCRIPTIVETYPENAMEORREF_NOT_SET;
}
Node::TypeNameOrRefCase Node::TypeNameOrRef_case() const {
return Node::TypeNameOrRefCase(_oneof_case_[0]);
}
@ -2965,6 +3207,9 @@ Node::JSObjectClassNameOrRefCase Node::JSObjectClassNameOrRef_case() const {
Node::ScriptFilenameOrRefCase Node::ScriptFilenameOrRef_case() const {
return Node::ScriptFilenameOrRefCase(_oneof_case_[2]);
}
Node::DescriptiveTypeNameOrRefCase Node::descriptiveTypeNameOrRef_case() const {
return Node::DescriptiveTypeNameOrRefCase(_oneof_case_[3]);
}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================

View File

@ -605,6 +605,12 @@ class Node : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(
SCRIPTFILENAMEORREF_NOT_SET = 0,
};
enum DescriptiveTypeNameOrRefCase {
kDescriptiveTypeName = 12,
kDescriptiveTypeNameRef = 13,
DESCRIPTIVETYPENAMEORREF_NOT_SET = 0,
};
static inline const Node* internal_default_instance() {
return reinterpret_cast<const Node*>(
&_Node_default_instance_);
@ -764,9 +770,32 @@ class Node : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(
::google::protobuf::uint64 scriptfilenameref() const;
void set_scriptfilenameref(::google::protobuf::uint64 value);
// optional bytes descriptiveTypeName = 12;
bool has_descriptivetypename() const;
void clear_descriptivetypename();
static const int kDescriptiveTypeNameFieldNumber = 12;
const ::std::string& descriptivetypename() const;
void set_descriptivetypename(const ::std::string& value);
#if LANG_CXX11
void set_descriptivetypename(::std::string&& value);
#endif
void set_descriptivetypename(const char* value);
void set_descriptivetypename(const void* value, size_t size);
::std::string* mutable_descriptivetypename();
::std::string* release_descriptivetypename();
void set_allocated_descriptivetypename(::std::string* descriptivetypename);
// optional uint64 descriptiveTypeNameRef = 13;
bool has_descriptivetypenameref() const;
void clear_descriptivetypenameref();
static const int kDescriptiveTypeNameRefFieldNumber = 13;
::google::protobuf::uint64 descriptivetypenameref() const;
void set_descriptivetypenameref(::google::protobuf::uint64 value);
TypeNameOrRefCase TypeNameOrRef_case() const;
JSObjectClassNameOrRefCase JSObjectClassNameOrRef_case() const;
ScriptFilenameOrRefCase ScriptFilenameOrRef_case() const;
DescriptiveTypeNameOrRefCase descriptiveTypeNameOrRef_case() const;
// @@protoc_insertion_point(class_scope:mozilla.devtools.protobuf.Node)
private:
void set_has_id();
@ -783,6 +812,8 @@ class Node : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(
void clear_has_coarsetype();
void set_has_scriptfilename();
void set_has_scriptfilenameref();
void set_has_descriptivetypename();
void set_has_descriptivetypenameref();
inline bool has_TypeNameOrRef() const;
void clear_TypeNameOrRef();
@ -796,6 +827,10 @@ class Node : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(
void clear_ScriptFilenameOrRef();
inline void clear_has_ScriptFilenameOrRef();
inline bool has_descriptiveTypeNameOrRef() const;
void clear_descriptiveTypeNameOrRef();
inline void clear_has_descriptiveTypeNameOrRef();
::google::protobuf::internal::InternalMetadataWithArenaLite _internal_metadata_;
::google::protobuf::internal::HasBits<1> _has_bits_;
mutable int _cached_size_;
@ -819,7 +854,12 @@ class Node : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(
::google::protobuf::internal::ArenaStringPtr scriptfilename_;
::google::protobuf::uint64 scriptfilenameref_;
} ScriptFilenameOrRef_;
::google::protobuf::uint32 _oneof_case_[3];
union DescriptiveTypeNameOrRefUnion {
DescriptiveTypeNameOrRefUnion() {}
::google::protobuf::internal::ArenaStringPtr descriptivetypename_;
::google::protobuf::uint64 descriptivetypenameref_;
} descriptiveTypeNameOrRef_;
::google::protobuf::uint32 _oneof_case_[4];
friend struct protobuf_CoreDump_2eproto::TableStruct;
};
@ -2057,6 +2097,130 @@ inline void Node::set_scriptfilenameref(::google::protobuf::uint64 value) {
// @@protoc_insertion_point(field_set:mozilla.devtools.protobuf.Node.scriptFilenameRef)
}
// optional bytes descriptiveTypeName = 12;
inline bool Node::has_descriptivetypename() const {
return descriptiveTypeNameOrRef_case() == kDescriptiveTypeName;
}
inline void Node::set_has_descriptivetypename() {
_oneof_case_[3] = kDescriptiveTypeName;
}
inline void Node::clear_descriptivetypename() {
if (has_descriptivetypename()) {
descriptiveTypeNameOrRef_.descriptivetypename_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_descriptiveTypeNameOrRef();
}
}
inline const ::std::string& Node::descriptivetypename() const {
// @@protoc_insertion_point(field_get:mozilla.devtools.protobuf.Node.descriptiveTypeName)
if (has_descriptivetypename()) {
return descriptiveTypeNameOrRef_.descriptivetypename_.GetNoArena();
}
return *&::google::protobuf::internal::GetEmptyStringAlreadyInited();
}
inline void Node::set_descriptivetypename(const ::std::string& value) {
// @@protoc_insertion_point(field_set:mozilla.devtools.protobuf.Node.descriptiveTypeName)
if (!has_descriptivetypename()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
descriptiveTypeNameOrRef_.descriptivetypename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:mozilla.devtools.protobuf.Node.descriptiveTypeName)
}
#if LANG_CXX11
inline void Node::set_descriptivetypename(::std::string&& value) {
// @@protoc_insertion_point(field_set:mozilla.devtools.protobuf.Node.descriptiveTypeName)
if (!has_descriptivetypename()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
descriptiveTypeNameOrRef_.descriptivetypename_.SetNoArena(
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
// @@protoc_insertion_point(field_set_rvalue:mozilla.devtools.protobuf.Node.descriptiveTypeName)
}
#endif
inline void Node::set_descriptivetypename(const char* value) {
GOOGLE_DCHECK(value != NULL);
if (!has_descriptivetypename()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
descriptiveTypeNameOrRef_.descriptivetypename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
::std::string(value));
// @@protoc_insertion_point(field_set_char:mozilla.devtools.protobuf.Node.descriptiveTypeName)
}
inline void Node::set_descriptivetypename(const void* value, size_t size) {
if (!has_descriptivetypename()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
descriptiveTypeNameOrRef_.descriptivetypename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:mozilla.devtools.protobuf.Node.descriptiveTypeName)
}
inline ::std::string* Node::mutable_descriptivetypename() {
if (!has_descriptivetypename()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
// @@protoc_insertion_point(field_mutable:mozilla.devtools.protobuf.Node.descriptiveTypeName)
return descriptiveTypeNameOrRef_.descriptivetypename_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Node::release_descriptivetypename() {
// @@protoc_insertion_point(field_release:mozilla.devtools.protobuf.Node.descriptiveTypeName)
if (has_descriptivetypename()) {
clear_has_descriptiveTypeNameOrRef();
return descriptiveTypeNameOrRef_.descriptivetypename_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
} else {
return NULL;
}
}
inline void Node::set_allocated_descriptivetypename(::std::string* descriptivetypename) {
if (!has_descriptivetypename()) {
descriptiveTypeNameOrRef_.descriptivetypename_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
clear_descriptiveTypeNameOrRef();
if (descriptivetypename != NULL) {
set_has_descriptivetypename();
descriptiveTypeNameOrRef_.descriptivetypename_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
descriptivetypename);
}
// @@protoc_insertion_point(field_set_allocated:mozilla.devtools.protobuf.Node.descriptiveTypeName)
}
// optional uint64 descriptiveTypeNameRef = 13;
inline bool Node::has_descriptivetypenameref() const {
return descriptiveTypeNameOrRef_case() == kDescriptiveTypeNameRef;
}
inline void Node::set_has_descriptivetypenameref() {
_oneof_case_[3] = kDescriptiveTypeNameRef;
}
inline void Node::clear_descriptivetypenameref() {
if (has_descriptivetypenameref()) {
descriptiveTypeNameOrRef_.descriptivetypenameref_ = GOOGLE_ULONGLONG(0);
clear_has_descriptiveTypeNameOrRef();
}
}
inline ::google::protobuf::uint64 Node::descriptivetypenameref() const {
// @@protoc_insertion_point(field_get:mozilla.devtools.protobuf.Node.descriptiveTypeNameRef)
if (has_descriptivetypenameref()) {
return descriptiveTypeNameOrRef_.descriptivetypenameref_;
}
return GOOGLE_ULONGLONG(0);
}
inline void Node::set_descriptivetypenameref(::google::protobuf::uint64 value) {
if (!has_descriptivetypenameref()) {
clear_descriptiveTypeNameOrRef();
set_has_descriptivetypenameref();
}
descriptiveTypeNameOrRef_.descriptivetypenameref_ = value;
// @@protoc_insertion_point(field_set:mozilla.devtools.protobuf.Node.descriptiveTypeNameRef)
}
inline bool Node::has_TypeNameOrRef() const {
return TypeNameOrRef_case() != TYPENAMEORREF_NOT_SET;
}
@ -2075,6 +2239,12 @@ inline bool Node::has_ScriptFilenameOrRef() const {
inline void Node::clear_has_ScriptFilenameOrRef() {
_oneof_case_[2] = SCRIPTFILENAMEORREF_NOT_SET;
}
inline bool Node::has_descriptiveTypeNameOrRef() const {
return descriptiveTypeNameOrRef_case() != DESCRIPTIVETYPENAMEORREF_NOT_SET;
}
inline void Node::clear_has_descriptiveTypeNameOrRef() {
_oneof_case_[3] = DESCRIPTIVETYPENAMEORREF_NOT_SET;
}
inline Node::TypeNameOrRefCase Node::TypeNameOrRef_case() const {
return Node::TypeNameOrRefCase(_oneof_case_[0]);
}
@ -2084,6 +2254,9 @@ inline Node::JSObjectClassNameOrRefCase Node::JSObjectClassNameOrRef_case() cons
inline Node::ScriptFilenameOrRefCase Node::ScriptFilenameOrRef_case() const {
return Node::ScriptFilenameOrRefCase(_oneof_case_[2]);
}
inline Node::DescriptiveTypeNameOrRefCase Node::descriptiveTypeNameOrRef_case() const {
return Node::DescriptiveTypeNameOrRefCase(_oneof_case_[3]);
}
// -------------------------------------------------------------------
// Edge

View File

@ -106,31 +106,37 @@ message StackFrame {
// A serialized version of `JS::ubi::Node` and its outgoing edges.
message Node {
optional uint64 id = 1;
optional uint64 id = 1;
// De-duplicated two-byte string.
oneof TypeNameOrRef {
bytes typeName = 2;
uint64 typeNameRef = 3;
bytes typeName = 2;
uint64 typeNameRef = 3;
}
optional uint64 size = 4;
repeated Edge edges = 5;
optional StackFrame allocationStack = 6;
optional uint64 size = 4;
repeated Edge edges = 5;
optional StackFrame allocationStack = 6;
// De-duplicated one-byte string.
oneof JSObjectClassNameOrRef {
bytes jsObjectClassName = 7;
uint64 jsObjectClassNameRef = 8;
bytes jsObjectClassName = 7;
uint64 jsObjectClassNameRef = 8;
}
// JS::ubi::CoarseType. Defaults to Other.
optional uint32 coarseType = 9 [default = 0];
optional uint32 coarseType = 9 [default = 0];
// De-duplicated one-byte string.
oneof ScriptFilenameOrRef {
bytes scriptFilename = 10;
uint64 scriptFilenameRef = 11;
bytes scriptFilename = 10;
uint64 scriptFilenameRef = 11;
}
// De-duplicated one-byte string.
oneof descriptiveTypeNameOrRef {
bytes descriptiveTypeName = 12;
uint64 descriptiveTypeNameRef = 13;
}
}

View File

@ -70,6 +70,8 @@ struct DeserializedNode {
const char* jsObjectClassName;
// A borrowed reference to a string owned by this node's owning HeapSnapshot.
const char* scriptFilename;
// A borrowed reference to a string owned by this node's owning HeapSnapshot.
const char16_t* descriptiveTypeName;
// A weak pointer to this node's owning `HeapSnapshot`. Safe without
// AddRef'ing because this node's lifetime is equal to that of its owner.
HeapSnapshot* owner;
@ -82,6 +84,7 @@ struct DeserializedNode {
const Maybe<StackFrameId>& allocationStack,
const char* className,
const char* filename,
const char16_t* descriptiveName,
HeapSnapshot& owner)
: id(id)
, coarseType(coarseType)
@ -91,6 +94,7 @@ struct DeserializedNode {
, allocationStack(allocationStack)
, jsObjectClassName(className)
, scriptFilename(filename)
, descriptiveTypeName(descriptiveName)
, owner(&owner)
{ }
virtual ~DeserializedNode() { }
@ -104,6 +108,7 @@ struct DeserializedNode {
, allocationStack(rhs.allocationStack)
, jsObjectClassName(rhs.jsObjectClassName)
, scriptFilename(rhs.scriptFilename)
, descriptiveTypeName(rhs.descriptiveTypeName)
, owner(rhs.owner)
{ }
@ -132,6 +137,7 @@ protected:
, allocationStack(Nothing())
, jsObjectClassName(nullptr)
, scriptFilename(nullptr)
, descriptiveTypeName(nullptr)
, owner(nullptr)
{ }
@ -259,6 +265,7 @@ public:
Node::Size size(mozilla::MallocSizeOf mallocSizeof) const override;
const char* jsObjectClassName() const override { return get().jsObjectClassName; }
const char* scriptFilename() const final { return get().scriptFilename; }
const char16_t* descriptiveTypeName() const override { return get().descriptiveTypeName; }
bool hasAllocationStack() const override { return get().allocationStack.isSome(); }
StackFrame allocationStack() const override;

View File

@ -284,11 +284,21 @@ HeapSnapshot::saveNode(const protobuf::Node& node, NodeIdSet& edgeReferents)
return false;
}
const char16_t* descriptiveTypeName = nullptr;
if (node.descriptiveTypeNameOrRef_case() != protobuf::Node::DESCRIPTIVETYPENAMEORREF_NOT_SET) {
Maybe<StringOrRef> descriptiveTypeNameOrRef = GET_STRING_OR_REF(node, descriptivetypename);
descriptiveTypeName = getOrInternString<char16_t>(internedTwoByteStrings, descriptiveTypeNameOrRef);
if (NS_WARN_IF(!descriptiveTypeName))
return false;
}
if (NS_WARN_IF(!nodes.putNew(id, DeserializedNode(id, coarseType, typeName,
size, std::move(edges),
allocationStack,
jsObjectClassName,
scriptFilename, *this))))
scriptFilename,
descriptiveTypeName,
*this))))
{
return false;
};
@ -1340,6 +1350,16 @@ public:
}
}
if (ubiNode.descriptiveTypeName()) {
auto descriptiveTypeName = TwoByteString(ubiNode.descriptiveTypeName());
if (NS_WARN_IF(!attachTwoByteString(descriptiveTypeName,
[&] (std::string* name) { protobufNode.set_allocated_descriptivetypename(name); },
[&] (uint64_t ref) { protobufNode.set_descriptivetypenameref(ref); })))
{
return false;
}
}
return writeMessage(protobufNode);
}
};

View File

@ -23,6 +23,10 @@ const breakdown = {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
domNode: {
by: "descriptiveType",
then: { by: "count", count: true, bytes: true },
},
};
const description = {
@ -32,7 +36,8 @@ const description = {
},
strings: {},
scripts: {},
other: {}
other: {},
domNode: {}
};
const expected = [

View File

@ -23,6 +23,10 @@ const breakdown = {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
domNode: {
by: "descriptiveType",
then: { by: "count", count: true, bytes: true },
},
};
const description = {
@ -31,7 +35,8 @@ const description = {
},
strings: {},
scripts: {},
other: {}
other: {},
domNode: {}
};
const expected = [

View File

@ -23,6 +23,10 @@ const breakdown = {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
domNode: {
by: "descriptiveType",
then: { by: "count", count: true, bytes: true },
},
};
const description = {
@ -33,7 +37,8 @@ const description = {
"JSString": { count: 1, bytes: 42 },
},
scripts: {},
other: {}
other: {},
domNode: {}
};
const expected = [

View File

@ -27,6 +27,10 @@ const breakdown = {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
domNode: {
by: "descriptiveType",
then: { by: "count", count: true, bytes: true },
},
};
const stack = saveStack();
@ -38,7 +42,8 @@ const description = {
},
strings: {},
scripts: {},
other: {}
other: {},
domNode: {}
};
const expected = [

View File

@ -38,7 +38,8 @@ const mockSnapshot = {
objects: { count: 0, bytes: 0 },
strings: { count: 0, bytes: 0 },
scripts: { count: 0, bytes: 0 },
other: { SomeType: { count: 1, bytes: 10 } }
other: { SomeType: { count: 1, bytes: 10 } },
domNode: { count: 0, bytes: 0 },
})
};
@ -51,6 +52,7 @@ const breakdown = {
by: "internalType",
then: { by: "count", count: true, bytes: true }
},
domNode: { by: "count", count: true, bytes: true },
};
const expected = {

View File

@ -10,6 +10,7 @@ const breakdown = {
scripts: { by: "count", count: true, bytes: true },
strings: { by: "count", count: true, bytes: true },
other: { by: "count", count: true, bytes: true },
domNode: { by: "count", count: true, bytes: true },
};
async function createSnapshotAndDominatorTree(client) {

View File

@ -12,6 +12,7 @@ const CENSUS_BREAKDOWN = {
strings: COUNT,
scripts: COUNT,
other: COUNT,
domNode: COUNT,
};
const LABEL_BREAKDOWN = {

View File

@ -10,6 +10,7 @@ const breakdown = {
scripts: { by: "count", count: true, bytes: true },
strings: { by: "count", count: true, bytes: true },
other: { by: "count", count: true, bytes: true },
domNode: { by: "count", count: true, bytes: true },
};
add_task(async function() {

View File

@ -10,6 +10,7 @@ const breakdown = {
scripts: { by: "count", count: true, bytes: true },
strings: { by: "count", count: true, bytes: true },
other: { by: "count", count: true, bytes: true },
domNode: { by: "count", count: true, bytes: true },
};
add_task(async function() {

View File

@ -24,6 +24,10 @@ const BREAKDOWN = {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
domNode: {
by: "descriptiveType",
then: { by: "count", count: true, bytes: true },
},
};
add_task(async function() {

View File

@ -24,6 +24,10 @@ const BREAKDOWN = {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
domNode: {
by: "descriptiveType",
then: { by: "count", count: true, bytes: true },
},
};
add_task(async function() {

View File

@ -14,6 +14,7 @@ const BREAKDOWN = {
strings: countBreakdown,
scripts: countBreakdown,
other: { by: "internalType", then: countBreakdown },
domNode: countBreakdown,
};
const REPORT = {
@ -27,6 +28,7 @@ const REPORT = {
"js::Shape": { bytes: 30, count: 3 },
"js::Shape2": { bytes: 40, count: 4 }
},
"domNode": { bytes: 0, count: 0 }
};
const EXPECTED = {

View File

@ -26,6 +26,10 @@ function run_test() {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
domNode: {
by: "descriptiveType",
then: { by: "count", count: true, bytes: true },
}
};
const REPORT = {
@ -41,7 +45,8 @@ function run_test() {
},
other: {
"js::Shape": { bytes: 80, count: 8 },
}
},
domNode: { }
};
const EXPECTED = {
@ -72,18 +77,18 @@ function run_test() {
count: 0,
totalCount: 22,
children: undefined,
id: 14,
parent: 13,
id: 15,
parent: 14,
reportLeafIndex: undefined,
}
],
id: 13,
parent: 12,
id: 14,
parent: 13,
reportLeafIndex: undefined,
}
],
id: 12,
parent: 11,
id: 13,
parent: 12,
reportLeafIndex: 9,
},
{
@ -107,18 +112,18 @@ function run_test() {
count: 0,
totalCount: 22,
children: undefined,
id: 17,
parent: 16,
id: 18,
parent: 17,
reportLeafIndex: undefined,
}
],
id: 16,
parent: 15,
id: 17,
parent: 16,
reportLeafIndex: undefined,
}
],
id: 15,
parent: 11,
id: 16,
parent: 12,
reportLeafIndex: 7,
},
{
@ -142,18 +147,18 @@ function run_test() {
count: 0,
totalCount: 22,
children: undefined,
id: 20,
parent: 19,
id: 21,
parent: 20,
reportLeafIndex: undefined,
}
],
id: 19,
parent: 18,
id: 20,
parent: 19,
reportLeafIndex: undefined,
}
],
id: 18,
parent: 11,
id: 19,
parent: 12,
reportLeafIndex: 2,
},
{
@ -177,22 +182,22 @@ function run_test() {
count: 0,
totalCount: 22,
children: undefined,
id: 23,
parent: 22,
id: 24,
parent: 23,
reportLeafIndex: undefined,
}
],
id: 22,
parent: 21,
id: 23,
parent: 22,
reportLeafIndex: undefined,
}
],
id: 21,
parent: 11,
id: 22,
parent: 12,
reportLeafIndex: 5,
},
],
id: 11,
id: 12,
parent: undefined,
reportLeafIndex: undefined,
};

View File

@ -20,6 +20,7 @@ function run_test() {
},
strings: { by: "count", count: true, bytes: true },
scripts: { by: "count", count: true, bytes: true },
domNode: { by: "count", count: true, bytes: true },
};
const REPORT = {
@ -31,6 +32,7 @@ function run_test() {
},
strings: { count: 0, bytes: 0 },
scripts: { count: 0, bytes: 0 },
domNode: {count: 0, bytes: 0 },
};
const node = censusReportToCensusTreeNode(BREAKDOWN, REPORT, { invert: true });

View File

@ -10,6 +10,7 @@ const BREAKDOWN = {
scripts: { by: "count", count: true, bytes: true },
strings: { by: "count", count: true, bytes: true },
other: { by: "count", count: true, bytes: true },
domNode: { by: "count", count: true, bytes: true },
};
const REPORT1 = {
@ -29,6 +30,10 @@ const REPORT1 = {
count: 3,
bytes: 30,
},
domNode: {
count: 0,
bytes: 0,
},
};
const REPORT2 = {
@ -48,6 +53,10 @@ const REPORT2 = {
count: 4,
bytes: 40,
},
domNode: {
count: 0,
bytes: 0,
},
};
const EXPECTED = {
@ -67,6 +76,10 @@ const EXPECTED = {
count: 1,
bytes: 10,
},
domNode: {
count: 0,
bytes: 0,
},
};
function run_test() {

View File

@ -31,6 +31,10 @@ const BREAKDOWN = {
by: "internalType",
then: { by: "count", count: false, bytes: true }
},
domNode: {
by: "internalType",
then: { by: "count", count: false, bytes: true }
},
};
const stack1 = saveStack();
@ -59,7 +63,8 @@ const REPORT1 = {
},
other: {
"mozilla::dom::Thing": { bytes: 1 },
}
},
domNode: {}
};
const REPORT2 = {
@ -85,7 +90,8 @@ const REPORT2 = {
},
other: {
"mozilla::dom::OtherThing": { bytes: 1 },
}
},
domNode: {}
};
const EXPECTED = {
@ -130,7 +136,8 @@ const EXPECTED = {
"mozilla::dom::OtherThing": {
"bytes": 1
}
}
},
"domNode": {},
};
function run_test() {

View File

@ -24,6 +24,10 @@ function run_test() {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
domNode: {
by: "descriptiveType",
then: { by: "count", count: true, bytes: true },
},
};
const REPORT = {
@ -41,7 +45,8 @@ function run_test() {
},
other: {
"js::Shape": { bytes: 80, count: 8 },
}
},
domNode: {}
};
const EXPECTED = {
@ -65,8 +70,8 @@ function run_test() {
count: 32,
totalCount: 32,
children: undefined,
id: 15,
parent: 14,
id: 16,
parent: 15,
reportLeafIndex: 4,
},
{
@ -76,8 +81,8 @@ function run_test() {
count: 8,
totalCount: 8,
children: undefined,
id: 16,
parent: 14,
id: 17,
parent: 15,
reportLeafIndex: 3,
},
{
@ -87,17 +92,17 @@ function run_test() {
count: 5,
totalCount: 5,
children: undefined,
id: 17,
parent: 14,
id: 18,
parent: 15,
reportLeafIndex: 2,
}
],
id: 14,
parent: 13,
id: 15,
parent: 14,
reportLeafIndex: undefined,
}
],
id: 13,
id: 14,
parent: undefined,
reportLeafIndex: undefined,
};

View File

@ -24,6 +24,10 @@ function run_test() {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
domNode: {
by: "descriptiveType",
then: { by: "count", count: true, bytes: true },
},
};
const REPORT = {
@ -41,7 +45,8 @@ function run_test() {
},
other: {
"js::Shape": { bytes: 80, count: 8 },
}
},
domNode: {}
};
const EXPECTED = {
@ -51,7 +56,7 @@ function run_test() {
count: 0,
totalCount: 62,
children: undefined,
id: 13,
id: 14,
parent: undefined,
reportLeafIndex: undefined,
};

View File

@ -19,6 +19,7 @@ function run_test() {
noFilename: INTERNAL_TYPE
},
other: INTERNAL_TYPE,
domNode: { by: "descriptiveType", then: COUNT, other: COUNT },
};
const REPORT = {
@ -49,7 +50,8 @@ function run_test() {
count: 1,
bytes: 10
}
}
},
domNode: {}
};
const EXPECTED = {
@ -73,8 +75,8 @@ function run_test() {
totalBytes: 70,
count: 7,
totalCount: 7,
id: 13,
parent: 12,
id: 14,
parent: 13,
children: undefined,
reportLeafIndex: 2,
},
@ -84,18 +86,18 @@ function run_test() {
totalBytes: 60,
count: 6,
totalCount: 6,
id: 14,
parent: 12,
id: 15,
parent: 13,
children: undefined,
reportLeafIndex: 3,
},
],
id: 12,
parent: 11,
id: 13,
parent: 12,
reportLeafIndex: undefined,
}
],
id: 11,
id: 12,
reportLeafIndex: undefined,
};

View File

@ -28,6 +28,10 @@ function run_test() {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
domNode: {
by: "descriptiveType",
then: { by: "count", count: true, bytes: true },
},
};
const REPORT = {
@ -53,6 +57,7 @@ function run_test() {
"js::Shape": { count: 7, bytes: 70 },
"js::BaseShape": { count: 1, bytes: 10 },
},
domNode: { },
};
const root = censusReportToCensusTreeNode(BREAKDOWN, REPORT);

View File

@ -0,0 +1,265 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BrowsingContext.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/Assertions.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Logging.h"
#include "mozilla/StaticPtr.h"
#include "nsDataHashtable.h"
#include "nsRefPtrHashtable.h"
#include "nsIDocShell.h"
#include "nsContentUtils.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace dom {
static LazyLogModule gBrowsingContextLog("BrowsingContext");
static StaticAutoPtr<BrowsingContext::Children> sRootBrowsingContexts;
static StaticAutoPtr<nsDataHashtable<nsUint64HashKey, BrowsingContext*>>
sBrowsingContexts;
// TODO(farre): This duplicates some of the work performed by the
// bfcache. This should be unified. [Bug 1471601]
static StaticAutoPtr<nsRefPtrHashtable<nsUint64HashKey, BrowsingContext>>
sCachedBrowsingContexts;
/* static */ void
BrowsingContext::Init()
{
if (!sRootBrowsingContexts) {
sRootBrowsingContexts = new BrowsingContext::Children();
ClearOnShutdown(&sRootBrowsingContexts);
}
if (!sBrowsingContexts) {
sBrowsingContexts =
new nsDataHashtable<nsUint64HashKey, BrowsingContext*>();
ClearOnShutdown(&sBrowsingContexts);
}
if (!sCachedBrowsingContexts) {
sCachedBrowsingContexts =
new nsRefPtrHashtable<nsUint64HashKey, BrowsingContext>();
ClearOnShutdown(&sCachedBrowsingContexts);
}
}
/* static */ LogModule*
BrowsingContext::GetLog()
{
return gBrowsingContextLog;
}
// TODO(farre): BrowsingContext::CleanupContexts starts from the list
// of root BrowsingContexts. This isn't enough when separate
// BrowsingContext nodes of a BrowsingContext tree not in a crashing
// child process are from that process and thus needs to be
// cleaned. [Bug 1472108]
/* static */ void
BrowsingContext::CleanupContexts(uint64_t aProcessId)
{
if (sRootBrowsingContexts) {
RefPtr<BrowsingContext> context = sRootBrowsingContexts->getFirst();
while (context) {
RefPtr<BrowsingContext> next = context->getNext();
if (context->IsOwnedByProcess() &&
aProcessId == context->OwnerProcessId()) {
context->Detach();
}
context = next;
}
}
}
/* static */ already_AddRefed<BrowsingContext>
BrowsingContext::Get(uint64_t aId)
{
RefPtr<BrowsingContext> abc = sBrowsingContexts->Get(aId);
return abc.forget();
}
BrowsingContext::BrowsingContext(nsIDocShell* aDocShell)
: mBrowsingContextId(nsContentUtils::GenerateBrowsingContextId())
, mProcessId(Nothing())
, mDocShell(aDocShell)
{
sBrowsingContexts->Put(mBrowsingContextId, this);
}
BrowsingContext::BrowsingContext(uint64_t aBrowsingContextId,
const nsAString& aName,
const Maybe<uint64_t>& aProcessId)
: mBrowsingContextId(aBrowsingContextId)
, mProcessId(aProcessId)
, mName(aName)
{
// mProcessId only really has a meaning in the parent process, where
// it keeps track of which BrowsingContext is actually holding the
// nsDocShell.
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || aProcessId.isNothing());
sBrowsingContexts->Put(mBrowsingContextId, this);
}
void
BrowsingContext::Attach(BrowsingContext* aParent)
{
if (isInList()) {
MOZ_LOG(GetLog(),
LogLevel::Debug,
("%s: Connecting already existing 0x%08" PRIx64 " to 0x%08" PRIx64,
XRE_IsParentProcess() ? "Parent" : "Child",
Id(),
aParent ? aParent->Id() : 0));
MOZ_DIAGNOSTIC_ASSERT(sBrowsingContexts->Contains(Id()));
MOZ_DIAGNOSTIC_ASSERT(!IsCached());
return;
}
bool wasCached = sCachedBrowsingContexts->Remove(Id());
MOZ_LOG(GetLog(),
LogLevel::Debug,
("%s: %s 0x%08" PRIx64 " to 0x%08" PRIx64,
wasCached ? "Re-connecting" : "Connecting",
XRE_IsParentProcess() ? "Parent" : "Child",
Id(),
aParent ? aParent->Id() : 0));
auto* children = aParent ? &aParent->mChildren : sRootBrowsingContexts.get();
children->insertBack(this);
mParent = aParent;
if (!XRE_IsContentProcess()) {
return;
}
auto cc = dom::ContentChild::GetSingleton();
MOZ_DIAGNOSTIC_ASSERT(cc);
cc->SendAttachBrowsingContext(
dom::BrowsingContextId(mParent ? mParent->Id() : 0),
dom::BrowsingContextId(Id()),
mName);
}
void
BrowsingContext::Detach()
{
RefPtr<BrowsingContext> kungFuDeathGrip(this);
if (sCachedBrowsingContexts) {
sCachedBrowsingContexts->Remove(Id());
}
if (!isInList()) {
MOZ_LOG(GetLog(),
LogLevel::Debug,
("%s: Detaching already detached 0x%08" PRIx64,
XRE_IsParentProcess() ? "Parent" : "Child",
Id()));
return;
}
MOZ_LOG(GetLog(),
LogLevel::Debug,
("%s: Detaching 0x%08" PRIx64 " from 0x%08" PRIx64,
XRE_IsParentProcess() ? "Parent" : "Child",
Id(),
mParent ? mParent->Id() : 0));
remove();
if (!XRE_IsContentProcess()) {
return;
}
auto cc = dom::ContentChild::GetSingleton();
MOZ_DIAGNOSTIC_ASSERT(cc);
cc->SendDetachBrowsingContext(dom::BrowsingContextId(Id()),
false /* aMoveToBFCache */);
}
void
BrowsingContext::CacheChildren()
{
if (mChildren.isEmpty()) {
return;
}
MOZ_LOG(GetLog(),
LogLevel::Debug,
("%s: Caching children of 0x%08" PRIx64 "",
XRE_IsParentProcess() ? "Parent" : "Child",
Id()));
while (!mChildren.isEmpty()) {
RefPtr<BrowsingContext> child = mChildren.popFirst();
sCachedBrowsingContexts->Put(child->Id(), child);
}
if (!XRE_IsContentProcess()) {
return;
}
auto cc = dom::ContentChild::GetSingleton();
MOZ_DIAGNOSTIC_ASSERT(cc);
cc->SendDetachBrowsingContext(dom::BrowsingContextId(Id()),
true /* aMoveToBFCache */);
}
bool
BrowsingContext::IsCached()
{
return sCachedBrowsingContexts->Contains(Id());
}
uint64_t
BrowsingContext::OwnerProcessId() const
{
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
return mProcessId.value();
}
BrowsingContext::~BrowsingContext()
{
MOZ_DIAGNOSTIC_ASSERT(!isInList());
if (sBrowsingContexts) {
sBrowsingContexts->Remove(mBrowsingContextId);
}
}
static void
ImplCycleCollectionUnlink(BrowsingContext::Children& aField)
{
aField.clear();
}
static void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
BrowsingContext::Children& aField,
const char* aName,
uint32_t aFlags = 0)
{
for (BrowsingContext* aContext : aField) {
aCallback.NoteNativeChild(aContext,
NS_CYCLE_COLLECTION_PARTICIPANT(BrowsingContext));
}
}
NS_IMPL_CYCLE_COLLECTION(BrowsingContext, mDocShell, mChildren)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(BrowsingContext, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(BrowsingContext, Release)
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,109 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef BrowsingContext_h
#define BrowsingContext_h
#include "mozilla/LinkedList.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
#include "mozilla/WeakPtr.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsString.h"
class nsIDocShell;
namespace mozilla {
class LogModule;
namespace dom {
// BrowsingContext, in this context, is the cross process replicated
// environment in which information about documents is stored. In
// particular the tree structure of nested browsing contexts is
// represented by the tree of BrowsingContexts.
//
// The tree of BrowsingContexts in created in step with its
// corresponding nsDocShell, and when nsDocShells are connected
// through a parent/child relationship, so are BrowsingContexts. The
// major difference is that BrowsingContexts are replicated (synced)
// to the parent process, making it possible to traverse the
// BrowsingContext tree for a tab, in both the parent and the child
// process.
class BrowsingContext
: public SupportsWeakPtr<BrowsingContext>
, public LinkedListElement<RefPtr<BrowsingContext>>
{
public:
static void Init();
static LogModule* GetLog();
static void CleanupContexts(uint64_t aProcessId);
static already_AddRefed<BrowsingContext> Get(uint64_t aId);
// Create a new BrowsingContext for 'aDocShell'. The id will be
// generated so that it is unique across all content child processes
// and the content parent process.
explicit BrowsingContext(nsIDocShell* aDocShell);
// Create a BrowsingContext for a particular BrowsingContext id, in
// the case where the id is known beforehand and a nsDocShell isn't
// needed (e.g. when creating BrowsingContexts in the parent
// process).
BrowsingContext(uint64_t aBrowsingContextId,
const nsAString& aName,
const Maybe<uint64_t>& aProcessId = Nothing());
// Attach the current BrowsingContext to its parent, in both the
// child and the parent process. If 'aParent' is null, 'this' is
// taken to be a root BrowsingContext.
void Attach(BrowsingContext* aParent);
// Detach the current BrowsingContext from its parent, in both the
// child and the parent process.
void Detach();
// Remove all children from the current BrowsingContext and cache
// them to allow them to be attached again.
void CacheChildren();
bool IsCached();
void SetName(const nsAString& aName) { mName = aName; }
void GetName(nsAString& aName) { aName = mName; }
bool NameEquals(const nsAString& aName) { return mName.Equals(aName); }
uint64_t Id() const { return mBrowsingContextId; }
uint64_t OwnerProcessId() const;
bool IsOwnedByProcess() const { return mProcessId.isSome(); }
BrowsingContext* Parent() const { return mParent; }
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(BrowsingContext)
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(BrowsingContext)
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(BrowsingContext)
using Children = AutoCleanLinkedList<RefPtr<BrowsingContext>>;
private:
~BrowsingContext();
const uint64_t mBrowsingContextId;
// Indicates which process owns the docshell. Only valid in the
// parent process.
Maybe<uint64_t> mProcessId;
WeakPtr<BrowsingContext> mParent;
Children mChildren;
nsCOMPtr<nsIDocShell> mDocShell;
nsString mName;
};
} // namespace dom
} // namespace mozilla
#endif

View File

@ -77,7 +77,12 @@ EXPORTS.mozilla += [
'LoadContext.h',
]
EXPORTS.mozilla.dom += [
'BrowsingContext.h',
]
UNIFIED_SOURCES += [
'BrowsingContext.cpp',
'LoadContext.cpp',
'nsAboutRedirector.cpp',
'nsDefaultURIFixup.cpp',

View File

@ -475,6 +475,8 @@ nsDocShell::Init()
rv = nsDocLoader::AddDocLoaderAsChildOfRoot(this);
NS_ENSURE_SUCCESS(rv, rv);
mBrowsingContext = new BrowsingContext(this);
// Add as |this| a progress listener to itself. A little weird, but
// simpler than reproducing all the listener-notification logic in
// overrides of the various methods via which nsDocLoader can be
@ -505,7 +507,8 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(nsDocShell,
mSessionStorageManager,
mScriptGlobal,
mInitialClientSource,
mSessionHistory)
mSessionHistory,
mBrowsingContext)
NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader)
NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader)
@ -2539,14 +2542,14 @@ nsDocShell::NotifyScrollObservers()
NS_IMETHODIMP
nsDocShell::GetName(nsAString& aName)
{
aName = mName;
mBrowsingContext->GetName(aName);
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetName(const nsAString& aName)
{
mName = aName;
mBrowsingContext->SetName(aName);
return NS_OK;
}
@ -2554,7 +2557,7 @@ NS_IMETHODIMP
nsDocShell::NameEquals(const nsAString& aName, bool* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = mName.Equals(aName);
*aResult = mBrowsingContext->NameEquals(aName);
return NS_OK;
}
@ -2851,6 +2854,7 @@ nsDocShell::SetDocLoaderParent(nsDocLoader* aParent)
bool value;
nsString customUserAgent;
nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent));
if (parentAsDocShell) {
if (mAllowPlugins && NS_SUCCEEDED(parentAsDocShell->GetAllowPlugins(&value))) {
SetAllowPlugins(value);
@ -3259,7 +3263,7 @@ nsDocShell::DoFindItemWithName(const nsAString& aName,
nsIDocShellTreeItem** aResult)
{
// First we check our name.
if (mName.Equals(aName) && ItemIsActive(this) &&
if (mBrowsingContext->NameEquals(aName) && ItemIsActive(this) &&
CanAccessItem(this, aOriginalRequestor)) {
NS_ADDREF(*aResult = this);
return NS_OK;
@ -3550,6 +3554,8 @@ nsDocShell::AddChild(nsIDocShellTreeItem* aChild)
return NS_OK;
}
childAsDocShell->AttachBrowsingContext(this);
// charset, style-disabling, and zoom will be inherited in SetupNewViewer()
// Now take this document's charset and set the child's parentCharset field
@ -3612,6 +3618,11 @@ nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild)
nsresult rv = RemoveChildLoader(childAsDocLoader);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
if (childAsDocShell) {
childAsDocShell->DetachBrowsingContext();
}
aChild->SetTreeOwner(nullptr);
return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader);
@ -5290,6 +5301,8 @@ nsDocShell::Destroy()
mSessionHistory = nullptr;
}
mBrowsingContext->Detach();
SetTreeOwner(nullptr);
mOnePermittedSandboxedNavigator = nullptr;
@ -7750,6 +7763,8 @@ nsDocShell::CaptureState()
mOSHE->AddChildShell(childShell);
}
mBrowsingContext->CacheChildren();
return NS_OK;
}
@ -14223,3 +14238,31 @@ nsDocShell::IsForceReloading()
{
return IsForceReloadType(mLoadType);
}
already_AddRefed<BrowsingContext>
nsDocShell::GetBrowsingContext() const
{
RefPtr<BrowsingContext> browsingContext = mBrowsingContext;
return browsingContext.forget();
}
void
nsIDocShell::AttachBrowsingContext(nsIDocShell* aParentDocShell)
{
RefPtr<BrowsingContext> childContext =
nsDocShell::Cast(this)->GetBrowsingContext();
RefPtr<BrowsingContext> parentContext;
if (aParentDocShell) {
parentContext =
nsDocShell::Cast(aParentDocShell)->GetBrowsingContext();
}
childContext->Attach(parentContext);
}
void
nsIDocShell::DetachBrowsingContext()
{
RefPtr<BrowsingContext> browsingContext =
nsDocShell::Cast(this)->GetBrowsingContext();
browsingContext->Detach();
}

View File

@ -15,6 +15,7 @@
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
#include "mozilla/gfx/Matrix.h"
#include "mozilla/dom/ChildSHistory.h"
@ -379,6 +380,9 @@ public:
// shift while triggering reload)
bool IsForceReloading();
already_AddRefed<mozilla::dom::BrowsingContext>
GetBrowsingContext() const;
private: // member functions
friend class nsDSURIContentListener;
friend class FramingChecker;
@ -907,7 +911,6 @@ private: // data members
#endif /* DEBUG */
nsID mHistoryID;
nsString mName;
nsString mTitle;
nsString mCustomUserAgent;
nsCString mOriginalUriString;
@ -932,6 +935,7 @@ private: // data members
RefPtr<mozilla::dom::ChildSHistory> mSessionHistory;
nsCOMPtr<nsIWebBrowserFind> mFind;
nsCOMPtr<nsICommandManager> mCommandManager;
RefPtr<mozilla::dom::BrowsingContext> mBrowsingContext;
// Dimensions of the docshell
nsIntRect mBounds;

View File

@ -22,6 +22,7 @@ namespace mozilla {
class Encoding;
class HTMLEditor;
namespace dom {
class BrowsingContext;
class ClientSource;
} // namespace dom
}
@ -1180,6 +1181,9 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
mozilla::HTMLEditor* GetHTMLEditor();
nsresult SetHTMLEditor(mozilla::HTMLEditor* aHTMLEditor);
void AttachBrowsingContext(nsIDocShell* aParentDocShell);
void DetachBrowsingContext();
%}
/**

View File

@ -7,6 +7,8 @@
#include "mozilla/ModuleUtils.h"
#include "nsDocShellCID.h"
#include "mozilla/dom/BrowsingContext.h"
#include "nsDocShell.h"
#include "nsDefaultURIFixup.h"
#include "nsWebNavigationInfo.h"
@ -53,6 +55,7 @@ Initialize()
}
gInitialized = true;
mozilla::dom::BrowsingContext::Init();
nsresult rv = nsSHistory::Startup();
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -1178,24 +1178,18 @@ Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
CallerType aCallerType,
ErrorResult& aRv)
{
CallbackObjectHolder<NavigatorUserMediaSuccessCallback,
nsIDOMGetUserMediaSuccessCallback> holder1(&aOnSuccess);
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onsuccess =
holder1.ToXPCOMCallback();
CallbackObjectHolder<NavigatorUserMediaErrorCallback,
nsIDOMGetUserMediaErrorCallback> holder2(&aOnError);
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback();
if (!mWindow || !mWindow->GetOuterWindow() ||
mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
return;
}
MediaManager::GetUserMediaSuccessCallback onsuccess(&aOnSuccess);
MediaManager::GetUserMediaErrorCallback onerror(&aOnError);
MediaManager* manager = MediaManager::Get();
aRv = manager->GetUserMedia(mWindow, aConstraints, onsuccess, onerror,
aCallerType);
aRv = manager->GetUserMedia(mWindow, aConstraints, std::move(onsuccess),
std::move(onerror), aCallerType);
}
void
@ -1206,15 +1200,6 @@ Navigator::MozGetUserMediaDevices(const MediaStreamConstraints& aConstraints,
const nsAString& aCallID,
ErrorResult& aRv)
{
CallbackObjectHolder<MozGetUserMediaDevicesSuccessCallback,
nsIGetUserMediaDevicesSuccessCallback> holder1(&aOnSuccess);
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onsuccess =
holder1.ToXPCOMCallback();
CallbackObjectHolder<NavigatorUserMediaErrorCallback,
nsIDOMGetUserMediaErrorCallback> holder2(&aOnError);
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback();
if (!mWindow || !mWindow->GetOuterWindow() ||
mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
@ -1222,7 +1207,8 @@ Navigator::MozGetUserMediaDevices(const MediaStreamConstraints& aConstraints,
}
MediaManager* manager = MediaManager::Get();
aRv = manager->GetUserMediaDevices(mWindow, aConstraints, onsuccess, onerror,
// XXXbz aOnError seems to be unused?
aRv = manager->GetUserMediaDevices(mWindow, aConstraints, aOnSuccess,
aInnerWindowID, aCallID);
}

View File

@ -64,6 +64,12 @@ JS::ubi::Concrete<nsINode>::size(mozilla::MallocSizeOf mallocSizeOf) const
return n;
}
const char16_t*
JS::ubi::Concrete<nsINode>::descriptiveTypeName() const
{
return get().NodeName().get();
}
JS::ubi::Node::Size
JS::ubi::Concrete<nsIDocument>::size(mozilla::MallocSizeOf mallocSizeOf) const
{

View File

@ -36,7 +36,8 @@ public:
js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
nsINode& get() const { return *static_cast<nsINode*>(ptr); }
CoarseType coarseType() const final { return CoarseType::Other; }
CoarseType coarseType() const final { return CoarseType::DOMNode; }
const char16_t* descriptiveTypeName() const override;
};
template<>

View File

@ -10800,13 +10800,11 @@ nsContentUtils::IsLocalRefURL(const nsACString& aString)
return ::IsLocalRefURL(aString);
}
// Tab ID is composed in a similar manner of Window ID.
static uint64_t gNextTabId = 0;
static const uint64_t kTabIdProcessBits = 32;
static const uint64_t kTabIdTabBits = 64 - kTabIdProcessBits;
static const uint64_t kIdProcessBits = 32;
static const uint64_t kIdBits = 64 - kIdProcessBits;
/* static */ uint64_t
nsContentUtils::GenerateTabId()
GenerateProcessSpecificId(uint64_t aId)
{
uint64_t processId = 0;
if (XRE_IsContentProcess()) {
@ -10814,14 +10812,32 @@ nsContentUtils::GenerateTabId()
processId = cc->GetID();
}
MOZ_RELEASE_ASSERT(processId < (uint64_t(1) << kTabIdProcessBits));
uint64_t processBits = processId & ((uint64_t(1) << kTabIdProcessBits) - 1);
MOZ_RELEASE_ASSERT(processId < (uint64_t(1) << kIdProcessBits));
uint64_t processBits = processId & ((uint64_t(1) << kIdProcessBits) - 1);
uint64_t tabId = ++gNextTabId;
MOZ_RELEASE_ASSERT(tabId < (uint64_t(1) << kTabIdTabBits));
uint64_t tabBits = tabId & ((uint64_t(1) << kTabIdTabBits) - 1);
uint64_t id = aId;
MOZ_RELEASE_ASSERT(id < (uint64_t(1) << kIdBits));
uint64_t bits = id & ((uint64_t(1) << kIdBits) - 1);
return (processBits << kTabIdTabBits) | tabBits;
return (processBits << kIdBits) | bits;
}
// Tab ID is composed in a similar manner of Window ID.
static uint64_t gNextTabId = 0;
/* static */ uint64_t
nsContentUtils::GenerateTabId()
{
return GenerateProcessSpecificId(++gNextTabId);
}
// Browsing context ID is composed in a similar manner of Window ID.
static uint64_t gNextBrowsingContextId = 0;
/* static */ uint64_t
nsContentUtils::GenerateBrowsingContextId()
{
return GenerateProcessSpecificId(++gNextBrowsingContextId);
}
/* static */ bool

View File

@ -3166,6 +3166,12 @@ public:
*/
static uint64_t GenerateTabId();
/**
* Generate an id for a BrowsingContext using a range of serial
* numbers reserved for the current process.
*/
static uint64_t GenerateBrowsingContextId();
/**
* Check whether we should skip moving the cursor for a same-value .value set
* on a text input or textarea.

View File

@ -689,6 +689,8 @@ nsFrameLoader::AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
// Now that we have our type set, add ourselves to the parent, as needed.
if (aParentNode) {
aParentNode->AddChild(aItem);
} else if (nsCOMPtr<nsIDocShell> childAsDocShell = do_QueryInterface(aItem)) {
childAsDocShell->AttachBrowsingContext(aParentNode);
}
bool retval = false;

View File

@ -433,11 +433,25 @@ public:
void operator=(const CallbackObjectHolder& aOther) = delete;
void Reset()
{
UnlinkSelf();
}
nsISupports* GetISupports() const
{
return reinterpret_cast<nsISupports*>(mPtrBits & ~XPCOMCallbackFlag);
}
already_AddRefed<nsISupports> Forget()
{
// This can be called from random threads. Make sure to not refcount things
// in here!
nsISupports* supp = GetISupports();
mPtrBits = 0;
return dont_AddRef(supp);
}
// Boolean conversion operator so people can use this in boolean tests
explicit operator bool() const
{

View File

@ -11,6 +11,7 @@
#include "js/Wrapper.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/Maybe.h"
@ -92,7 +93,7 @@ struct WebIDLNameTableEntry : public PLDHashEntryHdr
const char* name = WebIDLGlobalNameHash::sNames + mNameOffset;
if (aKey->mLatin1String) {
return PodEqual(aKey->mLatin1String, name, aKey->mLength);
return ArrayEqual(aKey->mLatin1String, name, aKey->mLength);
}
return nsCharTraits<char16_t>::compareASCII(aKey->mTwoBytesString, name,

View File

@ -36,6 +36,7 @@
#include "mozilla/DataStorage.h"
#include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/ClientManager.h"
#include "mozilla/dom/ClientOpenWindowOpActors.h"
#include "mozilla/dom/DataTransfer.h"
@ -1895,6 +1896,8 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
#if defined(XP_WIN32) && defined(ACCESSIBILITY)
a11y::AccessibleWrap::ReleaseContentProcessIdFor(ChildID());
#endif
BrowsingContext::CleanupContexts(ChildID());
}
bool
@ -5977,3 +5980,114 @@ ContentParent::RecvFirstPartyStorageAccessGrantedForOrigin(const Principal& aPar
std::move(aResolver));
return IPC_OK();
}
mozilla::ipc::IPCResult
ContentParent::RecvAttachBrowsingContext(
const BrowsingContextId& aParentId,
const BrowsingContextId& aChildId,
const nsString& aName)
{
RefPtr<BrowsingContext> parent = BrowsingContext::Get(aParentId);
if (aParentId && !parent) {
// Unless 'aParentId' is 0 (which it is when the child is a root
// BrowsingContext) there should always be a corresponding
// 'parent'. The only reason for there not beeing one is if the
// parent has already been detached, in which case the
// BrowsingContext that tries to attach itself to the context with
// 'aParentId' is surely doomed and we can safely do nothing.
// TODO(farre): When we start syncing/moving BrowsingContexts to
// other child processes is it possible to get into races where
// constructive operations on already detached BrowsingContexts
// are requested? This needs to be answered/handled, but for now
// return early. [Bug 1471598]
MOZ_LOG(
BrowsingContext::GetLog(),
LogLevel::Debug,
("ParentIPC: Trying to attach to already detached parent 0x%08" PRIx64,
(uint64_t)aParentId));
return IPC_OK();
}
if (parent && parent->OwnerProcessId() != ChildID()) {
// Where trying attach a child BrowsingContext to a parent
// BrowsingContext in another process. This is illegal since the
// only thing that could create that child BrowsingContext is a
// parent docshell in the same process as that BrowsingContext.
// TODO(farre): We're doing nothing now, but is that exactly what
// we want? Maybe we want to crash the child currently calling
// SendAttachBrowsingContext and/or the child that originally
// called SendAttachBrowsingContext or possibly all children that
// has a BrowsingContext connected to the child that currently
// called SendAttachBrowsingContext? [Bug 1471598]
MOZ_LOG(BrowsingContext::GetLog(),
LogLevel::Warning,
("ParentIPC: Trying to attach to out of process parent context "
"0x%08" PRIx64,
parent->Id()));
return IPC_OK();
}
RefPtr<BrowsingContext> child = BrowsingContext::Get(aChildId);
if (child && !child->IsCached()) {
// This is highly suspicious. BrowsingContexts should only be
// attached at most once, but finding one indicates that someone
// is doing something they shouldn't.
// TODO(farre): To crash or not to crash. Same reasoning as in
// above TODO. [Bug 1471598]
MOZ_LOG(BrowsingContext::GetLog(),
LogLevel::Warning,
("ParentIPC: Trying to attach already attached 0x%08" PRIx64
" to 0x%08" PRIx64,
child->Id(),
(uint64_t)aParentId));
return IPC_OK();
}
if (!child) {
child = new BrowsingContext(aChildId, aName, Some(ChildID()));
}
child->Attach(parent);
return IPC_OK();
}
mozilla::ipc::IPCResult
ContentParent::RecvDetachBrowsingContext(const BrowsingContextId& aContextId,
const bool& aMoveToBFCache)
{
RefPtr<BrowsingContext> context = BrowsingContext::Get(aContextId);
if (!context) {
MOZ_LOG(BrowsingContext::GetLog(),
LogLevel::Debug,
("ParentIPC: Trying to detach already detached 0x%08" PRIx64,
(uint64_t)aContextId));
return IPC_OK();
}
if (context->OwnerProcessId() != ChildID()) {
// Where trying to detach a child BrowsingContext in another child
// process. This is illegal since the owner of the BrowsingContext
// is the proccess with the in-process docshell, which is tracked
// by OwnerProcessId.
// TODO(farre): To crash or not to crash. Same reasoning as in
// above TODO. [Bug 1471598]
MOZ_LOG(BrowsingContext::GetLog(),
LogLevel::Warning,
("ParentIPC: Trying to detach out of process context 0x%08" PRIx64,
context->Id()));
return IPC_OK();
}
if (aMoveToBFCache) {
context->CacheChildren();
} else {
context->Detach();
}
return IPC_OK();
}

View File

@ -682,6 +682,15 @@ public:
static bool IsInputEventQueueSupported();
virtual mozilla::ipc::IPCResult RecvAttachBrowsingContext(
const BrowsingContextId& aParentContextId,
const BrowsingContextId& aContextId,
const nsString& aName) override;
virtual mozilla::ipc::IPCResult RecvDetachBrowsingContext(
const BrowsingContextId& aContextId,
const bool& aMoveToBFCache) override;
protected:
void OnChannelConnected(int32_t pid) override;

View File

@ -15,10 +15,10 @@ template<typename T> struct ParamTraits;
namespace mozilla {
namespace dom {
class BrowsingContext;
class ContentParent;
class TabParent;
template<typename T>
class IdType
{
@ -46,7 +46,7 @@ private:
typedef IdType<TabParent> TabId;
typedef IdType<ContentParent> ContentParentId;
typedef IdType<BrowsingContext> BrowsingContextId;
} // namespace dom
} // namespace mozilla

View File

@ -100,6 +100,7 @@ using mozilla::Telemetry::ChildEventData from "mozilla/TelemetryComms.h";
using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
using mozilla::CrossProcessMutexHandle from "mozilla/ipc/CrossProcessMutex.h";
using refcounted class nsIInputStream from "mozilla/ipc/IPCStreamUtils.h";
using mozilla::dom::BrowsingContextId from "mozilla/dom/ipc/IdType.h";
union ChromeRegistryItem
{
@ -1177,6 +1178,35 @@ parent:
nsCString aGrantedOrigin)
returns (bool unused);
/**
* Sync the BrowsingContext with id 'aContextId' and name 'aName'
* to the parent, and attach it to the BrowsingContext with id
* 'aParentContextId'. If 'aParentContextId' is '0' the
* BrowsingContext is a root in the BrowsingContext
* tree. AttachBrowsingContext must only be called at most once
* for any child BrowsingContext, and only for BrowsingContexts
* where the parent and the child context contains their
* nsDocShell.
*/
async AttachBrowsingContext(BrowsingContextId aParentContextId,
BrowsingContextId aContextId,
nsString aName);
/**
* Remove the synced BrowsingContext with id 'aContextId' from the
* parent. DetachBrowsingContext is only needed to be called once
* for any BrowsingContext, since detaching a node in the
* BrowsingContext detaches the entire sub-tree rooted at that
* node. Calling DetachBrowsingContext with an already detached
* BrowsingContext effectively does nothing. Note that it is not
* an error to call DetachBrowsingContext on a BrowsingContext
* belonging to an already detached subtree. The 'aMoveToBFCache'
* paramater controls if detaching a BrowsingContext should move
* it to the bfcache allowing it to be re-attached if navigated
* to.
*/
async DetachBrowsingContext(BrowsingContextId aContextId,
bool aMoveToBFCache);
both:
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
Principal aPrincipal, ClonedMessageData aData);

View File

@ -6,6 +6,7 @@
#include "mozilla/dom/MediaStreamBinding.h"
#include "mozilla/dom/MediaDeviceInfo.h"
#include "mozilla/dom/MediaDevicesBinding.h"
#include "mozilla/dom/NavigatorBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/MediaManager.h"
#include "MediaTrackConstraints.h"
@ -182,11 +183,12 @@ MediaDevices::GetUserMedia(const MediaStreamConstraints& aConstraints,
RefPtr<Promise> p = Promise::Create(GetParentObject(), aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
RefPtr<GumResolver> resolver = new GumResolver(p);
RefPtr<GumRejecter> rejecter = new GumRejecter(p);
MediaManager::GetUserMediaSuccessCallback resolver(new GumResolver(p));
MediaManager::GetUserMediaErrorCallback rejecter(new GumRejecter(p));
aRv = MediaManager::Get()->GetUserMedia(GetOwner(), aConstraints,
resolver, rejecter,
std::move(resolver),
std::move(rejecter),
aCallerType);
return p.forget();
}

View File

@ -99,6 +99,77 @@ struct nsIMediaDevice::COMTypeInfo<mozilla::MediaDevice, void> {
};
const nsIID nsIMediaDevice::COMTypeInfo<mozilla::MediaDevice, void>::kIID = NS_IMEDIADEVICE_IID;
// A specialization of nsMainThreadPtrHolder for
// mozilla::dom::CallbackObjectHolder. See documentation for
// nsMainThreadPtrHolder in nsProxyRelease.h. This specialization lets us avoid
// wrapping the CallbackObjectHolder into a separate refcounted object.
template<class WebIDLCallbackT, class XPCOMCallbackT>
class nsMainThreadPtrHolder<mozilla::dom::CallbackObjectHolder<WebIDLCallbackT,
XPCOMCallbackT>> final
{
typedef mozilla::dom::CallbackObjectHolder<WebIDLCallbackT,
XPCOMCallbackT> Holder;
public:
nsMainThreadPtrHolder(const char* aName, Holder&& aHolder)
: mHolder(std::move(aHolder))
#ifndef RELEASE_OR_BETA
, mName(aName)
#endif
{
MOZ_ASSERT(NS_IsMainThread());
}
private:
// We can be released on any thread.
~nsMainThreadPtrHolder()
{
if (NS_IsMainThread()) {
mHolder.Reset();
} else if (mHolder.GetISupports()) {
nsCOMPtr<nsIEventTarget> target = do_GetMainThread();
MOZ_ASSERT(target);
NS_ProxyRelease(
#ifdef RELEASE_OR_BETA
nullptr,
#else
mName,
#endif
target, mHolder.Forget());
}
}
public:
Holder* get()
{
// Nobody should be touching the raw pointer off-main-thread.
if (MOZ_UNLIKELY(!NS_IsMainThread())) {
NS_ERROR("Can't dereference nsMainThreadPtrHolder off main thread");
MOZ_CRASH();
}
return &mHolder;
}
bool operator!() const
{
return !mHolder;
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsMainThreadPtrHolder<Holder>)
private:
// Our holder.
Holder mHolder;
#ifndef RELEASE_OR_BETA
const char* mName = nullptr;
#endif
// Copy constructor and operator= not implemented. Once constructed, the
// holder is immutable.
Holder& operator=(const nsMainThreadPtrHolder& aOther) = delete;
nsMainThreadPtrHolder(const nsMainThreadPtrHolder& aOther) = delete;
};
namespace {
already_AddRefed<nsIAsyncShutdownClient> GetShutdownPhase() {
nsCOMPtr<nsIAsyncShutdownService> svc = mozilla::services::GetAsyncShutdown();
@ -231,6 +302,30 @@ FromCaptureState(CaptureState aState)
return static_cast<uint16_t>(aState);
}
static void
CallOnError(MediaManager::GetUserMediaErrorCallback* aCallback,
MediaStreamError& aError)
{
MOZ_ASSERT(aCallback);
if (aCallback->HasWebIDLCallback()) {
aCallback->GetWebIDLCallback()->Call(aError);
} else {
aCallback->GetXPCOMCallback()->OnError(&aError);
}
}
static void
CallOnSuccess(MediaManager::GetUserMediaSuccessCallback* aCallback,
DOMMediaStream& aStream)
{
MOZ_ASSERT(aCallback);
if (aCallback->HasWebIDLCallback()) {
aCallback->GetWebIDLCallback()->Call(aStream);
} else {
aCallback->GetXPCOMCallback()->OnSuccess(&aStream);
}
}
/**
* SourceListener has threadsafe refcounting for use across the main, media and
* MSG threads. But it has a non-threadsafe SupportsWeakPtr for WeakPtr usage
@ -776,7 +871,7 @@ private:
class ErrorCallbackRunnable : public Runnable
{
public:
ErrorCallbackRunnable(const nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
ErrorCallbackRunnable(const nsMainThreadPtrHandle<MediaManager::GetUserMediaErrorCallback>& aOnFailure,
MediaMgrError& aError,
uint64_t aWindowID)
: Runnable("ErrorCallbackRunnable")
@ -801,14 +896,14 @@ public:
if (auto* window = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID)) {
RefPtr<MediaStreamError> error =
new MediaStreamError(window->AsInner(), *mError);
mOnFailure->OnError(error);
CallOnError(mOnFailure, *error);
}
return NS_OK;
}
private:
~ErrorCallbackRunnable() override = default;
nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> mOnFailure;
nsMainThreadPtrHandle<MediaManager::GetUserMediaErrorCallback> mOnFailure;
RefPtr<MediaMgrError> mError;
uint64_t mWindowID;
RefPtr<MediaManager> mManager; // get ref to this when creating the runnable
@ -1164,8 +1259,8 @@ class GetUserMediaStreamRunnable : public Runnable
{
public:
GetUserMediaStreamRunnable(
const nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
const nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
const nsMainThreadPtrHandle<MediaManager::GetUserMediaSuccessCallback>& aOnSuccess,
const nsMainThreadPtrHandle<MediaManager::GetUserMediaErrorCallback>& aOnFailure,
uint64_t aWindowID,
GetUserMediaWindowListener* aWindowListener,
SourceListener* aSourceListener,
@ -1196,7 +1291,7 @@ public:
{
public:
TracksAvailableCallback(MediaManager* aManager,
const nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
const nsMainThreadPtrHandle<MediaManager::GetUserMediaSuccessCallback>& aSuccess,
const RefPtr<GetUserMediaWindowListener>& aWindowListener,
DOMMediaStream* aStream)
: mWindowListener(aWindowListener),
@ -1218,10 +1313,10 @@ public:
// This is safe since we're on main-thread, and the windowlist can only
// be invalidated from the main-thread (see OnNavigation)
LOG(("Returning success for getUserMedia()"));
mOnSuccess->OnSuccess(aStream);
CallOnSuccess(mOnSuccess, *aStream);
}
RefPtr<GetUserMediaWindowListener> mWindowListener;
nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
nsMainThreadPtrHandle<MediaManager::GetUserMediaSuccessCallback> mOnSuccess;
RefPtr<MediaManager> mManager;
// Keep the DOMMediaStream alive until the NotifyTracksAvailable callback
// has fired, otherwise we might immediately destroy the DOMMediaStream and
@ -1459,7 +1554,7 @@ public:
MediaStreamError::Name::AbortError,
sHasShutdown ? NS_LITERAL_STRING("In shutdown") :
NS_LITERAL_STRING("No stream."));
mOnFailure->OnError(error);
CallOnError(mOnFailure, *error);
}
return NS_OK;
}
@ -1511,7 +1606,7 @@ public:
// be invalidated from the main-thread (see OnNavigation)
if (auto* window = nsGlobalWindowInner::GetInnerWindowWithId(windowID)) {
auto streamError = MakeRefPtr<MediaStreamError>(window->AsInner(), *error);
onFailure->OnError(streamError);
CallOnError(onFailure, *streamError);
}
});
@ -1525,8 +1620,8 @@ public:
}
private:
nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> mOnFailure;
nsMainThreadPtrHandle<MediaManager::GetUserMediaSuccessCallback> mOnSuccess;
nsMainThreadPtrHandle<MediaManager::GetUserMediaErrorCallback> mOnFailure;
MediaStreamConstraints mConstraints;
RefPtr<MediaDevice> mAudioDevice;
RefPtr<MediaDevice> mVideoDevice;
@ -1672,8 +1767,8 @@ class GetUserMediaTask : public Runnable
public:
GetUserMediaTask(
const MediaStreamConstraints& aConstraints,
const nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
const nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
const nsMainThreadPtrHandle<MediaManager::GetUserMediaSuccessCallback>& aOnSuccess,
const nsMainThreadPtrHandle<MediaManager::GetUserMediaErrorCallback>& aOnFailure,
uint64_t aWindowID,
GetUserMediaWindowListener* aWindowListener,
SourceListener* aSourceListener,
@ -1822,7 +1917,7 @@ public:
if (auto* window = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID)) {
RefPtr<MediaStreamError> error = new MediaStreamError(window->AsInner(),
aName, aMessage);
mOnFailure->OnError(error);
CallOnError(mOnFailure, *error);
}
// Should happen *after* error runs for consistency, but may not matter
mWindowListener->Remove(mSourceListener);
@ -1872,8 +1967,8 @@ public:
private:
MediaStreamConstraints mConstraints;
nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> mOnFailure;
nsMainThreadPtrHandle<MediaManager::GetUserMediaSuccessCallback> mOnSuccess;
nsMainThreadPtrHandle<MediaManager::GetUserMediaErrorCallback> mOnFailure;
uint64_t mWindowID;
RefPtr<GetUserMediaWindowListener> mWindowListener;
RefPtr<SourceListener> mSourceListener;
@ -2497,20 +2592,20 @@ ReduceConstraint(
nsresult
MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
const MediaStreamConstraints& aConstraintsPassedIn,
nsIDOMGetUserMediaSuccessCallback* aOnSuccess,
nsIDOMGetUserMediaErrorCallback* aOnFailure,
GetUserMediaSuccessCallback&& aOnSuccess,
GetUserMediaErrorCallback&& aOnFailure,
dom::CallerType aCallerType)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aOnFailure);
MOZ_ASSERT(aOnSuccess);
nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback> onSuccess(
new nsMainThreadPtrHolder<nsIDOMGetUserMediaSuccessCallback>(
"GetUserMedia::SuccessCallback", aOnSuccess));
nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> onFailure(
new nsMainThreadPtrHolder<nsIDOMGetUserMediaErrorCallback>(
"GetUserMedia::FailureCallback", aOnFailure));
MOZ_ASSERT(aOnFailure.GetISupports());
MOZ_ASSERT(aOnSuccess.GetISupports());
nsMainThreadPtrHandle<GetUserMediaSuccessCallback> onSuccess(
new nsMainThreadPtrHolder<GetUserMediaSuccessCallback>(
"GetUserMedia::SuccessCallback", std::move(aOnSuccess)));
nsMainThreadPtrHandle<GetUserMediaErrorCallback> onFailure(
new nsMainThreadPtrHolder<GetUserMediaErrorCallback>(
"GetUserMedia::FailureCallback", std::move(aOnFailure)));
uint64_t windowID = aWindow->WindowID();
MediaStreamConstraints c(aConstraintsPassedIn); // use a modifiable copy
@ -2523,14 +2618,14 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
new MediaStreamError(aWindow,
MediaStreamError::Name::TypeError,
NS_LITERAL_STRING("audio and/or video is required"));
onFailure->OnError(error);
CallOnError(onFailure, *error);
return NS_OK;
}
if (!IsFullyActive(aWindow)) {
RefPtr<MediaStreamError> error =
new MediaStreamError(aWindow, MediaStreamError::Name::InvalidStateError);
onFailure->OnError(error);
CallOnError(onFailure, *error);
return NS_OK;
}
@ -2539,7 +2634,7 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
new MediaStreamError(aWindow,
MediaStreamError::Name::AbortError,
NS_LITERAL_STRING("In shutdown"));
onFailure->OnError(error);
CallOnError(onFailure, *error);
return NS_OK;
}
@ -2652,7 +2747,7 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
RefPtr<MediaStreamError> error =
new MediaStreamError(aWindow,
MediaStreamError::Name::NotAllowedError);
onFailure->OnError(error);
CallOnError(onFailure, *error);
return NS_OK;
}
break;
@ -2665,7 +2760,7 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
MediaStreamError::Name::OverconstrainedError,
NS_LITERAL_STRING(""),
NS_LITERAL_STRING("mediaSource"));
onFailure->OnError(error);
CallOnError(onFailure, *error);
return NS_OK;
}
}
@ -2732,7 +2827,7 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
RefPtr<MediaStreamError> error =
new MediaStreamError(aWindow,
MediaStreamError::Name::NotAllowedError);
onFailure->OnError(error);
CallOnError(onFailure, *error);
return NS_OK;
}
break;
@ -2744,7 +2839,7 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
MediaStreamError::Name::OverconstrainedError,
NS_LITERAL_STRING(""),
NS_LITERAL_STRING("mediaSource"));
onFailure->OnError(error);
CallOnError(onFailure, *error);
return NS_OK;
}
}
@ -2815,7 +2910,7 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
(IsOn(c.mVideo) && videoPerm == nsIPermissionManager::DENY_ACTION)) {
RefPtr<MediaStreamError> error =
new MediaStreamError(aWindow, MediaStreamError::Name::NotAllowedError);
onFailure->OnError(error);
CallOnError(onFailure, *error);
windowListener->Remove(sourceListener);
return NS_OK;
}
@ -2925,7 +3020,7 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
MediaStreamError::Name::OverconstrainedError,
NS_LITERAL_STRING(""),
constraint);
onFailure->OnError(error);
CallOnError(onFailure, *error);
return;
}
if (!(*devices)->Length()) {
@ -2939,7 +3034,7 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
// device, so report NotAllowedError.
resistFingerprinting ? MediaStreamError::Name::NotAllowedError
: MediaStreamError::Name::NotFoundError);
onFailure->OnError(error);
CallOnError(onFailure, *error);
return;
}
@ -3000,11 +3095,11 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
#endif
}, [onFailure](MediaStreamError*& reason) mutable {
LOG(("GetUserMedia: post enumeration pledge2 failure callback called!"));
onFailure->OnError(reason);
CallOnError(onFailure, *reason);
});
}, [onFailure](MediaStreamError*& reason) mutable {
LOG(("GetUserMedia: post enumeration pledge failure callback called!"));
onFailure->OnError(reason);
CallOnError(onFailure, *reason);
});
return NS_OK;
}
@ -3293,14 +3388,11 @@ MediaManager::EnumerateDevices(nsPIDOMWindowInner* aWindow,
nsresult
MediaManager::GetUserMediaDevices(nsPIDOMWindowInner* aWindow,
const MediaStreamConstraints& aConstraints,
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
nsIDOMGetUserMediaErrorCallback* aOnFailure,
dom::MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
uint64_t aWindowId,
const nsAString& aCallID)
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
if (!aWindowId) {
aWindowId = aWindow->WindowID();
}
@ -3317,7 +3409,7 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindowInner* aWindow,
if (!aCallID.Length() || aCallID == callID) {
if (mActiveCallbacks.Get(callID, getter_AddRefs(task))) {
nsCOMPtr<nsIWritableVariant> array = MediaManager_ToJSArray(*task->mMediaDeviceSet);
onSuccess->OnSuccess(array);
aOnSuccess.Call(array);
return NS_OK;
}
}

View File

@ -29,6 +29,7 @@
#include "mozilla/dom/MediaStreamBinding.h"
#include "mozilla/dom/MediaStreamTrackBinding.h"
#include "mozilla/dom/MediaStreamError.h"
#include "mozilla/dom/NavigatorBinding.h"
#include "mozilla/media/MediaChild.h"
#include "mozilla/media/MediaParent.h"
#include "mozilla/Logging.h"
@ -202,17 +203,21 @@ public:
void RemoveFromWindowList(uint64_t aWindowID,
GetUserMediaWindowListener *aListener);
typedef dom::CallbackObjectHolder<dom::NavigatorUserMediaSuccessCallback,
nsIDOMGetUserMediaSuccessCallback> GetUserMediaSuccessCallback;
typedef dom::CallbackObjectHolder<dom::NavigatorUserMediaErrorCallback,
nsIDOMGetUserMediaErrorCallback> GetUserMediaErrorCallback;
nsresult GetUserMedia(
nsPIDOMWindowInner* aWindow,
const dom::MediaStreamConstraints& aConstraints,
nsIDOMGetUserMediaSuccessCallback* onSuccess,
nsIDOMGetUserMediaErrorCallback* onError,
GetUserMediaSuccessCallback&& onSuccess,
GetUserMediaErrorCallback&& onError,
dom::CallerType aCallerType);
nsresult GetUserMediaDevices(nsPIDOMWindowInner* aWindow,
const dom::MediaStreamConstraints& aConstraints,
nsIGetUserMediaDevicesSuccessCallback* onSuccess,
nsIDOMGetUserMediaErrorCallback* onError,
dom::MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
uint64_t aInnerWindowID = 0,
const nsAString& aCallID = nsString());

View File

@ -755,10 +755,14 @@ SpeechRecognition::Start(const Optional<NonNull<DOMMediaStream>>& aStream,
} else {
AutoNoJSAPI();
MediaManager* manager = MediaManager::Get();
MediaManager::GetUserMediaSuccessCallback onsuccess(
new GetUserMediaSuccessCallback(this));
MediaManager::GetUserMediaErrorCallback onerror(
new GetUserMediaErrorCallback(this));
manager->GetUserMedia(GetOwner(),
constraints,
new GetUserMediaSuccessCallback(this),
new GetUserMediaErrorCallback(this),
std::move(onsuccess),
std::move(onerror),
aCallerType);
}

View File

@ -61,6 +61,11 @@ interface AccessibleNode {
attribute DOMString? live;
attribute DOMString? relevant;
// Other relationships
attribute AccessibleNode? activeDescendant;
attribute AccessibleNode? details;
attribute AccessibleNode? errorMessage;
// Collections.
attribute long? colCount;
attribute unsigned long? colIndex;

View File

@ -513,7 +513,7 @@ public:
// contents start at rightside also cause their horizontal scrollbars, if any,
// initially start at rightside. So we can also learn about the initial side
// of the horizontal scrollbar for the frame by calling this function.
bool IsHorizontalContentRightToLeft() {
bool IsHorizontalContentRightToLeft() const {
return mScrollableRect.x < 0;
}

View File

@ -13,6 +13,7 @@
#include "Units.h" // for ParentLayerIntRect
#include "gfxRect.h" // for gfxRect
#include "gfxUtils.h" // for gfxUtils
#include "mozilla/ArrayUtils.h" // for ArrayEqual
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/mozalloc.h" // for operator new, etc

View File

@ -821,7 +821,6 @@ AsyncPanZoomController::AsyncPanZoomController(LayersId aLayersId,
mRefPtrMonitor("RefPtrMonitor"),
// mTreeManager must be initialized before GetFrameTime() is called
mTreeManager(aTreeManager),
mFrameMetrics(mScrollMetadata.GetMetrics()),
mRecursiveMutex("AsyncPanZoomController"),
mLastContentPaintMetrics(mLastContentPaintMetadata.GetMetrics()),
mX(this),
@ -829,8 +828,8 @@ AsyncPanZoomController::AsyncPanZoomController(LayersId aLayersId,
mPanDirRestricted(false),
mPinchLocked(false),
mZoomConstraints(false, false,
mFrameMetrics.GetDevPixelsPerCSSPixel() * kViewportMinScale / ParentLayerToScreenScale(1),
mFrameMetrics.GetDevPixelsPerCSSPixel() * kViewportMaxScale / ParentLayerToScreenScale(1)),
Metrics().GetDevPixelsPerCSSPixel() * kViewportMinScale / ParentLayerToScreenScale(1),
Metrics().GetDevPixelsPerCSSPixel() * kViewportMaxScale / ParentLayerToScreenScale(1)),
mLastSampleTime(GetFrameTime()),
mLastCheckerboardReport(GetFrameTime()),
mOverscrollEffect(MakeUnique<OverscrollEffect>(*this)),
@ -899,7 +898,7 @@ AsyncPanZoomController::Destroy()
// Only send the release message if the SharedFrameMetrics has been created.
if (mMetricsSharingController && mSharedFrameMetricsBuffer) {
Unused << mMetricsSharingController->StopSharingMetrics(mFrameMetrics.GetScrollId(), mAPZCId);
Unused << mMetricsSharingController->StopSharingMetrics(Metrics().GetScrollId(), mAPZCId);
}
{ // scope the lock
@ -1063,16 +1062,16 @@ nsEventStatus AsyncPanZoomController::HandleDragEvent(const MouseInput& aEvent,
APZC_LOG("%p scrollbar dragged to %f percent\n", this, scrollPercent);
CSSCoord minScrollPosition =
GetAxisStart(direction, mFrameMetrics.GetScrollableRect().TopLeft());
GetAxisStart(direction, Metrics().GetScrollableRect().TopLeft());
CSSCoord maxScrollPosition =
GetAxisStart(direction, mFrameMetrics.GetScrollableRect().BottomRight()) -
GetAxisLength(direction, mFrameMetrics.CalculateCompositionBoundsInCssPixelsOfSurroundingContent());
GetAxisStart(direction, Metrics().GetScrollableRect().BottomRight()) -
GetAxisLength(direction, Metrics().CalculateCompositionBoundsInCssPixelsOfSurroundingContent());
CSSCoord scrollPosition = minScrollPosition + (scrollPercent * (maxScrollPosition - minScrollPosition));
scrollPosition = std::max(scrollPosition, minScrollPosition);
scrollPosition = std::min(scrollPosition, maxScrollPosition);
CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset();
CSSPoint scrollOffset = Metrics().GetScrollOffset();
if (direction == ScrollDirection::eHorizontal) {
scrollOffset.x = scrollPosition;
} else {
@ -1463,7 +1462,7 @@ nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEve
SetState(PINCHING);
mX.SetVelocity(0);
mY.SetVelocity(0);
mLastZoomFocus = aEvent.mLocalFocusPoint - mFrameMetrics.GetCompositionBounds().TopLeft();
mLastZoomFocus = aEvent.mLocalFocusPoint - Metrics().GetCompositionBounds().TopLeft();
return nsEventStatus_eConsumeNoDefault;
}
@ -1484,7 +1483,7 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
{
RecursiveMutexAutoLock lock(mRecursiveMutex);
focusPoint = aEvent.mLocalFocusPoint - mFrameMetrics.GetCompositionBounds().TopLeft();
focusPoint = aEvent.mLocalFocusPoint - Metrics().GetCompositionBounds().TopLeft();
focusChange = mLastZoomFocus - focusPoint;
mLastZoomFocus = focusPoint;
}
@ -1517,14 +1516,14 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
// would have to be adjusted (as e.g. it would no longer be valid to take
// the minimum or maximum of the ratios of the widths and heights of the
// page rect and the composition bounds).
MOZ_ASSERT(mFrameMetrics.IsRootContent());
MOZ_ASSERT(mFrameMetrics.GetZoom().AreScalesSame());
MOZ_ASSERT(Metrics().IsRootContent());
MOZ_ASSERT(Metrics().GetZoom().AreScalesSame());
{
RecursiveMutexAutoLock lock(mRecursiveMutex);
CSSToParentLayerScale userZoom = mFrameMetrics.GetZoom().ToScaleFactor();
CSSPoint cssFocusPoint = focusPoint / mFrameMetrics.GetZoom();
CSSToParentLayerScale userZoom = Metrics().GetZoom().ToScaleFactor();
CSSPoint cssFocusPoint = focusPoint / Metrics().GetZoom();
// If displacing by the change in focus point will take us off page bounds,
// then reduce the displacement such that it doesn't.
@ -1556,9 +1555,9 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
CSSToParentLayerScale realMinZoom = mZoomConstraints.mMinZoom;
CSSToParentLayerScale realMaxZoom = mZoomConstraints.mMaxZoom;
realMinZoom.scale = std::max(realMinZoom.scale,
mFrameMetrics.GetCompositionBounds().Width() / mFrameMetrics.GetScrollableRect().Width());
Metrics().GetCompositionBounds().Width() / Metrics().GetScrollableRect().Width());
realMinZoom.scale = std::max(realMinZoom.scale,
mFrameMetrics.GetCompositionBounds().Height() / mFrameMetrics.GetScrollableRect().Height());
Metrics().GetCompositionBounds().Height() / Metrics().GetScrollableRect().Height());
if (realMaxZoom < realMinZoom) {
realMaxZoom = realMinZoom;
}
@ -1763,13 +1762,13 @@ AsyncPanZoomController::ConvertScrollbarPoint(const ParentLayerPoint& aScrollbar
RecursiveMutexAutoLock lock(mRecursiveMutex);
// First, get it into the right coordinate space.
CSSPoint scrollbarPoint = aScrollbarPoint / mFrameMetrics.GetZoom();
CSSPoint scrollbarPoint = aScrollbarPoint / Metrics().GetZoom();
// The scrollbar can be transformed with the frame but the pres shell
// resolution is only applied to the scroll frame.
scrollbarPoint = scrollbarPoint * mFrameMetrics.GetPresShellResolution();
scrollbarPoint = scrollbarPoint * Metrics().GetPresShellResolution();
// Now, get it to be relative to the beginning of the scroll track.
CSSRect cssCompositionBound = mFrameMetrics.CalculateCompositionBoundsInCssPixelsOfSurroundingContent();
CSSRect cssCompositionBound = Metrics().CalculateCompositionBoundsInCssPixelsOfSurroundingContent();
return GetAxisStart(*aThumbData.mDirection, scrollbarPoint)
- GetAxisStart(*aThumbData.mDirection, cssCompositionBound)
- aThumbData.mScrollTrackStart;
@ -1808,9 +1807,9 @@ AsyncPanZoomController::GetScrollWheelDelta(const ScrollWheelInput& aEvent,
LayoutDeviceIntSize scrollAmountLD = mScrollMetadata.GetLineScrollAmount();
LayoutDeviceIntSize pageScrollSizeLD = mScrollMetadata.GetPageScrollAmount();
scrollAmount = scrollAmountLD /
mFrameMetrics.GetDevPixelsPerCSSPixel() * mFrameMetrics.GetZoom();
Metrics().GetDevPixelsPerCSSPixel() * Metrics().GetZoom();
pageScrollSize = pageScrollSizeLD /
mFrameMetrics.GetDevPixelsPerCSSPixel() * mFrameMetrics.GetZoom();
Metrics().GetDevPixelsPerCSSPixel() * Metrics().GetZoom();
}
ParentLayerPoint delta;
@ -1897,8 +1896,8 @@ AsyncPanZoomController::OnKeyboard(const KeyboardInput& aEvent)
// CallDispatchScroll interprets the start and end points as the start and
// end of a touch scroll so they need to be reversed.
ParentLayerPoint startPoint = destination * mFrameMetrics.GetZoom();
ParentLayerPoint endPoint = mFrameMetrics.GetScrollOffset() * mFrameMetrics.GetZoom();
ParentLayerPoint startPoint = destination * Metrics().GetZoom();
ParentLayerPoint endPoint = Metrics().GetScrollOffset() * Metrics().GetZoom();
ParentLayerPoint delta = endPoint - startPoint;
ScreenPoint distance = ToScreenCoordinates(
@ -1935,7 +1934,7 @@ AsyncPanZoomController::OnKeyboard(const KeyboardInput& aEvent)
CancelAnimation();
SetState(KEYBOARD_SCROLL);
nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
nsPoint initialPosition = CSSPoint::ToAppUnits(Metrics().GetScrollOffset());
StartAnimation(new KeyboardScrollAnimation(*this, initialPosition, aEvent.mAction.mType));
}
@ -1944,7 +1943,7 @@ AsyncPanZoomController::OnKeyboard(const KeyboardInput& aEvent)
nsPoint velocity =
CSSPoint::ToAppUnits(
ParentLayerPoint(mX.GetVelocity() * 1000.0f, mY.GetVelocity() * 1000.0f) /
mFrameMetrics.GetZoom());
Metrics().GetZoom());
KeyboardScrollAnimation* animation = mAnimation->AsKeyboardScrollAnimation();
MOZ_ASSERT(animation);
@ -1969,9 +1968,9 @@ AsyncPanZoomController::GetKeyboardDestination(const KeyboardScrollAction& aActi
RecursiveMutexAutoLock lock(mRecursiveMutex);
lineScrollSize = mScrollMetadata.GetLineScrollAmount() /
mFrameMetrics.GetDevPixelsPerCSSPixel();
Metrics().GetDevPixelsPerCSSPixel();
pageScrollSize = mScrollMetadata.GetPageScrollAmount() /
mFrameMetrics.GetDevPixelsPerCSSPixel();
Metrics().GetDevPixelsPerCSSPixel();
if (mState == WHEEL_SCROLL) {
scrollOffset = mAnimation->AsWheelScrollAnimation()->GetDestination();
@ -1980,10 +1979,10 @@ AsyncPanZoomController::GetKeyboardDestination(const KeyboardScrollAction& aActi
} else if (mState == KEYBOARD_SCROLL) {
scrollOffset = mAnimation->AsKeyboardScrollAnimation()->GetDestination();
} else {
scrollOffset = mFrameMetrics.GetScrollOffset();
scrollOffset = Metrics().GetScrollOffset();
}
scrollRect = mFrameMetrics.GetScrollableRect();
scrollRect = Metrics().GetScrollableRect();
}
// Calculate the scroll destination based off of the scroll type and direction
@ -2140,7 +2139,7 @@ AsyncPanZoomController::IsContentOfHonouredTargetRightToLeft(
return mScrollMetadata.IsAutoDirRootContentRTL();
}
RecursiveMutexAutoLock lock(mRecursiveMutex);
return mFrameMetrics.IsHorizontalContentRightToLeft();
return Metrics().IsHorizontalContentRightToLeft();
}
bool
@ -2237,7 +2236,7 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
gfxPrefs::MouseScrollTestingEnabled()) {
if (RefPtr<GeckoContentController> controller = GetGeckoContentController()) {
controller->NotifyMozMouseScrollEvent(
mFrameMetrics.GetScrollId(),
Metrics().GetScrollId(),
NS_LITERAL_STRING("MozMouseScrollFailed"));
}
}
@ -2259,7 +2258,7 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
// Wheel events from "clicky" mouse wheels trigger scroll snapping to the
// next snap point. Check for this, and adjust the delta to take into
// account the snap point.
CSSPoint startPosition = mFrameMetrics.GetScrollOffset();
CSSPoint startPosition = Metrics().GetScrollOffset();
MaybeAdjustDeltaForScrollSnapping(aEvent, delta, startPosition);
ScreenPoint distance = ToScreenCoordinates(
@ -2292,7 +2291,7 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
RecursiveMutexAutoLock lock(mRecursiveMutex);
// Perform scroll snapping if appropriate.
CSSPoint startPosition = mFrameMetrics.GetScrollOffset();
CSSPoint startPosition = Metrics().GetScrollOffset();
// If we're already in a wheel scroll or smooth scroll animation,
// the delta is applied to its destination, not to the current
// scroll position. Take this into account when finding a snap point.
@ -2317,13 +2316,13 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
CancelAnimation();
SetState(WHEEL_SCROLL);
nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
nsPoint initialPosition = CSSPoint::ToAppUnits(Metrics().GetScrollOffset());
StartAnimation(new WheelScrollAnimation(
*this, initialPosition, aEvent.mDeltaType));
}
nsPoint deltaInAppUnits =
CSSPoint::ToAppUnits(delta / mFrameMetrics.GetZoom());
CSSPoint::ToAppUnits(delta / Metrics().GetZoom());
// Convert velocity from ParentLayerPoints/ms to ParentLayerPoints/s and
// then to appunits/second.
@ -2331,7 +2330,7 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
CSSPoint::ToAppUnits(
ParentLayerPoint(mX.GetVelocity() * 1000.0f,
mY.GetVelocity() * 1000.0f) /
mFrameMetrics.GetZoom());
Metrics().GetZoom());
WheelScrollAnimation* animation = mAnimation->AsWheelScrollAnimation();
animation->UpdateDelta(aEvent.mTimeStamp, deltaInAppUnits, nsSize(velocity.x, velocity.y));
@ -2350,7 +2349,7 @@ AsyncPanZoomController::NotifyMozMouseScrollEvent(const nsString& aString) const
return;
}
controller->NotifyMozMouseScrollEvent(mFrameMetrics.GetScrollId(), aString);
controller->NotifyMozMouseScrollEvent(Metrics().GetScrollId(), aString);
}
nsEventStatus AsyncPanZoomController::OnPanMayBegin(const PanGestureInput& aEvent) {
@ -2935,7 +2934,7 @@ bool AsyncPanZoomController::AttemptScroll(ParentLayerPoint& aStartPoint,
}
if (!IsZero(adjustedDisplacement)) {
ScrollBy(adjustedDisplacement / mFrameMetrics.GetZoom());
ScrollBy(adjustedDisplacement / Metrics().GetZoom());
if (InputBlockState* block = GetCurrentInputBlock()) {
#if defined(MOZ_WIDGET_ANDROID)
if (block->AsTouchBlock() && (block->GetScrolledApzc() != this) && IsRootContent()) {
@ -3155,14 +3154,14 @@ void AsyncPanZoomController::SmoothScrollTo(const CSSPoint& aDestination) {
} else {
CancelAnimation();
SetState(SMOOTH_SCROLL);
nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
nsPoint initialPosition = CSSPoint::ToAppUnits(Metrics().GetScrollOffset());
// Convert velocity from ParentLayerPoints/ms to ParentLayerPoints/s and
// then to appunits/second.
nsPoint initialVelocity =
CSSPoint::ToAppUnits(
ParentLayerPoint(mX.GetVelocity() * 1000.0f,
mY.GetVelocity() * 1000.0f) /
mFrameMetrics.GetZoom());
Metrics().GetZoom());
nsPoint destination = CSSPoint::ToAppUnits(aDestination);
@ -3309,13 +3308,13 @@ void AsyncPanZoomController::AdjustScrollForSurfaceShift(const ScreenPoint& aShi
RecursiveMutexAutoLock lock(mRecursiveMutex);
CSSPoint adjustment =
ViewAs<ParentLayerPixel>(aShift, PixelCastJustification::ScreenIsParentLayerForRoot)
/ mFrameMetrics.GetZoom();
/ Metrics().GetZoom();
APZC_LOG("%p adjusting scroll position by %s for surface shift\n",
this, Stringify(adjustment).c_str());
CSSRect scrollRange = mFrameMetrics.CalculateScrollRange();
// Apply shift to mFrameMetrics.mScrollOffset.
CSSRect scrollRange = Metrics().CalculateScrollRange();
// Apply shift to Metrics().mScrollOffset.
SetScrollOffset(scrollRange.ClampPoint(
mFrameMetrics.GetScrollOffset() + adjustment));
Metrics().GetScrollOffset() + adjustment));
// Apply shift to mCompositedScrollOffset, since the dynamic toolbar expects
// the shift to take effect right away, without the usual frame delay.
mCompositedScrollOffset = scrollRange.ClampPoint(
@ -3325,36 +3324,36 @@ void AsyncPanZoomController::AdjustScrollForSurfaceShift(const ScreenPoint& aShi
}
void AsyncPanZoomController::SetScrollOffset(const CSSPoint& aOffset) {
mFrameMetrics.SetScrollOffset(aOffset);
mFrameMetrics.RecalculateViewportOffset();
Metrics().SetScrollOffset(aOffset);
Metrics().RecalculateViewportOffset();
}
void AsyncPanZoomController::ClampAndSetScrollOffset(const CSSPoint& aOffset) {
mFrameMetrics.ClampAndSetScrollOffset(aOffset);
mFrameMetrics.RecalculateViewportOffset();
Metrics().ClampAndSetScrollOffset(aOffset);
Metrics().RecalculateViewportOffset();
}
void AsyncPanZoomController::ScrollBy(const CSSPoint& aOffset) {
SetScrollOffset(mFrameMetrics.GetScrollOffset() + aOffset);
SetScrollOffset(Metrics().GetScrollOffset() + aOffset);
}
void AsyncPanZoomController::ScrollByAndClamp(const CSSPoint& aOffset) {
ClampAndSetScrollOffset(mFrameMetrics.GetScrollOffset() + aOffset);
ClampAndSetScrollOffset(Metrics().GetScrollOffset() + aOffset);
}
void AsyncPanZoomController::CopyScrollInfoFrom(const FrameMetrics& aFrameMetrics) {
mFrameMetrics.CopyScrollInfoFrom(aFrameMetrics);
mFrameMetrics.RecalculateViewportOffset();
Metrics().CopyScrollInfoFrom(aFrameMetrics);
Metrics().RecalculateViewportOffset();
}
void AsyncPanZoomController::ScaleWithFocus(float aScale,
const CSSPoint& aFocus) {
mFrameMetrics.ZoomBy(aScale);
Metrics().ZoomBy(aScale);
// We want to adjust the scroll offset such that the CSS point represented by aFocus remains
// at the same position on the screen before and after the change in zoom. The below code
// accomplishes this; see https://bugzilla.mozilla.org/show_bug.cgi?id=923431#c6 for an
// in-depth explanation of how.
SetScrollOffset((mFrameMetrics.GetScrollOffset() + aFocus) - (aFocus / aScale));
SetScrollOffset((Metrics().GetScrollOffset() + aFocus) - (aFocus / aScale));
}
/**
@ -3549,7 +3548,7 @@ bool AsyncPanZoomController::IsPannable() const {
bool AsyncPanZoomController::IsScrollInfoLayer() const {
RecursiveMutexAutoLock lock(mRecursiveMutex);
return mFrameMetrics.IsScrollInfoLayer();
return Metrics().IsScrollInfoLayer();
}
int32_t AsyncPanZoomController::GetLastTouchIdentifier() const {
@ -3561,7 +3560,7 @@ void AsyncPanZoomController::RequestContentRepaint(bool aUserAction) {
// Reinvoke this method on the repaint thread if it's not there already. It's
// important to do this before the call to CalculatePendingDisplayPort, so
// that CalculatePendingDisplayPort uses the most recent available version of
// mFrameMetrics, just before the paint request is dispatched to content.
// Metrics(). just before the paint request is dispatched to content.
RefPtr<GeckoContentController> controller = GetGeckoContentController();
if (!controller) {
return;
@ -3582,11 +3581,11 @@ void AsyncPanZoomController::RequestContentRepaint(bool aUserAction) {
RecursiveMutexAutoLock lock(mRecursiveMutex);
ParentLayerPoint velocity = GetVelocityVector();
mFrameMetrics.SetDisplayPortMargins(CalculatePendingDisplayPort(mFrameMetrics, velocity));
mFrameMetrics.SetUseDisplayPortMargins(true);
mFrameMetrics.SetPaintRequestTime(TimeStamp::Now());
mFrameMetrics.SetRepaintDrivenByUserAction(aUserAction);
RequestContentRepaint(mFrameMetrics, velocity);
Metrics().SetDisplayPortMargins(CalculatePendingDisplayPort(Metrics(), velocity));
Metrics().SetUseDisplayPortMargins(true);
Metrics().SetPaintRequestTime(TimeStamp::Now());
Metrics().SetRepaintDrivenByUserAction(aUserAction);
RequestContentRepaint(Metrics(), velocity);
}
/*static*/ CSSRect
@ -3683,7 +3682,7 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
mLastSampleTime = aSampleTime;
if (mAnimation) {
bool continueAnimation = mAnimation->Sample(mFrameMetrics, sampleTimeDelta);
bool continueAnimation = mAnimation->Sample(Metrics(), sampleTimeDelta);
bool wantsRepaints = mAnimation->WantsRepaints();
*aOutDeferredTasks = mAnimation->TakeDeferredTasks();
if (!continueAnimation) {
@ -3749,8 +3748,8 @@ bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime)
if (mCheckerboardEvent) {
mCheckerboardEvent->UpdateRendertraceProperty(
CheckerboardEvent::UserVisible,
CSSRect(mFrameMetrics.GetScrollOffset(),
mFrameMetrics.CalculateCompositedSizeInCssPixels()));
CSSRect(Metrics().GetScrollOffset(),
Metrics().CalculateCompositedSizeInCssPixels()));
}
}
}
@ -3771,7 +3770,7 @@ bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime)
CSSRect
AsyncPanZoomController::GetCurrentAsyncLayoutViewport(AsyncTransformConsumer aMode) const {
RecursiveMutexAutoLock lock(mRecursiveMutex);
MOZ_ASSERT(mFrameMetrics.IsRootContent(),
MOZ_ASSERT(Metrics().IsRootContent(),
"Only the root content APZC has a layout viewport");
if (aMode == eForCompositing && mScrollMetadata.IsApzForceDisabled()) {
return mLastContentPaintMetrics.GetViewport();
@ -3844,7 +3843,7 @@ AsyncPanZoomController::GetCurrentAsyncTransform(AsyncTransformConsumer aMode) c
* effectiveZoom * mTestAsyncZoom.scale;
LayerToParentLayerScale compositedAsyncZoom =
(effectiveZoom / mFrameMetrics.LayersPixelsPerCSSPixel()).ToScaleFactor();
(effectiveZoom / Metrics().LayersPixelsPerCSSPixel()).ToScaleFactor();
return AsyncTransform(
LayerToParentLayerScale(compositedAsyncZoom.scale * mTestAsyncZoom.scale),
-translation);
@ -3856,7 +3855,7 @@ AsyncPanZoomController::GetEffectiveLayoutViewport(AsyncTransformConsumer aMode)
if (gfxPrefs::APZFrameDelayEnabled() && aMode == eForCompositing) {
return mCompositedLayoutViewport;
}
return mFrameMetrics.GetViewport();
return Metrics().GetViewport();
}
CSSPoint
@ -3865,7 +3864,7 @@ AsyncPanZoomController::GetEffectiveScrollOffset(AsyncTransformConsumer aMode) c
if (gfxPrefs::APZFrameDelayEnabled() && aMode == eForCompositing) {
return mCompositedScrollOffset;
}
return mFrameMetrics.GetScrollOffset();
return Metrics().GetScrollOffset();
}
CSSToParentLayerScale2D
@ -3874,18 +3873,18 @@ AsyncPanZoomController::GetEffectiveZoom(AsyncTransformConsumer aMode) const
if (gfxPrefs::APZFrameDelayEnabled() && aMode == eForCompositing) {
return mCompositedZoom;
}
return mFrameMetrics.GetZoom();
return Metrics().GetZoom();
}
bool
AsyncPanZoomController::SampleCompositedAsyncTransform()
{
RecursiveMutexAutoLock lock(mRecursiveMutex);
if (mCompositedScrollOffset != mFrameMetrics.GetScrollOffset() ||
mCompositedZoom != mFrameMetrics.GetZoom()) {
mCompositedLayoutViewport = mFrameMetrics.GetViewport();
mCompositedScrollOffset = mFrameMetrics.GetScrollOffset();
mCompositedZoom = mFrameMetrics.GetZoom();
if (mCompositedScrollOffset != Metrics().GetScrollOffset() ||
mCompositedZoom != Metrics().GetZoom()) {
mCompositedLayoutViewport = Metrics().GetViewport();
mCompositedScrollOffset = Metrics().GetScrollOffset();
mCompositedZoom = Metrics().GetZoom();
return true;
}
return false;
@ -3924,9 +3923,9 @@ AsyncPanZoomController::GetCheckerboardMagnitude() const
{
RecursiveMutexAutoLock lock(mRecursiveMutex);
CSSPoint currentScrollOffset = mFrameMetrics.GetScrollOffset() + mTestAsyncScrollOffset;
CSSPoint currentScrollOffset = Metrics().GetScrollOffset() + mTestAsyncScrollOffset;
CSSRect painted = mLastContentPaintMetrics.GetDisplayPort() + mLastContentPaintMetrics.GetScrollOffset();
CSSRect visible = CSSRect(currentScrollOffset, mFrameMetrics.CalculateCompositedSizeInCssPixels());
CSSRect visible = CSSRect(currentScrollOffset, Metrics().CalculateCompositedSizeInCssPixels());
CSSIntRegion checkerboard;
// Round so as to minimize checkerboarding; if we're only showing fractional
@ -4004,14 +4003,14 @@ bool AsyncPanZoomController::IsCurrentlyCheckerboarding() const {
return false;
}
CSSPoint currentScrollOffset = mFrameMetrics.GetScrollOffset() + mTestAsyncScrollOffset;
CSSPoint currentScrollOffset = Metrics().GetScrollOffset() + mTestAsyncScrollOffset;
CSSRect painted = mLastContentPaintMetrics.GetDisplayPort() + mLastContentPaintMetrics.GetScrollOffset();
painted.Inflate(CSSMargin::FromAppUnits(nsMargin(1, 1, 1, 1))); // fuzz for rounding error
CSSRect visible = CSSRect(currentScrollOffset, mFrameMetrics.CalculateCompositedSizeInCssPixels());
CSSRect visible = CSSRect(currentScrollOffset, Metrics().CalculateCompositedSizeInCssPixels());
if (painted.Contains(visible)) {
return false;
}
APZC_LOG_FM(mFrameMetrics, "%p is currently checkerboarding (painted %s visble %s)",
APZC_LOG_FM(Metrics(), "%p is currently checkerboarding (painted %s visble %s)",
this, Stringify(painted).c_str(), Stringify(visible).c_str());
return true;
}
@ -4033,7 +4032,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
return;
}
// If the mFrameMetrics scroll offset is different from the last scroll offset
// If the Metrics scroll offset is different from the last scroll offset
// that the main-thread sent us, then we know that the user has been doing
// something that triggers a scroll. This check is the APZ equivalent of the
// check on the main-thread at
@ -4043,8 +4042,8 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
// how the main thread code does the same thing.
CSSPoint lastScrollOffset = mLastContentPaintMetadata.GetMetrics().GetScrollOffset();
bool userScrolled =
!FuzzyEqualsAdditive(mFrameMetrics.GetScrollOffset().x, lastScrollOffset.x) ||
!FuzzyEqualsAdditive(mFrameMetrics.GetScrollOffset().y, lastScrollOffset.y);
!FuzzyEqualsAdditive(Metrics().GetScrollOffset().x, lastScrollOffset.x) ||
!FuzzyEqualsAdditive(Metrics().GetScrollOffset().y, lastScrollOffset.y);
if (aLayerMetrics.GetScrollUpdateType() != FrameMetrics::ScrollOffsetUpdateType::ePending) {
mLastContentPaintMetadata = aScrollMetadata;
@ -4095,7 +4094,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
// to filter duplicate calls to NotifyLayersUpdated with the same scroll offset
// update message.
bool scrollOffsetUpdated = aLayerMetrics.GetScrollOffsetUpdated()
&& (aLayerMetrics.GetScrollGeneration() != mFrameMetrics.GetScrollGeneration());
&& (aLayerMetrics.GetScrollGeneration() != Metrics().GetScrollGeneration());
if (scrollOffsetUpdated && userScrolled &&
aLayerMetrics.GetScrollUpdateType() == FrameMetrics::ScrollOffsetUpdateType::eRestore) {
@ -4104,24 +4103,24 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
}
bool smoothScrollRequested = aLayerMetrics.GetDoSmoothScroll()
&& (aLayerMetrics.GetScrollGeneration() != mFrameMetrics.GetScrollGeneration());
&& (aLayerMetrics.GetScrollGeneration() != Metrics().GetScrollGeneration());
// TODO if we're in a drag and scrollOffsetUpdated is set then we want to
// ignore it
bool needContentRepaint = false;
bool viewportUpdated = false;
if (FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().Width(), mFrameMetrics.GetCompositionBounds().Width()) &&
FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().Height(), mFrameMetrics.GetCompositionBounds().Height())) {
if (FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().Width(), Metrics().GetCompositionBounds().Width()) &&
FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().Height(), Metrics().GetCompositionBounds().Height())) {
// Remote content has sync'd up to the composition geometry
// change, so we can accept the viewport it's calculated.
if (mFrameMetrics.GetViewport().Width() != aLayerMetrics.GetViewport().Width() ||
mFrameMetrics.GetViewport().Height() != aLayerMetrics.GetViewport().Height()) {
if (Metrics().GetViewport().Width() != aLayerMetrics.GetViewport().Width() ||
Metrics().GetViewport().Height() != aLayerMetrics.GetViewport().Height()) {
needContentRepaint = true;
viewportUpdated = true;
}
if (viewportUpdated || scrollOffsetUpdated) {
mFrameMetrics.SetViewport(aLayerMetrics.GetViewport());
Metrics().SetViewport(aLayerMetrics.GetViewport());
}
}
@ -4144,11 +4143,11 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
mExpectedGeckoMetrics = aLayerMetrics;
ShareCompositorFrameMetrics();
mCompositedLayoutViewport = mFrameMetrics.GetViewport();
mCompositedScrollOffset = mFrameMetrics.GetScrollOffset();
mCompositedZoom = mFrameMetrics.GetZoom();
mCompositedLayoutViewport = Metrics().GetViewport();
mCompositedScrollOffset = Metrics().GetScrollOffset();
mCompositedZoom = Metrics().GetZoom();
if (mFrameMetrics.GetDisplayPortMargins() != ScreenMargin()) {
if (Metrics().GetDisplayPortMargins() != ScreenMargin()) {
// A non-zero display port margin here indicates a displayport has
// been set by a previous APZC for the content at this guid. The
// scrollable rect may have changed since then, making the margins
@ -4158,11 +4157,11 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
}
} else {
// If we're not taking the aLayerMetrics wholesale we still need to pull
// in some things into our local mFrameMetrics because these things are
// determined by Gecko and our copy in mFrameMetrics may be stale.
// in some things into our local Metrics() because these things are
// determined by Gecko and our copy in Metrics() may be stale.
if (FuzzyEqualsAdditive(mFrameMetrics.GetCompositionBounds().Width(), aLayerMetrics.GetCompositionBounds().Width()) &&
mFrameMetrics.GetDevPixelsPerCSSPixel() == aLayerMetrics.GetDevPixelsPerCSSPixel() &&
if (FuzzyEqualsAdditive(Metrics().GetCompositionBounds().Width(), aLayerMetrics.GetCompositionBounds().Width()) &&
Metrics().GetDevPixelsPerCSSPixel() == aLayerMetrics.GetDevPixelsPerCSSPixel() &&
!viewportUpdated) {
// Any change to the pres shell resolution was requested by APZ and is
// already included in our zoom; however, other components of the
@ -4172,33 +4171,33 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
// aLayerMetrics.mZoom because the APZ may have additional async zoom
// since the repaint request.
gfxSize totalResolutionChange = aLayerMetrics.GetCumulativeResolution()
/ mFrameMetrics.GetCumulativeResolution();
/ Metrics().GetCumulativeResolution();
float presShellResolutionChange = aLayerMetrics.GetPresShellResolution()
/ mFrameMetrics.GetPresShellResolution();
/ Metrics().GetPresShellResolution();
if (presShellResolutionChange != 1.0f) {
needContentRepaint = true;
}
mFrameMetrics.ZoomBy(totalResolutionChange / presShellResolutionChange);
Metrics().ZoomBy(totalResolutionChange / presShellResolutionChange);
mCompositedZoom.xScale *= (totalResolutionChange / presShellResolutionChange).width;
mCompositedZoom.yScale *= (totalResolutionChange / presShellResolutionChange).height;
} else {
// Take the new zoom as either device scale or composition width or
// viewport size got changed (e.g. due to orientation change, or content
// changing the meta-viewport tag).
mFrameMetrics.SetZoom(aLayerMetrics.GetZoom());
Metrics().SetZoom(aLayerMetrics.GetZoom());
mCompositedZoom = aLayerMetrics.GetZoom();
mFrameMetrics.SetDevPixelsPerCSSPixel(aLayerMetrics.GetDevPixelsPerCSSPixel());
Metrics().SetDevPixelsPerCSSPixel(aLayerMetrics.GetDevPixelsPerCSSPixel());
}
bool scrollableRectChanged = false;
if (!mFrameMetrics.GetScrollableRect().IsEqualEdges(aLayerMetrics.GetScrollableRect())) {
mFrameMetrics.SetScrollableRect(aLayerMetrics.GetScrollableRect());
if (!Metrics().GetScrollableRect().IsEqualEdges(aLayerMetrics.GetScrollableRect())) {
Metrics().SetScrollableRect(aLayerMetrics.GetScrollableRect());
needContentRepaint = true;
scrollableRectChanged = true;
}
mFrameMetrics.SetCompositionBounds(aLayerMetrics.GetCompositionBounds());
mFrameMetrics.SetRootCompositionSize(aLayerMetrics.GetRootCompositionSize());
mFrameMetrics.SetPresShellResolution(aLayerMetrics.GetPresShellResolution());
mFrameMetrics.SetCumulativeResolution(aLayerMetrics.GetCumulativeResolution());
Metrics().SetCompositionBounds(aLayerMetrics.GetCompositionBounds());
Metrics().SetRootCompositionSize(aLayerMetrics.GetRootCompositionSize());
Metrics().SetPresShellResolution(aLayerMetrics.GetPresShellResolution());
Metrics().SetCumulativeResolution(aLayerMetrics.GetCumulativeResolution());
mScrollMetadata.SetHasScrollgrab(aScrollMetadata.GetHasScrollgrab());
mScrollMetadata.SetLineScrollAmount(aScrollMetadata.GetLineScrollAmount());
mScrollMetadata.SetPageScrollAmount(aScrollMetadata.GetPageScrollAmount());
@ -4211,14 +4210,14 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
mScrollMetadata.SetIsAutoDirRootContentRTL(
aScrollMetadata.IsAutoDirRootContentRTL());
mScrollMetadata.SetUsesContainerScrolling(aScrollMetadata.UsesContainerScrolling());
mFrameMetrics.SetIsScrollInfoLayer(aLayerMetrics.IsScrollInfoLayer());
Metrics().SetIsScrollInfoLayer(aLayerMetrics.IsScrollInfoLayer());
mScrollMetadata.SetForceDisableApz(aScrollMetadata.IsApzForceDisabled());
mScrollMetadata.SetDisregardedDirection(aScrollMetadata.GetDisregardedDirection());
mScrollMetadata.SetOverscrollBehavior(aScrollMetadata.GetOverscrollBehavior());
if (scrollOffsetUpdated) {
APZC_LOG("%p updating scroll offset from %s to %s\n", this,
ToString(mFrameMetrics.GetScrollOffset()).c_str(),
ToString(Metrics().GetScrollOffset()).c_str(),
ToString(aLayerMetrics.GetScrollOffset()).c_str());
// Send an acknowledgement with the new scroll generation so that any
@ -4229,8 +4228,8 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
// correct this we need to update mExpectedGeckoMetrics to be the
// last thing we know was painted by Gecko.
CopyScrollInfoFrom(aLayerMetrics);
mCompositedLayoutViewport = mFrameMetrics.GetViewport();
mCompositedScrollOffset = mFrameMetrics.GetScrollOffset();
mCompositedLayoutViewport = Metrics().GetViewport();
mCompositedScrollOffset = Metrics().GetScrollOffset();
mExpectedGeckoMetrics = aLayerMetrics;
// Cancel the animation (which might also trigger a repaint request)
@ -4253,7 +4252,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
// Even if we didn't accept a new scroll offset from content, the
// scrollable rect may have changed in a way that makes our local
// scroll offset out of bounds, so re-clamp it.
ClampAndSetScrollOffset(mFrameMetrics.GetScrollOffset());
ClampAndSetScrollOffset(Metrics().GetScrollOffset());
}
}
@ -4263,17 +4262,17 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
// the scroll update acknowledgement.
APZC_LOG("%p smooth scrolling from %s to %s in state %d\n", this,
Stringify(mFrameMetrics.GetScrollOffset()).c_str(),
Stringify(Metrics().GetScrollOffset()).c_str(),
Stringify(aLayerMetrics.GetSmoothScrollOffset()).c_str(),
mState);
// See comment on the similar code in the |if (scrollOffsetUpdated)| block
// above.
mFrameMetrics.CopySmoothScrollInfoFrom(aLayerMetrics);
Metrics().CopySmoothScrollInfoFrom(aLayerMetrics);
needContentRepaint = true;
mExpectedGeckoMetrics = aLayerMetrics;
SmoothScrollTo(mFrameMetrics.GetSmoothScrollOffset());
SmoothScrollTo(Metrics().GetSmoothScrollOffset());
}
if (needContentRepaint) {
@ -4283,9 +4282,17 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
UpdateSharedCompositorFrameMetrics();
}
FrameMetrics& AsyncPanZoomController::Metrics() {
return mScrollMetadata.GetMetrics();
}
const FrameMetrics& AsyncPanZoomController::Metrics() const {
return mScrollMetadata.GetMetrics();;
}
const FrameMetrics& AsyncPanZoomController::GetFrameMetrics() const {
mRecursiveMutex.AssertCurrentThreadIn();
return mFrameMetrics;
return mScrollMetadata.GetMetrics();;
}
const ScrollMetadata& AsyncPanZoomController::GetScrollMetadata() const {
@ -4331,18 +4338,18 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect, const uint32_t aFlags) {
// would have to be adjusted (as e.g. it would no longer be valid to take
// the minimum or maximum of the ratios of the widths and heights of the
// page rect and the composition bounds).
MOZ_ASSERT(mFrameMetrics.IsRootContent());
MOZ_ASSERT(mFrameMetrics.GetZoom().AreScalesSame());
MOZ_ASSERT(Metrics().IsRootContent());
MOZ_ASSERT(Metrics().GetZoom().AreScalesSame());
SetState(ANIMATING_ZOOM);
{
RecursiveMutexAutoLock lock(mRecursiveMutex);
ParentLayerRect compositionBounds = mFrameMetrics.GetCompositionBounds();
CSSRect cssPageRect = mFrameMetrics.GetScrollableRect();
CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset();
CSSToParentLayerScale currentZoom = mFrameMetrics.GetZoom().ToScaleFactor();
ParentLayerRect compositionBounds = Metrics().GetCompositionBounds();
CSSRect cssPageRect = Metrics().GetScrollableRect();
CSSPoint scrollOffset = Metrics().GetScrollOffset();
CSSToParentLayerScale currentZoom = Metrics().GetZoom().ToScaleFactor();
CSSToParentLayerScale targetZoom;
// The minimum zoom to prevent over-zoom-out.
@ -4377,7 +4384,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect, const uint32_t aFlags) {
}
if (zoomOut) {
CSSSize compositedSize = mFrameMetrics.CalculateCompositedSizeInCssPixels();
CSSSize compositedSize = Metrics().CalculateCompositedSizeInCssPixels();
float y = scrollOffset.y;
float newHeight =
cssPageRect.Width() * (compositedSize.height / compositedSize.width);
@ -4393,12 +4400,12 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect, const uint32_t aFlags) {
}
targetZoom.scale = clamped(targetZoom.scale, localMinZoom.scale, localMaxZoom.scale);
FrameMetrics endZoomToMetrics = mFrameMetrics;
FrameMetrics endZoomToMetrics = Metrics();
if (aFlags & PAN_INTO_VIEW_ONLY) {
targetZoom = currentZoom;
} else if(aFlags & ONLY_ZOOM_TO_DEFAULT_SCALE) {
CSSToParentLayerScale zoomAtDefaultScale =
mFrameMetrics.GetDevPixelsPerCSSPixel() * LayoutDeviceToParentLayerScale(1.0);
Metrics().GetDevPixelsPerCSSPixel() * LayoutDeviceToParentLayerScale(1.0);
if (targetZoom.scale > zoomAtDefaultScale.scale) {
// Only change the zoom if we are less than the default zoom
if (currentZoom.scale < zoomAtDefaultScale.scale) {
@ -4435,8 +4442,8 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect, const uint32_t aFlags) {
StartAnimation(new ZoomAnimation(
*this,
mFrameMetrics.GetScrollOffset(),
mFrameMetrics.GetZoom(),
Metrics().GetScrollOffset(),
Metrics().GetZoom(),
endZoomToMetrics.GetScrollOffset(),
endZoomToMetrics.GetZoom()));
@ -4562,7 +4569,7 @@ void AsyncPanZoomController::DispatchStateChangeNotification(PanZoomState aOldSt
if (APZCTreeManager* manager = GetApzcTreeManager()) {
AndroidDynamicToolbarAnimator* animator = manager->GetAndroidDynamicToolbarAnimator();
MOZ_ASSERT(animator);
animator->UpdateRootFrameMetrics(mFrameMetrics);
animator->UpdateRootFrameMetrics(Metrics());
}
#endif
@ -4593,9 +4600,9 @@ void AsyncPanZoomController::UpdateZoomConstraints(const ZoomConstraints& aConst
return;
}
CSSToParentLayerScale min = mFrameMetrics.GetDevPixelsPerCSSPixel()
CSSToParentLayerScale min = Metrics().GetDevPixelsPerCSSPixel()
* kViewportMinScale / ParentLayerToScreenScale(1);
CSSToParentLayerScale max = mFrameMetrics.GetDevPixelsPerCSSPixel()
CSSToParentLayerScale max = Metrics().GetDevPixelsPerCSSPixel()
* kViewportMaxScale / ParentLayerToScreenScale(1);
// inf float values and other bad cases should be sanitized by the code below.
@ -4646,7 +4653,7 @@ void AsyncPanZoomController::GetGuid(ScrollableLayerGuid* aGuidOut) const
ScrollableLayerGuid AsyncPanZoomController::GetGuid() const
{
return ScrollableLayerGuid(mLayersId, mFrameMetrics);
return ScrollableLayerGuid(mLayersId, Metrics());
}
void AsyncPanZoomController::UpdateSharedCompositorFrameMetrics()
@ -4658,7 +4665,7 @@ void AsyncPanZoomController::UpdateSharedCompositorFrameMetrics()
if (frame && mSharedLock && gfxPrefs::ProgressivePaint()) {
mSharedLock->Lock();
*frame = mFrameMetrics;
*frame = Metrics();
mSharedLock->Unlock();
}
}
@ -4683,7 +4690,7 @@ void AsyncPanZoomController::ShareCompositorFrameMetrics()
{ // scope the monitor, only needed to copy the FrameMetrics.
RecursiveMutexAutoLock lock(mRecursiveMutex);
*frame = mFrameMetrics;
*frame = Metrics();
}
// Get the process id of the content process
@ -4725,13 +4732,13 @@ Maybe<CSSPoint> AsyncPanZoomController::FindSnapPointNear(
const CSSPoint& aDestination, nsIScrollableFrame::ScrollUnit aUnit) {
mRecursiveMutex.AssertCurrentThreadIn();
APZC_LOG("%p scroll snapping near %s\n", this, Stringify(aDestination).c_str());
CSSRect scrollRange = mFrameMetrics.CalculateScrollRange();
CSSRect scrollRange = Metrics().CalculateScrollRange();
if (Maybe<nsPoint> snapPoint = ScrollSnapUtils::GetSnapPointForDestination(
mScrollMetadata.GetSnapInfo(),
aUnit,
CSSSize::ToAppUnits(mFrameMetrics.CalculateCompositedSizeInCssPixels()),
CSSSize::ToAppUnits(Metrics().CalculateCompositedSizeInCssPixels()),
CSSRect::ToAppUnits(scrollRange),
CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset()),
CSSPoint::ToAppUnits(Metrics().GetScrollOffset()),
CSSPoint::ToAppUnits(aDestination))) {
CSSPoint cssSnapPoint = CSSPoint::FromAppUnits(snapPoint.ref());
// GetSnapPointForDestination() can produce a destination that's outside
@ -4746,7 +4753,7 @@ Maybe<CSSPoint> AsyncPanZoomController::FindSnapPointNear(
void AsyncPanZoomController::ScrollSnapNear(const CSSPoint& aDestination) {
if (Maybe<CSSPoint> snapPoint =
FindSnapPointNear(aDestination, nsIScrollableFrame::DEVICE_PIXELS)) {
if (*snapPoint != mFrameMetrics.GetScrollOffset()) {
if (*snapPoint != Metrics().GetScrollOffset()) {
APZC_LOG("%p smooth scrolling to snap point %s\n", this, Stringify(*snapPoint).c_str());
SmoothScrollTo(*snapPoint);
}
@ -4755,7 +4762,7 @@ void AsyncPanZoomController::ScrollSnapNear(const CSSPoint& aDestination) {
void AsyncPanZoomController::ScrollSnap() {
RecursiveMutexAutoLock lock(mRecursiveMutex);
ScrollSnapNear(mFrameMetrics.GetScrollOffset());
ScrollSnapNear(Metrics().GetScrollOffset());
}
void AsyncPanZoomController::ScrollSnapToDestination() {
@ -4772,7 +4779,7 @@ void AsyncPanZoomController::ScrollSnapToDestination() {
if (velocity.y != 0.0f) {
predictedDelta.y = -velocity.y / log(1.0 - friction);
}
CSSPoint predictedDestination = mFrameMetrics.GetScrollOffset() + predictedDelta / mFrameMetrics.GetZoom();
CSSPoint predictedDestination = Metrics().GetScrollOffset() + predictedDelta / Metrics().GetZoom();
// If the fling will overscroll, don't scroll snap, because then the user
// user would not see any overscroll animation.
@ -4783,8 +4790,8 @@ void AsyncPanZoomController::ScrollSnapToDestination() {
"predictedDelta: %f, %f position: %f, %f "
"predictedDestination: %f, %f\n",
this, friction, velocity.x, velocity.y, (float)predictedDelta.x,
(float)predictedDelta.y, (float)mFrameMetrics.GetScrollOffset().x,
(float)mFrameMetrics.GetScrollOffset().y,
(float)predictedDelta.y, (float)Metrics().GetScrollOffset().x,
(float)Metrics().GetScrollOffset().y,
(float)predictedDestination.x, (float)predictedDestination.y);
ScrollSnapNear(predictedDestination);
@ -4803,8 +4810,8 @@ bool AsyncPanZoomController::MaybeAdjustDeltaForScrollSnapping(
}
RecursiveMutexAutoLock lock(mRecursiveMutex);
CSSToParentLayerScale2D zoom = mFrameMetrics.GetZoom();
CSSPoint destination = mFrameMetrics.CalculateScrollRange().ClampPoint(
CSSToParentLayerScale2D zoom = Metrics().GetZoom();
CSSPoint destination = Metrics().CalculateScrollRange().ClampPoint(
aStartPosition + (aDelta / zoom));
nsIScrollableFrame::ScrollUnit unit =
ScrollWheelInput::ScrollUnitForDeltaType(aEvent.mDeltaType);

View File

@ -517,6 +517,13 @@ public:
bool OverscrollBehaviorAllowsSwipe() const;
//|Metrics()| and |Metrics() const| are getter functions that both return
//mScrollMetadata.mMetrics
const FrameMetrics& Metrics() const;
FrameMetrics& Metrics();
private:
// Get whether the horizontal content of the honoured target of auto-dir
// scrolling starts from right to left. If you don't know of auto-dir
@ -887,13 +894,12 @@ protected:
PlatformSpecificStateBase* GetPlatformSpecificState();
protected:
// Both |mFrameMetrics| and |mLastContentPaintMetrics| are protected by the
// monitor. Do not read from or modify either of them without locking.
// Both |mScrollMetadata| and |mLastContentPaintMetrics| are protected by the
// monitor. Do not read from or modify them without locking.
ScrollMetadata mScrollMetadata;
FrameMetrics& mFrameMetrics; // for convenience, refers to mScrollMetadata.mMetrics
// Protects |mFrameMetrics|, |mLastContentPaintMetrics|, and |mState|.
// Before manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the
// Protects |mScrollMetadata|, |mLastContentPaintMetrics| and |mState|.
// Before manipulating |mScrollMetadata| or |mLastContentPaintMetrics| the
// monitor should be held. When setting |mState|, either the SetState()
// function can be used, or the monitor can be held and then |mState| updated.
// IMPORTANT: See the note about lock ordering at the top of APZCTreeManager.h.
@ -931,7 +937,7 @@ private:
FrameMetrics mExpectedGeckoMetrics;
// These variables cache the layout viewport, scroll offset, and zoom stored
// in |mFrameMetrics| the last time SampleCompositedAsyncTransform() was
// in |Metrics()| the last time SampleCompositedAsyncTransform() was
// called.
CSSRect mCompositedLayoutViewport;
CSSPoint mCompositedScrollOffset;
@ -1059,20 +1065,20 @@ private:
/**
* Samples the composited async transform, making the result of
* |GetCurrentAsyncTransform(eForCompositing)| and similar functions reflect
* the async scroll offset and zoom stored in |mFrameMetrics|.
* the async scroll offset and zoom stored in |Metrics()|.
*
* Returns true if the newly sampled value is different from the previously
* sampled value.
*
* (This is only relevant when |gfxPrefs::APZFrameDelayEnabled() == true|.
* Otherwise, GetCurrentAsyncTransform() always reflects what's stored in
* |mFrameMetrics| immediately, without any delay.)
* |Metrics()| immediately, without any delay.)
*/
bool SampleCompositedAsyncTransform();
/*
* Helper functions to query the async layout viewport, scroll offset, and
* zoom either directly from |mFrameMetrics|, or from cached variables that
* zoom either directly from |Metrics()|, or from cached variables that
* store the required value from the last time it was sampled by calling
* SampleCompositedAsyncTransform(), depending on who is asking.
*/
@ -1273,7 +1279,7 @@ public:
bool IsRootContent() const {
RecursiveMutexAutoLock lock(mRecursiveMutex);
return mFrameMetrics.IsRootContent();
return Metrics().IsRootContent();
}
private:
@ -1427,7 +1433,7 @@ private:
RefPtr<ipc::SharedMemoryBasic> mSharedFrameMetricsBuffer;
CrossProcessMutex* mSharedLock;
/**
* Called when ever mFrameMetrics is updated so that if it is being
* Called when ever Metrics() is updated so that if it is being
* shared with the content process the shared FrameMetrics may be updated.
*/
void UpdateSharedCompositorFrameMetrics();

View File

@ -104,7 +104,7 @@ public:
* Return the amount of overscroll on this axis, in ParentLayer pixels.
*
* If this amount is nonzero, the relevant component of
* mAsyncPanZoomController->mFrameMetrics.mScrollOffset must be at its
* mAsyncPanZoomController->Metrics().mScrollOffset must be at its
* extreme allowed value in the relevant direction (that is, it must be at
* its maximum value if we are overscrolled at our composition length, and
* at its minimum value if we are overscrolled at the origin).

View File

@ -227,6 +227,7 @@ protected:
return mcc->Time();
}
private:
RefPtr<MockContentControllerDelayed> mcc;
};
@ -269,12 +270,12 @@ public:
void SetFrameMetrics(const FrameMetrics& metrics) {
RecursiveMutexAutoLock lock(mRecursiveMutex);
mFrameMetrics = metrics;
Metrics() = metrics;
}
FrameMetrics& GetFrameMetrics() {
RecursiveMutexAutoLock lock(mRecursiveMutex);
return mFrameMetrics;
return mScrollMetadata.GetMetrics();
}
ScrollMetadata& GetScrollMetadata() {
@ -284,7 +285,7 @@ public:
const FrameMetrics& GetFrameMetrics() const {
RecursiveMutexAutoLock lock(mRecursiveMutex);
return mFrameMetrics;
return mScrollMetadata.GetMetrics();
}
using AsyncPanZoomController::GetVelocityVector;

View File

@ -9,6 +9,7 @@
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Filters.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/PodOperations.h"
#include "gfxContext.h"
@ -763,7 +764,7 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
uint32_t type = atts.GetUint(eColorMatrixType);
const nsTArray<float>& values = atts.GetFloats(eColorMatrixValues);
if (NS_FAILED(ComputeColorMatrix(type, values, colorMatrix)) ||
PodEqual(colorMatrix, identityMatrix)) {
ArrayEqual(colorMatrix, identityMatrix)) {
RefPtr<FilterNode> filter(aSources[0]);
return filter.forget();
}
@ -974,7 +975,7 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
// All-zero coefficients sometimes occur in junk filters.
if (!filter ||
(coefficients.Length() == ArrayLength(allZero) &&
PodEqual(coefficients.Elements(), allZero, ArrayLength(allZero)))) {
ArrayEqual(coefficients.Elements(), allZero, ArrayLength(allZero)))) {
return nullptr;
}
filter->SetAttribute(ATT_ARITHMETIC_COMBINE_COEFFICIENTS,

View File

@ -5,8 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/gfx/Swizzle.h"
#include "mozilla/PodOperations.h"
using namespace mozilla;
using namespace mozilla::gfx;
@ -50,17 +50,17 @@ TEST(Moz2D, PremultiplyData) {
PremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out, check_bgra));
EXPECT_TRUE(ArrayEqual(out, check_bgra));
PremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out, sizeof(in_bgra), SurfaceFormat::R8G8B8A8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out, check_rgba));
EXPECT_TRUE(ArrayEqual(out, check_rgba));
PremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out, sizeof(in_bgra), SurfaceFormat::A8R8G8B8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out, check_argb));
EXPECT_TRUE(ArrayEqual(out, check_argb));
}
TEST(Moz2D, UnpremultiplyData) {
@ -103,17 +103,17 @@ TEST(Moz2D, UnpremultiplyData) {
UnpremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out, check_bgra));
EXPECT_TRUE(ArrayEqual(out, check_bgra));
UnpremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out, sizeof(in_bgra), SurfaceFormat::R8G8B8A8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out, check_rgba));
EXPECT_TRUE(ArrayEqual(out, check_rgba));
UnpremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out, sizeof(in_bgra), SurfaceFormat::A8R8G8B8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out, check_argb));
EXPECT_TRUE(ArrayEqual(out, check_argb));
}
TEST(Moz2D, SwizzleData) {
@ -199,42 +199,42 @@ TEST(Moz2D, SwizzleData) {
SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out, sizeof(out), SurfaceFormat::B8G8R8A8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out, check_bgra));
EXPECT_TRUE(ArrayEqual(out, check_bgra));
SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out, sizeof(out), SurfaceFormat::R8G8B8A8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out, check_rgba));
EXPECT_TRUE(ArrayEqual(out, check_rgba));
SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out, sizeof(out), SurfaceFormat::A8R8G8B8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out, check_argb));
EXPECT_TRUE(ArrayEqual(out, check_argb));
SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out, sizeof(out), SurfaceFormat::R8G8B8X8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out, check_rgbx));
EXPECT_TRUE(ArrayEqual(out, check_rgbx));
SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out24, sizeof(out24), SurfaceFormat::B8G8R8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out24, check_bgr));
EXPECT_TRUE(ArrayEqual(out24, check_bgr));
SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out24, sizeof(out24), SurfaceFormat::R8G8B8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out24, check_rgb));
EXPECT_TRUE(ArrayEqual(out24, check_rgb));
SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8,
out8, sizeof(out8), SurfaceFormat::A8,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out8, check_a));
EXPECT_TRUE(ArrayEqual(out8, check_a));
SwizzleData(SurfaceFormat::A8R8G8B8_UINT32 == SurfaceFormat::A8R8G8B8 ? check_argb : check_bgra,
sizeof(in_bgra), SurfaceFormat::A8R8G8B8_UINT32,
reinterpret_cast<uint8_t*>(out16), sizeof(out16), SurfaceFormat::R5G6B5_UINT16,
IntSize(5, 1));
EXPECT_TRUE(PodEqual(out16, check_16));
EXPECT_TRUE(ArrayEqual(out16, check_16));
}

View File

@ -484,13 +484,14 @@ ConstructSavedFrameStackSlow(JSContext* cx,
// by an offline heap snapshot from an older SpiderMonkey/Firefox version to
// break. Consider this enum append only.
enum class CoarseType: uint32_t {
Other = 0,
Object = 1,
Script = 2,
String = 3,
Other = 0,
Object = 1,
Script = 2,
String = 3,
DOMNode = 4,
FIRST = Other,
LAST = String
FIRST = Other,
LAST = DOMNode
};
inline uint32_t
@ -619,6 +620,13 @@ class JS_PUBLIC_API(Base) {
"hasAllocationStack and allocationStack.");
}
// In some cases, Concrete<T> can return a more descriptive
// referent type name than simply `T`. This method returns an
// identifier as specific as is efficiently available.
// The string returned is borrowed from the ubi::Node's referent.
// If nothing more specific than typeName() is available, return nullptr.
virtual const char16_t* descriptiveTypeName() const { return nullptr; }
// Methods for JSObject Referents
//
// These methods are only semantically valid if the referent is either a
@ -778,12 +786,13 @@ class Node {
// not all!) JSObjects can be exposed.
JS::Value exposeToJS() const;
CoarseType coarseType() const { return base()->coarseType(); }
const char16_t* typeName() const { return base()->typeName(); }
JS::Zone* zone() const { return base()->zone(); }
JS::Compartment* compartment() const { return base()->compartment(); }
JS::Realm* realm() const { return base()->realm(); }
const char* jsObjectClassName() const { return base()->jsObjectClassName(); }
CoarseType coarseType() const { return base()->coarseType(); }
const char16_t* typeName() const { return base()->typeName(); }
JS::Zone* zone() const { return base()->zone(); }
JS::Compartment* compartment() const { return base()->compartment(); }
JS::Realm* realm() const { return base()->realm(); }
const char* jsObjectClassName() const { return base()->jsObjectClassName(); }
const char16_t* descriptiveTypeName() const { return base()->descriptiveTypeName(); }
MOZ_MUST_USE bool jsObjectConstructorName(JSContext* cx, UniqueTwoByteChars& outName) const {
return base()->jsObjectConstructorName(cx, outName);
}

View File

@ -30,6 +30,8 @@
// - objects with a specific [[Class]] *
// - strings
// - scripts
// - DOM nodes
// - nsINodes with a specific name (found in nsINode::NodeName()) *
// - all other Node types
// - nodes with a specific ubi::Node::typeName *
//
@ -47,7 +49,8 @@
// {
// by: "coarseType",
// objects: { by: "objectClass" },
// other: { by: "internalType" }
// other: { by: "internalType" },
// domNode: { by: "descriptiveType" }
// }
//
// we would build the following tree of CountType subclasses:
@ -59,6 +62,8 @@
// strings: SimpleCount
// other: ByUbinodeType
// each type: SimpleCount
// domNode: ByDomObjectClass
// each type: SimpleCount
//
// The interior nodes are all breakdown types that categorize nodes according to
// one characteristic or another; and the leaf nodes are all SimpleType.

View File

@ -275,13 +275,15 @@ Function Properties of the `Debugger.Memory.prototype` Object
{ "count": 1616, "bytes": 93240 }
Here is a breakdown that groups JavaScript objects by their class name, and
non-string, non-script items by their C++ type name:
Here is a breakdown that groups JavaScript objects by their class name,
non-string, non-script items by their C++ type name, and DOM nodes with
their node name:
{
by: "coarseType",
objects: { by: "objectClass" },
other: { by: "internalType" }
other: { by: "internalType" },
domNode: { by: "descriptiveType" }
}
which produces a result like this:
@ -300,6 +302,9 @@ Function Properties of the `Debugger.Memory.prototype` Object
"js::Shape": { "count": 450, "bytes": 0 },
"js::BaseShape": { "count": 21, "bytes": 0 },
"js::ObjectGroup": { "count": 17, "bytes": 0 }
},
"domNode": {
"#text": { "count": 1, "bytes": 12 }
}
}
@ -370,7 +375,7 @@ Function Properties of the `Debugger.Memory.prototype` Object
The results for non-object items appear as the value of the property
named `"other"`.
<code>{ by: "coarseType", objects:<i>objects</i>, scripts:<i>scripts</i>, strings:<i>strings</i>, other:<i>other</i> }</code>
<code>{ by: "coarseType", objects:<i>objects</i>, scripts:<i>scripts</i>, strings:<i>strings</i>, domNode:<i>domNode</i>, other:<i>other</i> }</code>
: Group items by their coarse type.
Use the breakdown value <i>objects</i> for items that are JavaScript
@ -382,6 +387,8 @@ Function Properties of the `Debugger.Memory.prototype` Object
Use the breakdown value <i>strings</i> for JavaScript strings.
Use the breakdown value <i>domNode</i> for DOM nodes.
Use the breakdown value <i>other</i> for items that don't fit into any of
the above categories.
@ -393,6 +400,7 @@ Function Properties of the `Debugger.Memory.prototype` Object
"objects": <i>result</i>,
"scripts": <i>result</i>,
"strings": <i>result</i>,
"domNode:" <i>result</i>,
"other": <i>result</i>
}
</code></pre>
@ -438,6 +446,7 @@ Function Properties of the `Debugger.Memory.prototype` Object
{
by: "coarseType",
objects: { by: "objectClass" },
domNode: { by: "descriptiveType" },
other: { by: "internalType" }
}
</code></pre>
@ -449,6 +458,7 @@ Function Properties of the `Debugger.Memory.prototype` Object
objects: { <i>class</i>: <i>count</i>, ... },
scripts: <i>count</i>,
strings: <i>count</i>,
domNode: { <i>node name</i>: <i>count</i>, ... },
other: { <i>type name</i>: <i>count</i>, ... }
}
</code></pre>

View File

@ -6,6 +6,7 @@
#include "jit/CacheIRCompiler.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/ScopeExit.h"
#include <utility>
@ -1165,7 +1166,7 @@ CacheIRStubKey::match(const CacheIRStubKey& entry, const CacheIRStubKey::Lookup&
if (entry.stubInfo->codeLength() != l.length)
return false;
if (!mozilla::PodEqual(entry.stubInfo->code(), l.code, l.length))
if (!mozilla::ArrayEqual(entry.stubInfo->code(), l.code, l.length))
return false;
return true;

View File

@ -3,12 +3,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ArrayUtils.h"
#include "mozilla/PodOperations.h"
#include "jsapi-tests/tests.h"
using mozilla::ArrayEqual;
using mozilla::ArrayLength;
using mozilla::PodEqual;
static const char16_t arr[] = {
'h', 'i', ',', 'd', 'o', 'n', '\'', 't', ' ', 'd', 'e', 'l', 'e', 't', 'e', ' ', 'm', 'e', '\0'
@ -27,7 +26,7 @@ static const JSStringFinalizer finalizer2 = { finalize_str };
static void
finalize_str(const JSStringFinalizer* fin, char16_t* chars)
{
if (chars && PodEqual(const_cast<const char16_t*>(chars), arr, arrlen)) {
if (chars && ArrayEqual(chars, arr, arrlen)) {
if (fin == &finalizer1) {
++finalized1;
} else if (fin == &finalizer2) {

View File

@ -127,14 +127,13 @@ using namespace js::shell;
using js::shell::RCFile;
using mozilla::ArrayEqual;
using mozilla::ArrayLength;
using mozilla::Atomic;
using mozilla::MakeScopeExit;
using mozilla::Maybe;
using mozilla::Nothing;
using mozilla::NumberEqualsInt32;
using mozilla::PodCopy;
using mozilla::PodEqual;
using mozilla::TimeDuration;
using mozilla::TimeStamp;
@ -2074,7 +2073,7 @@ Evaluate(JSContext* cx, unsigned argc, Value* vp)
return false;
}
if (!PodEqual(loadBuffer.begin(), saveBuffer.begin(), loadBuffer.length())) {
if (!ArrayEqual(loadBuffer.begin(), saveBuffer.begin(), loadBuffer.length())) {
JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr,
JSSMSG_CACHE_EQ_CONTENT_FAILED);
return false;
@ -5582,7 +5581,7 @@ SingleStepCallback(void* arg, jit::Simulator* sim, void* pc)
// Only append the stack if it differs from the last stack.
if (sc->stacks.empty() ||
sc->stacks.back().length() != stack.length() ||
!PodEqual(sc->stacks.back().begin(), stack.begin(), stack.length()))
!ArrayEqual(sc->stacks.back().begin(), stack.begin(), stack.length()))
{
if (!sc->stacks.append(std::move(stack)))
oomUnsafe.crash("stacks.append");

View File

@ -7,6 +7,7 @@
#ifndef util_Text_h
#define util_Text_h
#include "mozilla/ArrayUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/TextUtils.h"
@ -54,26 +55,11 @@ namespace js {
class StringBuffer;
template <typename Char1, typename Char2>
inline bool
EqualChars(const Char1* s1, const Char2* s2, size_t len);
template <typename Char1>
inline bool
EqualChars(const Char1* s1, const Char1* s2, size_t len)
{
return mozilla::PodEqual(s1, s2, len);
}
template <typename Char1, typename Char2>
inline bool
EqualChars(const Char1* s1, const Char2* s2, size_t len)
{
for (const Char1* s1end = s1 + len; s1 < s1end; s1++, s2++) {
if (*s1 != *s2)
return false;
}
return true;
return mozilla::ArrayEqual(s1, s2, len);
}
// Return less than, equal to, or greater than zero depending on whether

View File

@ -102,6 +102,7 @@
macro(direction, direction, "direction") \
macro(displayURL, displayURL, "displayURL") \
macro(do, do_, "do") \
macro(domNode, domNode, "domNode") \
macro(done, done, "done") \
macro(dotGenerator, dotGenerator, ".generator") \
macro(dotThis, dotThis, ".this") \

View File

@ -8,6 +8,7 @@
#include "vm/Iteration.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Likely.h"
#include "mozilla/Maybe.h"
@ -47,10 +48,10 @@
using namespace js;
using namespace js::gc;
using mozilla::ArrayEqual;
using mozilla::DebugOnly;
using mozilla::Maybe;
using mozilla::PodCopy;
using mozilla::PodEqual;
typedef Rooted<PropertyIteratorObject*> RootedPropertyIteratorObject;
@ -793,8 +794,8 @@ IteratorHashPolicy::match(PropertyIteratorObject* obj, const Lookup& lookup)
if (ni->guardKey() != lookup.key || ni->guardCount() != lookup.numGuards)
return false;
return PodEqual(reinterpret_cast<ReceiverGuard*>(ni->guardsBegin()), lookup.guards,
ni->guardCount());
return ArrayEqual(reinterpret_cast<ReceiverGuard*>(ni->guardsBegin()), lookup.guards,
ni->guardCount());
}
static inline bool

View File

@ -96,14 +96,14 @@ js::AtomHasher::match(const AtomStateEntry& entry, const Lookup& lookup)
if (key->hasLatin1Chars()) {
const Latin1Char* keyChars = key->latin1Chars(lookup.nogc);
if (lookup.isLatin1)
return mozilla::PodEqual(keyChars, lookup.latin1Chars, lookup.length);
return mozilla::ArrayEqual(keyChars, lookup.latin1Chars, lookup.length);
return EqualChars(keyChars, lookup.twoByteChars, lookup.length);
}
const char16_t* keyChars = key->twoByteChars(lookup.nogc);
if (lookup.isLatin1)
return EqualChars(lookup.latin1Chars, keyChars, lookup.length);
return mozilla::PodEqual(keyChars, lookup.twoByteChars, lookup.length);
return mozilla::ArrayEqual(keyChars, lookup.twoByteChars, lookup.length);
}
inline JSAtom*

View File

@ -9,10 +9,10 @@
#ifndef vm_JSScript_h
#define vm_JSScript_h
#include "mozilla/ArrayUtils.h"
#include "mozilla/Atomics.h"
#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/PodOperations.h"
#include "mozilla/Variant.h"
#include "jstypes.h"
@ -886,7 +886,7 @@ struct ScriptBytecodeHasher
return false;
if (entry->numNotes() != data->numNotes())
return false;
return mozilla::PodEqual<uint8_t>(entry->data(), data->data(), data->dataLength());
return mozilla::ArrayEqual<uint8_t>(entry->data(), data->data(), data->dataLength());
}
};

View File

@ -6,6 +6,7 @@
#include "vm/StringType-inl.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/MathAlgorithms.h"
@ -30,11 +31,11 @@
using namespace js;
using mozilla::ArrayEqual;
using mozilla::IsAsciiDigit;
using mozilla::IsNegativeZero;
using mozilla::IsSame;
using mozilla::PodCopy;
using mozilla::PodEqual;
using mozilla::RangedPtr;
using mozilla::RoundUpPow2;
using mozilla::Unused;
@ -846,13 +847,13 @@ js::EqualChars(JSLinearString* str1, JSLinearString* str2)
AutoCheckCannotGC nogc;
if (str1->hasTwoByteChars()) {
if (str2->hasTwoByteChars())
return PodEqual(str1->twoByteChars(nogc), str2->twoByteChars(nogc), len);
return ArrayEqual(str1->twoByteChars(nogc), str2->twoByteChars(nogc), len);
return EqualChars(str2->latin1Chars(nogc), str1->twoByteChars(nogc), len);
}
if (str2->hasLatin1Chars())
return PodEqual(str1->latin1Chars(nogc), str2->latin1Chars(nogc), len);
return ArrayEqual(str1->latin1Chars(nogc), str2->latin1Chars(nogc), len);
return EqualChars(str1->latin1Chars(nogc), str2->twoByteChars(nogc), len);
}
@ -868,14 +869,14 @@ js::HasSubstringAt(JSLinearString* text, JSLinearString* pat, size_t start)
if (text->hasLatin1Chars()) {
const Latin1Char* textChars = text->latin1Chars(nogc) + start;
if (pat->hasLatin1Chars())
return PodEqual(textChars, pat->latin1Chars(nogc), patLen);
return ArrayEqual(textChars, pat->latin1Chars(nogc), patLen);
return EqualChars(textChars, pat->twoByteChars(nogc), patLen);
}
const char16_t* textChars = text->twoByteChars(nogc) + start;
if (pat->hasTwoByteChars())
return PodEqual(textChars, pat->twoByteChars(nogc), patLen);
return ArrayEqual(textChars, pat->twoByteChars(nogc), patLen);
return EqualChars(pat->latin1Chars(nogc), textChars, patLen);
}
@ -991,7 +992,7 @@ js::StringEqualsAscii(JSLinearString* str, const char* asciiBytes)
AutoCheckCannotGC nogc;
return str->hasLatin1Chars()
? PodEqual(latin1, str->latin1Chars(nogc), length)
? ArrayEqual(latin1, str->latin1Chars(nogc), length)
: EqualChars(latin1, str->twoByteChars(nogc), length);
}
@ -1757,7 +1758,7 @@ ExternalStringCache::lookup(const char16_t* chars, size_t len) const
// Compare the chars. Don't do this for long strings as it will be
// faster to allocate a new external string.
static const size_t MaxLengthForCharComparison = 100;
if (len <= MaxLengthForCharComparison && PodEqual(chars, strChars, len))
if (len <= MaxLengthForCharComparison && ArrayEqual(chars, strChars, len))
return str;
}

View File

@ -177,7 +177,7 @@ BucketCount::report(JSContext* cx, CountBase& countBase, MutableHandleValue repo
// A type that categorizes nodes by their JavaScript type -- 'objects',
// 'strings', 'scripts', and 'other' -- and then passes the nodes to child
// 'strings', 'scripts', 'domNode', and 'other' -- and then passes the nodes to child
// types.
//
// Implementation details of scripts like jitted code are counted under
@ -187,36 +187,42 @@ class ByCoarseType : public CountType {
CountTypePtr scripts;
CountTypePtr strings;
CountTypePtr other;
CountTypePtr domNode;
struct Count : CountBase {
Count(CountType& type,
CountBasePtr& objects,
CountBasePtr& scripts,
CountBasePtr& strings,
CountBasePtr& other)
CountBasePtr& other,
CountBasePtr& domNode)
: CountBase(type),
objects(std::move(objects)),
scripts(std::move(scripts)),
strings(std::move(strings)),
other(std::move(other))
other(std::move(other)),
domNode(std::move(domNode))
{ }
CountBasePtr objects;
CountBasePtr scripts;
CountBasePtr strings;
CountBasePtr other;
CountBasePtr domNode;
};
public:
ByCoarseType(CountTypePtr& objects,
CountTypePtr& scripts,
CountTypePtr& strings,
CountTypePtr& other)
CountTypePtr& other,
CountTypePtr& domNode)
: CountType(),
objects(std::move(objects)),
scripts(std::move(scripts)),
strings(std::move(strings)),
other(std::move(other))
other(std::move(other)),
domNode(std::move(domNode))
{ }
void destructCount(CountBase& countBase) override {
@ -237,15 +243,17 @@ ByCoarseType::makeCount()
CountBasePtr scriptsCount(scripts->makeCount());
CountBasePtr stringsCount(strings->makeCount());
CountBasePtr otherCount(other->makeCount());
CountBasePtr domNodeCount(domNode->makeCount());
if (!objectsCount || !scriptsCount || !stringsCount || !otherCount)
if (!objectsCount || !scriptsCount || !stringsCount || !otherCount || !domNodeCount)
return CountBasePtr(nullptr);
return CountBasePtr(js_new<Count>(*this,
objectsCount,
scriptsCount,
stringsCount,
otherCount));
otherCount,
domNodeCount));
}
void
@ -256,6 +264,7 @@ ByCoarseType::traceCount(CountBase& countBase, JSTracer* trc)
count.scripts->trace(trc);
count.strings->trace(trc);
count.other->trace(trc);
count.domNode->trace(trc);
}
bool
@ -272,6 +281,8 @@ ByCoarseType::count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, co
return count.strings->count(mallocSizeOf, node);
case JS::ubi::CoarseType::Other:
return count.other->count(mallocSizeOf, node);
case JS::ubi::CoarseType::DOMNode:
return count.domNode->count(mallocSizeOf, node);
default:
MOZ_CRASH("bad JS::ubi::CoarseType in JS::ubi::ByCoarseType::count");
return false;
@ -306,6 +317,10 @@ ByCoarseType::report(JSContext* cx, CountBase& countBase, MutableHandleValue rep
if (!count.other->report(cx, &otherReport) ||
!DefineDataProperty(cx, obj, cx->names().other, otherReport))
return false;
RootedValue domReport(cx);
if (!count.domNode->report(cx, &domReport) ||
!DefineDataProperty(cx, obj, cx->names().domNode, domReport))
return false;
report.setObject(*obj);
return true;
@ -386,6 +401,51 @@ countMapToObject(JSContext* cx, Map& map, GetName getName) {
return obj;
}
template <class Map, class GetName>
static PlainObject*
countMap16ToObject(JSContext* cx, Map& map, GetName getName) {
// Build a vector of pointers to entries; sort by total; and then use
// that to build the result object. This makes the ordering of entries
// more interesting, and a little less non-deterministic.
JS::ubi::Vector<typename Map::Entry*> entries;
if (!entries.reserve(map.count())) {
ReportOutOfMemory(cx);
return nullptr;
}
for (auto r = map.all(); !r.empty(); r.popFront())
entries.infallibleAppend(&r.front());
if (entries.length()) {
qsort(entries.begin(), entries.length(), sizeof(*entries.begin()),
compareEntries<typename Map::Entry>);
}
RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx));
if (!obj)
return nullptr;
for (auto& entry : entries) {
CountBasePtr& thenCount = entry->value();
RootedValue thenReport(cx);
if (!thenCount->report(cx, &thenReport))
return nullptr;
const char16_t* name = getName(entry->key());
MOZ_ASSERT(name);
JSAtom* atom = AtomizeChars(cx, name, js_strlen(name));
if (!atom)
return nullptr;
RootedId entryId(cx, AtomToId(atom));
if (!DefineDataProperty(cx, obj, entryId, thenReport))
return nullptr;
}
return obj;
}
// A type that categorizes nodes that are JSObjects by their class name,
// and places all other nodes in an 'other' category.
@ -492,6 +552,111 @@ ByObjectClass::report(JSContext* cx, CountBase& countBase, MutableHandleValue re
return true;
}
class ByDomObjectClass : public CountType {
// A table mapping descriptive names to their counts.
using UniqueC16String = JS::UniqueTwoByteChars;
struct UniqueC16StringHasher
{
using Lookup = UniqueC16String;
static js::HashNumber hash(const Lookup& lookup) {
return mozilla::HashString(lookup.get());
}
static bool match(const UniqueC16String& key, const Lookup& lookup) {
return CompareChars(key.get(), js_strlen(key.get()), lookup.get(),
js_strlen(lookup.get())) == 0;
}
};
using Table = HashMap<UniqueC16String,
CountBasePtr,
UniqueC16StringHasher,
SystemAllocPolicy>;
using Entry = Table::Entry;
struct Count : public CountBase {
Table table;
explicit Count(CountType& type) : CountBase(type) { }
bool init() { return table.init(); }
};
CountTypePtr classesType;
public:
explicit ByDomObjectClass(CountTypePtr& classesType)
: CountType(),
classesType(std::move(classesType))
{ }
void destructCount(CountBase& countBase) override {
Count& count = static_cast<Count&>(countBase);
count.~Count();
}
CountBasePtr makeCount() override;
void traceCount(CountBase& countBase, JSTracer* trc) override;
bool count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node) override;
bool report(JSContext* cx, CountBase& countBase, MutableHandleValue report) override;
};
CountBasePtr
ByDomObjectClass::makeCount()
{
auto count = js::MakeUnique<Count>(*this);
if (!count || !count->init())
return nullptr;
return CountBasePtr(count.release());
}
void
ByDomObjectClass::traceCount(CountBase& countBase, JSTracer* trc)
{
Count& count = static_cast<Count&>(countBase);
for (Table::Range r = count.table.all(); !r.empty(); r.popFront())
r.front().value()->trace(trc);
}
bool
ByDomObjectClass::count(CountBase& countBase, mozilla::MallocSizeOf mallocSizeOf, const Node& node)
{
Count& count = static_cast<Count&>(countBase);
const char16_t* nodeName = node.descriptiveTypeName();
if (!nodeName)
return false;
UniqueC16String name = DuplicateString(nodeName);
if (!name)
return false;
Table::AddPtr p = count.table.lookupForAdd(name);
if (!p) {
CountBasePtr classesCount(classesType->makeCount());
if (!classesCount || !count.table.add(p, std::move(name), std::move(classesCount)))
return false;
}
return p->value()->count(mallocSizeOf, node);
}
bool
ByDomObjectClass::report(JSContext* cx, CountBase& countBase, MutableHandleValue report)
{
Count& count = static_cast<Count&>(countBase);
RootedPlainObject obj(cx, countMap16ToObject(cx, count.table, [](const UniqueC16String& key) {
return key.get();
}));
if (!obj)
return false;
report.setObject(*obj);
return true;
}
// A count type that categorizes nodes by their ubi::Node::typeName.
class ByUbinodeType : public CountType {
@ -1058,11 +1223,15 @@ ParseBreakdown(JSContext* cx, HandleValue breakdownValue)
CountTypePtr otherType(ParseChildBreakdown(cx, breakdown, cx->names().other));
if (!otherType)
return nullptr;
CountTypePtr domNodeType(ParseChildBreakdown(cx, breakdown, cx->names().domNode));
if (!domNodeType)
return nullptr;
return CountTypePtr(cx->new_<ByCoarseType>(objectsType,
scriptsType,
stringsType,
otherType));
otherType,
domNodeType));
}
if (StringEqualsAscii(by, "internalType")) {
@ -1073,6 +1242,13 @@ ParseBreakdown(JSContext* cx, HandleValue breakdownValue)
return CountTypePtr(cx->new_<ByUbinodeType>(thenType));
}
if (StringEqualsAscii(by, "descriptiveType")) {
CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then));
if (!thenType)
return nullptr;
return CountTypePtr(cx->new_<ByDomObjectClass>(thenType));
}
if (StringEqualsAscii(by, "allocationStack")) {
CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then));
if (!thenType)
@ -1114,11 +1290,15 @@ ParseBreakdown(JSContext* cx, HandleValue breakdownValue)
//
// { by: "coarseType",
// objects: { by: "objectClass" },
// other: { by: "internalType" }
// other: { by: "internalType" },
// domNode: { by: "descriptiveType" }
// }
static CountTypePtr
GetDefaultBreakdown(JSContext* cx)
{
CountTypePtr byDomClass(cx->new_<SimpleCount>());
if (!byDomClass)
return nullptr;
CountTypePtr byClass(cx->new_<SimpleCount>());
if (!byClass)
return nullptr;
@ -1146,11 +1326,15 @@ GetDefaultBreakdown(JSContext* cx)
CountTypePtr other(cx->new_<ByUbinodeType>(byType));
if (!other)
return nullptr;
CountTypePtr domNode(cx->new_<ByDomObjectClass>(byDomClass));
if (!domNode)
return nullptr;
return CountTypePtr(cx->new_<ByCoarseType>(objects,
scripts,
strings,
other));
other,
domNode));
}
JS_PUBLIC_API(bool)

View File

@ -6,6 +6,7 @@
#include "vm/Xdr.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/PodOperations.h"
#include "mozilla/ScopeExit.h"
@ -21,7 +22,7 @@
#include "vm/TraceLogging.h"
using namespace js;
using mozilla::PodEqual;
using mozilla::ArrayEqual;
template<XDRMode mode>
LifoAlloc&
@ -116,7 +117,7 @@ VersionCheck(XDRState<mode>* xdr)
MOZ_TRY(xdr->codeBytes(decodedBuildId.begin(), buildIdLength));
// We do not provide binary compatibility with older scripts.
if (!PodEqual(decodedBuildId.begin(), buildId.begin(), buildIdLength))
if (!ArrayEqual(decodedBuildId.begin(), buildId.begin(), buildIdLength))
return xdr->fail(JS::TranscodeResult_Failure_BadBuildId);
}

View File

@ -18,6 +18,7 @@
#include "wasm/AsmJS.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/Compression.h"
#include "mozilla/MathAlgorithms.h"
@ -58,6 +59,7 @@ using namespace js::frontend;
using namespace js::jit;
using namespace js::wasm;
using mozilla::ArrayEqual;
using mozilla::CeilingLog2;
using mozilla::Compression::LZ4;
using mozilla::HashGeneric;
@ -65,7 +67,6 @@ using mozilla::IsNaN;
using mozilla::IsNegativeZero;
using mozilla::IsPositiveZero;
using mozilla::IsPowerOfTwo;
using mozilla::PodEqual;
using mozilla::PodZero;
using mozilla::PositiveInfinity;
using mozilla::Unused;
@ -6827,7 +6828,7 @@ class ModuleCharsForLookup : ModuleChars
MOZ_ASSERT(parseLimit >= parseBegin);
if (uint32_t(parseLimit - parseBegin) < chars_.length())
return false;
if (!PodEqual(chars_.begin(), parseBegin, chars_.length()))
if (!ArrayEqual(chars_.begin(), parseBegin, chars_.length()))
return false;
if (isFunCtor_ != parser.pc->isStandaloneFunctionBody())
return false;

View File

@ -541,7 +541,7 @@ Assumptions::operator==(const Assumptions& rhs) const
{
return cpuId == rhs.cpuId &&
buildId.length() == rhs.buildId.length() &&
PodEqual(buildId.begin(), rhs.buildId.begin(), buildId.length());
ArrayEqual(buildId.begin(), rhs.buildId.begin(), buildId.length());
}
size_t

View File

@ -20,6 +20,7 @@
#define wasm_types_h
#include "mozilla/Alignment.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Atomics.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/HashFunctions.h"
@ -75,6 +76,7 @@ typedef Rooted<WasmGlobalObject*> RootedWasmGlobalObject;
namespace wasm {
using mozilla::ArrayEqual;
using mozilla::Atomic;
using mozilla::DebugOnly;
using mozilla::EnumeratedArray;
@ -83,7 +85,6 @@ using mozilla::MallocSizeOf;
using mozilla::Nothing;
using mozilla::PodZero;
using mozilla::PodCopy;
using mozilla::PodEqual;
using mozilla::Some;
using mozilla::Unused;

View File

@ -8,7 +8,6 @@
#define nsCSSPropertyIDSet_h__
#include "mozilla/ArrayUtils.h"
#include "mozilla/PodOperations.h"
#include "nsCSSPropertyID.h"
#include <limits.h> // for CHAR_BIT
@ -64,7 +63,7 @@ public:
}
bool Equals(const nsCSSPropertyIDSet& aOther) const {
return mozilla::PodEqual(mProperties, aOther.mProperties);
return mozilla::ArrayEqual(mProperties, aOther.mProperties);
}
bool IsEmpty() const {

View File

@ -436,6 +436,8 @@ TEST(Jemalloc, InPlace)
// moz_dispose_arena(arena);
}
// Bug 1474254: disable this test for windows ccov builds because it leads to timeout.
#if !defined(XP_WIN) || !defined(MOZ_CODE_COVERAGE)
TEST(Jemalloc, JunkPoison)
{
jemalloc_stats_t stats;
@ -622,3 +624,4 @@ TEST(Jemalloc, JunkPoison)
// Until Bug 1364359 is fixed it is unsafe to call moz_dispose_arena.
// moz_dispose_arena(buf_arena);
}
#endif

View File

@ -14,6 +14,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include <algorithm>
#include <stddef.h>
#ifdef __cplusplus
@ -98,6 +99,24 @@ ArrayEnd(const Array<T, N>& aArr)
return &aArr[0] + ArrayLength(aArr);
}
/**
* std::equal has subpar ergonomics.
*/
template<typename T, typename U, size_t N>
bool
ArrayEqual(const T (&a)[N], const U (&b)[N])
{
return std::equal(a, a + N, b);
}
template<typename T, typename U>
bool
ArrayEqual(const T* const a, const U* const b, const size_t n)
{
return std::equal(a, a + n, b);
}
namespace detail {
template<typename AlignType, typename Pointee,

View File

@ -99,6 +99,11 @@ struct LinkedListElementTraits
// to a list.
static void enterList(LinkedListElement<T>* elt) {}
static void exitList(LinkedListElement<T>* elt) {}
// This method is called when AutoCleanLinkedList cleans itself
// during destruction. It can be used to call delete on elements if
// the list is the sole owner.
static void cleanElement(LinkedListElement<T>* elt) { delete elt->asT(); }
};
template<typename T>
@ -111,6 +116,7 @@ struct LinkedListElementTraits<RefPtr<T>>
static void enterList(LinkedListElement<RefPtr<T>>* elt) { elt->asT()->AddRef(); }
static void exitList(LinkedListElement<RefPtr<T>>* elt) { elt->asT()->Release(); }
static void cleanElement(LinkedListElement<RefPtr<T>>* elt) {}
};
} /* namespace detail */
@ -655,6 +661,9 @@ private:
template <typename T>
class AutoCleanLinkedList : public LinkedList<T>
{
private:
using Traits = detail::LinkedListElementTraits<T>;
using ClientType = typename detail::LinkedListElementTraits<T>::ClientType;
public:
~AutoCleanLinkedList()
{
@ -669,8 +678,8 @@ public:
void clear()
{
while (T* element = this->popFirst()) {
delete element;
while (ClientType element = this->popFirst()) {
Traits::cleanElement(element);
}
}
};

View File

@ -19,6 +19,7 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/Attributes.h"
#include <algorithm>
#include <stdint.h>
#include <string.h>
@ -158,38 +159,9 @@ PodMove(T* aDst, const T* aSrc, size_t aNElem)
}
/**
* Determine whether the |len| elements at |one| are memory-identical to the
* |len| elements at |two|.
* Looking for a PodEqual? Use ArrayEqual from ArrayUtils.h.
* Note that we *cannot* use memcmp for this, due to padding bytes, etc..
*/
template<typename T>
static MOZ_ALWAYS_INLINE bool
PodEqual(const T* one, const T* two, size_t len)
{
if (len < 128) {
const T* p1end = one + len;
const T* p1 = one;
const T* p2 = two;
for (; p1 < p1end; p1++, p2++) {
if (*p1 != *p2) {
return false;
}
}
return true;
}
return !memcmp(one, two, len * sizeof(T));
}
/*
* Determine whether the |N| elements at |one| are memory-identical to the
* |N| elements at |two|.
*/
template <class T, size_t N>
static MOZ_ALWAYS_INLINE bool
PodEqual(const T (&one)[N], const T (&two)[N])
{
return PodEqual(one, two, N);
}
} // namespace mozilla

View File

@ -0,0 +1,93 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/LinkedList.h"
#include "mozilla/RefPtr.h"
using mozilla::AutoCleanLinkedList;
using mozilla::LinkedList;
using mozilla::LinkedListElement;
class PtrClass : public LinkedListElement<PtrClass>
{
public:
bool* mResult;
explicit PtrClass(bool* result)
: mResult(result)
{
EXPECT_TRUE(!*mResult);
}
virtual ~PtrClass() {
*mResult = true;
}
};
class InheritedPtrClass : public PtrClass {
public:
bool* mInheritedResult;
InheritedPtrClass(bool* result, bool* inheritedResult)
: PtrClass(result)
, mInheritedResult(inheritedResult)
{
EXPECT_TRUE(!*mInheritedResult);
}
virtual ~InheritedPtrClass() {
*mInheritedResult = true;
}
};
TEST(LinkedList, AutoCleanLinkedList)
{
bool rv1 = false;
bool rv2 = false;
bool rv3 = false;
{
AutoCleanLinkedList<PtrClass> list;
list.insertBack(new PtrClass(&rv1));
list.insertBack(new InheritedPtrClass(&rv2, &rv3));
}
EXPECT_TRUE(rv1);
EXPECT_TRUE(rv2);
EXPECT_TRUE(rv3);
}
class CountedClass final : public LinkedListElement<RefPtr<CountedClass>>
{
public:
int mCount;
void AddRef() { mCount++; }
void Release() { mCount--; }
CountedClass()
: mCount(0)
{
}
~CountedClass() { EXPECT_TRUE(mCount == 0); }
};
TEST(LinkedList, AutoCleanLinkedListRefPtr)
{
RefPtr<CountedClass> elt1 = new CountedClass;
CountedClass* elt2 = new CountedClass;
{
AutoCleanLinkedList<RefPtr<CountedClass>> list;
list.insertBack(elt1);
list.insertBack(elt2);
EXPECT_TRUE(elt1->mCount == 2);
EXPECT_TRUE(elt2->mCount == 1);
}
EXPECT_TRUE(elt1->mCount == 1);
EXPECT_TRUE(elt2->mCount == 0);
}

View File

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'TestLinkedList.cpp',
'TestSpan.cpp',
]

View File

@ -106,6 +106,13 @@ class AccessibilityTest : BaseSessionTest() {
sessionRule.session.accessibility.view = null
}
private fun waitForInitialFocus() {
sessionRule.waitUntilCalled(object : EventDelegate {
@AssertCalled(count = 1)
override fun onFocused(event: AccessibilityEvent) { }
})
}
@Test fun testRootNode() {
assertThat("provider is not null", provider, notNullValue())
val node = provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID)
@ -125,7 +132,7 @@ class AccessibilityTest : BaseSessionTest() {
@Test fun testAccessibilityFocus() {
var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID
sessionRule.session.loadTestPath(INPUTS_PATH)
sessionRule.waitForPageStop()
waitForInitialFocus()
provider.performAction(AccessibilityNodeProvider.HOST_VIEW_ID,
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
@ -154,7 +161,7 @@ class AccessibilityTest : BaseSessionTest() {
@Test fun testTextEntryNode() {
sessionRule.session.loadString("<input aria-label='Name' value='Tobias'>", "text/html")
sessionRule.waitForPageStop()
waitForInitialFocus()
mainSession.evaluateJS("$('input').focus()")
@ -233,7 +240,7 @@ class AccessibilityTest : BaseSessionTest() {
@Test fun testClipboard() {
var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID;
sessionRule.session.loadString("<input value='hello cruel world' id='input'>", "text/html")
sessionRule.waitForPageStop()
waitForInitialFocus()
mainSession.evaluateJS("$('input').focus()")
@ -284,7 +291,7 @@ class AccessibilityTest : BaseSessionTest() {
@Test fun testMoveByCharacter() {
var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID
sessionRule.session.loadTestPath(LOREM_IPSUM_HTML_PATH)
sessionRule.waitForPageStop()
waitForInitialFocus()
provider.performAction(AccessibilityNodeProvider.HOST_VIEW_ID,
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
@ -317,7 +324,7 @@ class AccessibilityTest : BaseSessionTest() {
@Test fun testMoveByWord() {
var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID
sessionRule.session.loadTestPath(LOREM_IPSUM_HTML_PATH)
sessionRule.waitForPageStop()
waitForInitialFocus()
provider.performAction(AccessibilityNodeProvider.HOST_VIEW_ID,
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
@ -350,7 +357,7 @@ class AccessibilityTest : BaseSessionTest() {
@Test fun testMoveByLine() {
var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID
sessionRule.session.loadTestPath(LOREM_IPSUM_HTML_PATH)
sessionRule.waitForPageStop()
waitForInitialFocus()
provider.performAction(AccessibilityNodeProvider.HOST_VIEW_ID,
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
@ -383,7 +390,7 @@ class AccessibilityTest : BaseSessionTest() {
@Test fun testCheckbox() {
var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID;
sessionRule.session.loadString("<label><input id='checkbox' type='checkbox'>many option</label>", "text/html")
sessionRule.waitForPageStop()
waitForInitialFocus()
mainSession.evaluateJS("$('#checkbox').focus()")
sessionRule.waitUntilCalled(object : EventDelegate {
@ -413,7 +420,7 @@ class AccessibilityTest : BaseSessionTest() {
<li id="li" role="option" onclick="this.setAttribute('aria-selected',
this.getAttribute('aria-selected') == 'true' ? 'false' : 'true')">1</li>
</ul>""","text/html")
sessionRule.waitForPageStop()
waitForInitialFocus()
provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
sessionRule.waitUntilCalled(object : EventDelegate {

View File

@ -1102,17 +1102,17 @@ CertIsAuthoritativeForEVPolicy(const UniqueCERTCertificate& cert,
// This check ensures that only the specific roots we approve for EV get
// that status, and not certs (roots or otherwise) that happen to have an
// OID that's already been approved for EV.
if (!PodEqual(fingerprint, entry.sha256Fingerprint)) {
if (!ArrayEqual(fingerprint, entry.sha256Fingerprint)) {
continue;
}
if (cabforumOIDData && cabforumOIDData->oid.len == policy.numBytes &&
PodEqual(cabforumOIDData->oid.data, policy.bytes, policy.numBytes)) {
ArrayEqual(cabforumOIDData->oid.data, policy.bytes, policy.numBytes)) {
return true;
}
const SECOidData* oidData = SECOID_FindOIDByTag(sEVInfoOIDTags[i]);
if (oidData && oidData->oid.len == policy.numBytes &&
PodEqual(oidData->oid.data, policy.bytes, policy.numBytes)) {
ArrayEqual(oidData->oid.data, policy.bytes, policy.numBytes)) {
return true;
}
}
@ -1188,7 +1188,7 @@ LoadExtendedValidationInfo()
if (srv != SECSuccess) {
return NS_ERROR_FAILURE;
}
bool same = PodEqual(certFingerprint, entry.sha256Fingerprint);
bool same = ArrayEqual(certFingerprint, entry.sha256Fingerprint);
MOZ_ASSERT(same, "EV root fingerprint mismatch");
if (!same) {
return NS_ERROR_FAILURE;

View File

@ -9,7 +9,7 @@
#include "nsNSSCertificate.h"
#include "nsNSSCertValidity.h"
#include "mozilla/PodOperations.h"
#include "mozilla/ArrayUtils.h"
using namespace mozilla;
@ -29,7 +29,7 @@ CertDNIsInList(const CERTCertificate* aCert, const DataAndLength (&aDnList)[T])
for (auto& dn: aDnList) {
if (aCert->derSubject.len == dn.len &&
mozilla::PodEqual(aCert->derSubject.data, dn.data, dn.len)) {
mozilla::ArrayEqual(aCert->derSubject.data, dn.data, dn.len)) {
return true;
}
}
@ -47,7 +47,7 @@ CertSPKIIsInList(const CERTCertificate* aCert, const DataAndLength (&aSpkiList)[
for (auto& spki: aSpkiList) {
if (aCert->derPublicKey.len == spki.len &&
mozilla::PodEqual(aCert->derPublicKey.data, spki.data, spki.len)) {
mozilla::ArrayEqual(aCert->derPublicKey.data, spki.data, spki.len)) {
return true;
}
}
@ -64,9 +64,9 @@ CertMatchesStaticData(const CERTCertificate* cert,
return false;
}
return cert->derSubject.len == T &&
mozilla::PodEqual(cert->derSubject.data, subject, T) &&
mozilla::ArrayEqual(cert->derSubject.data, subject, T) &&
cert->derPublicKey.len == R &&
mozilla::PodEqual(cert->derPublicKey.data, spki, R);
mozilla::ArrayEqual(cert->derPublicKey.data, spki, R);
}
// Implements the graduated Symantec distrust algorithm from Bug 1409257.

View File

@ -8,8 +8,8 @@
#include "gtest/gtest.h"
#include "md4.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Casting.h"
#include "mozilla/PodOperations.h"
struct RFC1320TestParams
{
@ -68,7 +68,7 @@ TEST_P(psm_MD4, RFC1320TestValues)
uint8_t actualHash[16];
md4sum(mozilla::BitwiseCast<const uint8_t*, const char*>(params.data),
strlen(params.data), actualHash);
EXPECT_TRUE(mozilla::PodEqual(actualHash, params.expectedHash))
EXPECT_TRUE(mozilla::ArrayEqual(actualHash, params.expectedHash))
<< "MD4 hashes aren't equal for input: '" << params.data << "'";
}

View File

@ -603,7 +603,7 @@ var State = {
dispatchesSincePrevious: prev ? dispatches - prev.dispatchCount : NaN,
dispatchesSinceStartOfBuffer: oldest ? dispatches - oldest.dispatchCount : NaN,
children: tab.children});
}).sort((a, b) => b.dispatchesSinceStartOfBuffer - a.dispatchesSinceStartOfBuffer);
});
}
};
@ -954,7 +954,7 @@ var Control = {
// Make sure that we do not keep obsolete stuff around.
View.DOMCache.trimTo(state.deltas);
} else {
let counters = State.getCounters();
let counters = this._sortCounters(State.getCounters());
for (let {name, image, totalDispatches, dispatchesSincePrevious,
totalDuration, durationSincePrevious, children} of counters) {
function dispatchesAndDuration(dispatches, duration) {
@ -995,6 +995,15 @@ var Control = {
// Inform watchers
Services.obs.notifyObservers(null, UPDATE_COMPLETE_TOPIC, mode);
},
_sortCounters(counters) {
return counters.sort((a, b) => {
if (a.dispatchesSinceStartOfBuffer != b.dispatchesSinceStartOfBuffer)
return b.dispatchesSinceStartOfBuffer - a.dispatchesSinceStartOfBuffer;
if (a.totalDispatches != b.totalDispatches)
return b.totalDispatches - a.totalDispatches;
return a.name.localeCompare(b.name);
});
},
_setOptions(options) {
dump(`about:performance _setOptions ${JSON.stringify(options)}\n`);
let eltRefresh = document.getElementById("check-autorefresh");

View File

@ -1250,6 +1250,7 @@ nsWebBrowser::Create()
mDocShell->SetItemType(nsIDocShellTreeItem::typeContent);
}
mDocShell->SetTreeOwner(mDocShellTreeOwner);
mDocShell->AttachBrowsingContext(nullptr);
// If the webbrowser is a content docshell item then we won't hear any
// events from subframes. To solve that we install our own chrome event

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