This commit is contained in:
Ryan VanderMeulen 2015-05-29 16:58:30 -04:00
Родитель fd95ec79c9 a9dff21310
Коммит 012e20629b
203 изменённых файлов: 3414 добавлений и 932 удалений

Просмотреть файл

@ -32,7 +32,7 @@
#include "nsIWebProgress.h"
#include "nsCoreUtils.h"
#include "nsXULAppAPI.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/TabChild.h"
using namespace mozilla;
using namespace mozilla::a11y;
@ -457,8 +457,10 @@ DocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
if (IPCAccessibilityActive()) {
DocAccessibleChild* ipcDoc = new DocAccessibleChild(docAcc);
docAcc->SetIPCDoc(ipcDoc);
auto contentChild = dom::ContentChild::GetSingleton();
contentChild->SendPDocAccessibleConstructor(ipcDoc, nullptr, 0);
nsCOMPtr<nsITabChild> tabChild =
do_GetInterface(aDocument->GetDocShell());
static_cast<TabChild*>(tabChild.get())->
SendPDocAccessibleConstructor(ipcDoc, nullptr, 0);
}
} else {
parentDocAcc->BindChildDocument(docAcc);

Просмотреть файл

@ -10,7 +10,7 @@
#include "TextLeafAccessible.h"
#include "TextUpdater.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/dom/Element.h"
#include "mozilla/Telemetry.h"
@ -292,8 +292,10 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
ipcDoc = new DocAccessibleChild(childDoc);
childDoc->SetIPCDoc(ipcDoc);
auto contentChild = dom::ContentChild::GetSingleton();
contentChild->SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id);
nsCOMPtr<nsITabChild> tabChild =
do_GetInterface(mDocument->DocumentNode()->GetDocShell());
static_cast<TabChild*>(tabChild.get())->
SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id);
}
}

Просмотреть файл

@ -32,7 +32,7 @@ public:
{
MOZ_COUNT_DTOR_INHERITED(DocAccessibleParent, ProxyAccessible);
MOZ_ASSERT(mChildDocs.Length() == 0);
MOZ_ASSERT(!mParentDoc);
MOZ_ASSERT(!ParentDoc());
}
/*
@ -55,7 +55,7 @@ public:
void Unbind()
{
mParent = nullptr;
mParentDoc->mChildDocs.RemoveElement(this);
ParentDoc()->mChildDocs.RemoveElement(this);
mParentDoc = nullptr;
}
@ -70,7 +70,7 @@ public:
* Return the main processes representation of the parent document (if any)
* of the document this object represents.
*/
DocAccessibleParent* Parent() const { return mParentDoc; }
DocAccessibleParent* ParentDoc() const { return mParentDoc; }
/*
* Called when a document in a content process notifies the main process of a
@ -85,7 +85,7 @@ public:
*/
void RemoveChildDoc(DocAccessibleParent* aChildDoc)
{
aChildDoc->mParent->SetChildDoc(nullptr);
aChildDoc->Parent()->SetChildDoc(nullptr);
mChildDocs.RemoveElement(aChildDoc);
aChildDoc->mParentDoc = nullptr;
MOZ_ASSERT(aChildDoc->mChildDocs.Length() == 0);

Просмотреть файл

@ -4,7 +4,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PContent;
include protocol PFileDescriptorSet;
include protocol PBrowser;
include "mozilla/GfxMessageUtils.h";
@ -44,7 +45,7 @@ struct RelationTargets
prio(normal upto high) sync protocol PDocAccessible
{
manager PContent;
manager PBrowser;
parent:
__delete__();

Просмотреть файл

@ -46,7 +46,7 @@ public:
ProxyAccessible* ChildAt(uint32_t aIdx) const { return mChildren[aIdx]; }
// XXX evaluate if this is fast enough.
size_t IndexInParent() const { return mParent->mChildren.IndexOf(this); }
size_t IndexInParent() const { return Parent()->mChildren.IndexOf(this); }
int32_t IndexOfEmbeddedChild(const ProxyAccessible*);
bool MustPruneChildren() const;

Просмотреть файл

@ -174,10 +174,17 @@ this.EventManager.prototype = {
let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
let state = Utils.getState(event);
if (state.contains(States.CHECKED)) {
this.present(
Presentation.
actionInvoked(aEvent.accessible,
event.isEnabled ? 'check' : 'uncheck'));
if (aEvent.accessible.role === Roles.SWITCH) {
this.present(
Presentation.
actionInvoked(aEvent.accessible,
event.isEnabled ? 'on' : 'off'));
} else {
this.present(
Presentation.
actionInvoked(aEvent.accessible,
event.isEnabled ? 'check' : 'uncheck'));
}
} else if (state.contains(States.SELECTED)) {
this.present(
Presentation.

Просмотреть файл

@ -210,7 +210,7 @@ let OutputGenerator = {
aOutput.push({string: 'textInputType_' + typeName});
},
_addState: function _addState(aOutput, aState) {}, // jshint ignore:line
_addState: function _addState(aOutput, aState, aRoleStr) {}, // jshint ignore:line
_addRole: function _addRole(aOutput, aRoleStr) {}, // jshint ignore:line
@ -252,6 +252,7 @@ let OutputGenerator = {
'outlineitem': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'pagetab': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'graphic': INCLUDE_DESC,
'switch': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'pushbutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'checkbutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'radiobutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
@ -307,7 +308,7 @@ let OutputGenerator = {
let output = [];
if (aFlags & INCLUDE_DESC) {
this._addState(output, aState);
this._addState(output, aState, aRoleStr);
this._addType(output, aAccessible, aRoleStr);
this._addRole(output, aRoleStr);
}
@ -413,13 +414,15 @@ let OutputGenerator = {
* not.
*/
this.UtteranceGenerator = { // jshint ignore:line
__proto__: OutputGenerator,
__proto__: OutputGenerator, // jshint ignore:line
gActionMap: {
jump: 'jumpAction',
press: 'pressAction',
check: 'checkAction',
uncheck: 'uncheckAction',
on: 'onAction',
off: 'offAction',
select: 'selectAction',
unselect: 'unselectAction',
open: 'openAction',
@ -475,7 +478,7 @@ this.UtteranceGenerator = { // jshint ignore:line
objectOutputFunctions: {
__proto__: OutputGenerator.objectOutputFunctions,
__proto__: OutputGenerator.objectOutputFunctions, // jshint ignore:line
defaultFunc: function defaultFunc() {
return this.objectOutputFunctions._generateBaseOutput.apply(
@ -597,7 +600,7 @@ this.UtteranceGenerator = { // jshint ignore:line
aOutput.push({string: this._getOutputName(aRoleStr)});
},
_addState: function _addState(aOutput, aState) {
_addState: function _addState(aOutput, aState, aRoleStr) {
if (aState.contains(States.UNAVAILABLE)) {
aOutput.push({string: 'stateUnavailable'});
@ -613,8 +616,13 @@ this.UtteranceGenerator = { // jshint ignore:line
// regardless of the utterance ordering preference.
if ((Utils.AndroidSdkVersion < 16 || Utils.MozBuildApp === 'browser') &&
aState.contains(States.CHECKABLE)) {
let statetr = aState.contains(States.CHECKED) ?
'stateChecked' : 'stateNotChecked';
let checked = aState.contains(States.CHECKED);
let statetr;
if (aRoleStr === 'switch') {
statetr = checked ? 'stateOn' : 'stateOff';
} else {
statetr = checked ? 'stateChecked' : 'stateNotChecked';
}
aOutput.push({string: statetr});
}
@ -662,7 +670,7 @@ this.UtteranceGenerator = { // jshint ignore:line
};
this.BrailleGenerator = { // jshint ignore:line
__proto__: OutputGenerator,
__proto__: OutputGenerator, // jshint ignore:line
genForContext: function genForContext(aContext) {
let output = OutputGenerator.genForContext.apply(this, arguments);
@ -699,7 +707,7 @@ this.BrailleGenerator = { // jshint ignore:line
objectOutputFunctions: {
__proto__: OutputGenerator.objectOutputFunctions,
__proto__: OutputGenerator.objectOutputFunctions, // jshint ignore:line
defaultFunc: function defaultFunc() {
return this.objectOutputFunctions._generateBaseOutput.apply(
@ -760,13 +768,17 @@ this.BrailleGenerator = { // jshint ignore:line
_useStateNotRole:
function _useStateNotRole(aAccessible, aRoleStr, aState, aFlags) {
let braille = [];
this._addState(braille, aState, aAccessible.role);
this._addState(braille, aState, aRoleStr);
this._addName(braille, aAccessible, aFlags);
this._addLandmark(braille, aAccessible);
return braille;
},
switch: function braille_generator_object_output_functions_switch() {
return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
},
checkbutton: function checkbutton() {
return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
},
@ -796,7 +808,7 @@ this.BrailleGenerator = { // jshint ignore:line
aBraille.push({string: this._getOutputName(aRoleStr)});
},
_addState: function _addState(aBraille, aState, aRole) {
_addState: function _addState(aBraille, aState, aRoleStr) {
if (aState.contains(States.CHECKABLE)) {
aBraille.push({
string: aState.contains(States.CHECKED) ?
@ -804,7 +816,7 @@ this.BrailleGenerator = { // jshint ignore:line
this._getOutputName('stateUnchecked')
});
}
if (aRole === Roles.TOGGLE_BUTTON) {
if (aRoleStr === 'toggle button') {
aBraille.push({
string: aState.contains(States.PRESSED) ?
this._getOutputName('statePressed') :

Просмотреть файл

@ -3,15 +3,13 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global PrefCache, Roles, Prefilters, States, Filters, Utils,
TraversalRules */
TraversalRules, Components, XPCOMUtils */
/* exported TraversalRules */
'use strict';
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
this.EXPORTED_SYMBOLS = ['TraversalRules']; // jshint ignore:line
@ -103,7 +101,8 @@ var gSimpleTraversalRoles =
Roles.GRID_CELL,
Roles.COLUMNHEADER,
Roles.ROWHEADER,
Roles.STATUSBAR];
Roles.STATUSBAR,
Roles.SWITCH];
var gSimpleMatchFunc = function gSimpleMatchFunc(aAccessible) {
// An object is simple, if it either has a single child lineage,
@ -240,7 +239,8 @@ this.TraversalRules = { // jshint ignore:line
Roles.RADIO_MENU_ITEM,
Roles.SLIDER,
Roles.CHECKBUTTON,
Roles.CHECK_MENU_ITEM]),
Roles.CHECK_MENU_ITEM,
Roles.SWITCH]),
Graphic: new BaseTraversalRule(
[Roles.GRAPHIC],
@ -302,7 +302,8 @@ this.TraversalRules = { // jshint ignore:line
Checkbox: new BaseTraversalRule(
[Roles.CHECKBUTTON,
Roles.CHECK_MENU_ITEM]),
Roles.CHECK_MENU_ITEM,
Roles.SWITCH /* A type of checkbox that represents on/off values */]),
_shouldSkipImage: function _shouldSkipImage(aAccessible) {
if (gSkipEmptyImages.value && aAccessible.name === '') {

Просмотреть файл

@ -55,6 +55,12 @@
'aria-valuetext', 'medium');
}
function toggleLight() {
var lightSwitch = document.getElementById('light');
lightSwitch.setAttribute('aria-checked',
lightSwitch.getAttribute('aria-checked') === 'true' ? 'false' : 'true');
}
</script>
<style>
#windows {
@ -100,6 +106,7 @@
</div>
<button id="home">Home</button>
<button id="fruit" aria-label="apple"></button>
<span id="light" role="switch" aria-label="Light" aria-checked="false" onclick="toggleLight()"></span>
<div id="live" aria-live="polite" aria-label="live">
<div id="slider" role="slider" aria-label="slider" aria-valuemin="0"
aria-valuemax="10" aria-valuenow="0"></div>

Просмотреть файл

@ -143,5 +143,7 @@
</table>
<div id="statusbar-1" role="status">Last sync:<span>2 days ago</span></div>
<div aria-label="Last sync: 30min ago" id="statusbar-2" role="status"></div>
<span id="switch-1" role="switch" aria-checked="false" aria-label="Light switch"></span>
</body>
</html>

Просмотреть файл

@ -617,6 +617,18 @@ function ExpectedCheckAction(aChecked, aOptions) {
ExpectedCheckAction.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedSwitchAction(aSwitched, aOptions) {
ExpectedPresent.call(this, {
eventType: 'action',
data: [{ string: aSwitched ? 'onAction' : 'offAction' }]
}, [{
eventType: AndroidEvent.VIEW_CLICKED,
checked: aSwitched
}], aOptions);
}
ExpectedSwitchAction.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedNameChange(aName, aOptions) {
ExpectedPresent.call(this, {
eventType: 'name-change',

Просмотреть файл

@ -58,10 +58,22 @@
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['apple', {'string': 'pushbutton'}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['Light', {"string": "stateOff"}, {'string': 'switch'}])],
// switch on
[ContentMessages.activateCurrent(),
new ExpectedClickAction({ no_android: true }),
new ExpectedSwitchAction(true)],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['slider', '0', {'string': 'slider'}])],
// Simple traversal backward
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(['Light', {"string": "stateOn"}, {'string': 'switch'}])],
// switch off
[ContentMessages.activateCurrent(),
new ExpectedClickAction({ no_android: true }),
new ExpectedSwitchAction(false)],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(['apple', {'string': 'pushbutton'}])],
[ContentMessages.simpleMovePrevious,

Просмотреть файл

@ -488,6 +488,21 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
expectedUtterance: [["Last sync: 30min ago"],
["Last sync: 30min ago"]],
expectedBraille: [["Last sync: 30min ago"], ["Last sync: 30min ago"]]
}, {
accOrElmOrID: "switch-1",
expectedUtterance: [[{"string": "stateOn"}, {"string": "switch"},
"Simple switch"], ["Simple switch", {"string": "stateOn"},
{"string": "switch"}]],
expectedBraille: [[{"string": "stateCheckedAbbr"}, "Simple switch"],
["Simple switch", {"string": "stateCheckedAbbr"}]]
}, {
accOrElmOrID: "switch-2",
expectedUtterance: [[{"string": "stateOff"},
{"string": "switch"}, "Another switch"], ["Another switch",
{"string": "stateOff"}, {"string": "switch"}]],
expectedBraille: [
[{"string": "stateUncheckedAbbr"}, "Another switch"],
["Another switch", {"string": "stateUncheckedAbbr"}]]
}];
// Test all possible utterance order preference values.
@ -645,6 +660,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
</select>
<div id="statusbar-1" role="status">Last sync:<span>2 days ago</span></div>
<div aria-label="Last sync: 30min ago" id="statusbar-2" role="status"></div>
<span id="switch-1" role="switch" aria-label="Simple switch" aria-checked="true"></span>
<span id="switch-2" role="switch" aria-label="Another switch" aria-checked="false"></span>
</div>
</body>
</html>

Просмотреть файл

@ -56,7 +56,7 @@
'select-1-1', 'select-1-2', 'checkbox-1-2',
'select-1-3', 'input-1-5', 'button-1-3',
'button-2-1', 'button-2-2', 'button-2-3',
'button-2-4', 'checkbox-1-5']);
'button-2-4', 'checkbox-1-5', 'switch-1']);
queueTraversalSequence(gQueue, docAcc, TraversalRules.Button, null,
['button-1-1', 'button-1-2', 'button-1-3',
@ -67,7 +67,8 @@
['radio-1-1', 'radio-1-2']);
queueTraversalSequence(gQueue, docAcc, TraversalRules.Checkbox, null,
['checkbox-1-1', 'checkbox-1-2', 'checkbox-1-5']);
['checkbox-1-1', 'checkbox-1-2', 'checkbox-1-5',
'switch-1']);
queueTraversalSequence(gQueue, docAcc, TraversalRules.Combobox, null,
['select-1-1', 'select-1-2', 'select-1-3']);
@ -122,7 +123,8 @@
'1', 'Sunday', 'M', 'Week 1', '3', '4', '7', '2',
'5 8', 'gridcell4', 'Just an innocuous separator',
'Dirty Words', 'Meaning', 'Mud', 'Wet Dirt',
'Dirt', 'Messy Stuff', 'statusbar-1', 'statusbar-2']);
'Dirt', 'Messy Stuff', 'statusbar-1', 'statusbar-2',
'switch-1']);
gQueue.invoke();
}

Просмотреть файл

@ -24,7 +24,8 @@ ia2AccessibleAction::QueryInterface(REFIID iid, void** ppv)
*ppv = nullptr;
if (IID_IAccessibleAction == iid) {
if (IID_IAccessibleAction == iid &&
!static_cast<AccessibleWrap*>(this)->IsProxy()) {
*ppv = static_cast<IAccessibleAction*>(this);
(reinterpret_cast<IUnknown*>(*ppv))->AddRef();
return S_OK;

Просмотреть файл

@ -55,7 +55,9 @@ ia2AccessibleHyperlink::get_anchor(long aIndex, VARIANT* aAnchor)
if (!anchor)
return S_FALSE;
aAnchor->punkVal = static_cast<IAccessibleHyperlink*>(WrapperFor(anchor));
IUnknown* tmp = static_cast<IAccessibleHyperlink*>(WrapperFor(anchor));
tmp->AddRef();
aAnchor->punkVal = tmp;
aAnchor->vt = VT_UNKNOWN;
return S_OK;
}

Просмотреть файл

@ -115,21 +115,17 @@ AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
if (IID_IUnknown == iid)
*ppv = static_cast<IAccessible*>(this);
if (!*ppv && IsProxy())
return E_NOINTERFACE;
if (IID_IDispatch == iid || IID_IAccessible == iid)
else if (IID_IDispatch == iid || IID_IAccessible == iid)
*ppv = static_cast<IAccessible*>(this);
else if (IID_IEnumVARIANT == iid) {
else if (IID_IEnumVARIANT == iid && !IsProxy()) {
// Don't support this interface for leaf elements.
if (!HasChildren() || nsAccUtils::MustPrune(this))
return E_NOINTERFACE;
*ppv = static_cast<IEnumVARIANT*>(new ChildrenEnumVariant(this));
} else if (IID_IServiceProvider == iid)
} else if (IID_IServiceProvider == iid && !IsProxy())
*ppv = new ServiceProvider(this);
else if (IID_ISimpleDOMNode == iid) {
else if (IID_ISimpleDOMNode == iid && !IsProxy()) {
if (IsDefunct() || (!HasOwnContent() && !IsDoc()))
return E_NOINTERFACE;
@ -142,7 +138,7 @@ AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
return hr;
}
if (nullptr == *ppv) {
if (nullptr == *ppv && !IsProxy()) {
HRESULT hr = ia2AccessibleComponent::QueryInterface(iid, ppv);
if (SUCCEEDED(hr))
return hr;
@ -154,7 +150,7 @@ AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
return hr;
}
if (nullptr == *ppv) {
if (nullptr == *ppv && !IsProxy()) {
HRESULT hr = ia2AccessibleValue::QueryInterface(iid, ppv);
if (SUCCEEDED(hr))
return hr;

Просмотреть файл

@ -350,6 +350,7 @@ var shell = {
this.contentBrowser.addEventListener('mozbrowserloadstart', this, true);
this.contentBrowser.addEventListener('mozbrowserselectionstatechanged', this, true);
this.contentBrowser.addEventListener('mozbrowserscrollviewchange', this, true);
this.contentBrowser.addEventListener('mozbrowsercaretstatechanged', this);
CustomEventManager.init();
WebappsHelper.init();
@ -380,6 +381,7 @@ var shell = {
this.contentBrowser.removeEventListener('mozbrowserloadstart', this, true);
this.contentBrowser.removeEventListener('mozbrowserselectionstatechanged', this, true);
this.contentBrowser.removeEventListener('mozbrowserscrollviewchange', this, true);
this.contentBrowser.removeEventListener('mozbrowsercaretstatechanged', this);
ppmm.removeMessageListener("content-handler", this);
UserAgentOverrides.uninit();
@ -490,6 +492,28 @@ var shell = {
detail: data,
});
break;
case 'mozbrowsercaretstatechanged':
{
let elt = evt.target;
let win = elt.ownerDocument.defaultView;
let offsetX = win.mozInnerScreenX - window.mozInnerScreenX;
let offsetY = win.mozInnerScreenY - window.mozInnerScreenY;
let rect = elt.getBoundingClientRect();
offsetX += rect.left;
offsetY += rect.top;
let data = evt.detail;
data.offsetX = offsetX;
data.offsetY = offsetY;
data.sendDoCommandMsg = null;
shell.sendChromeEvent({
type: 'caretstatechanged',
detail: data,
});
}
break;
case 'MozApplicationManifest':
try {
@ -718,6 +742,10 @@ var CustomEventManager = {
case 'do-command':
DoCommandHelper.handleEvent(detail.cmd);
break;
case 'copypaste-do-command':
Services.obs.notifyObservers({ wrappedJSObject: shell.contentBrowser },
'ask-children-to-execute-copypaste-command', detail.cmd);
break;
}
}
}

Просмотреть файл

@ -1198,9 +1198,10 @@ pref("security.sandbox.windows.log", false);
// On windows these levels are:
// 0 - no sandbox
// 1 - sandbox with USER_NON_ADMIN access token level
// 2 - a more strict sandbox, which might cause functionality issues
// 2 - a more strict sandbox, which might cause functionality issues. This now
// includes running at low integrity.
// 3 - the strongest settings we seem to be able to use without breaking
// everything, but will definitely cause some functionality restrictions
// everything, but will probably cause some functionality restrictions
pref("dom.ipc.plugins.sandbox-level.default", 0);
#if defined(MOZ_CONTENT_SANDBOX)

Просмотреть файл

@ -529,14 +529,10 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
aCx ? aCx : FindJSContext(aGlobalObject))
, ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ true)
, mWebIDLCallerPrincipal(nullptr)
, mIsMainThread(aIsMainThread)
{
MOZ_ASSERT(aGlobalObject);
MOZ_ASSERT_IF(!aCx, aIsMainThread); // cx is mandatory off-main-thread.
MOZ_ASSERT_IF(aCx && aIsMainThread, aCx == FindJSContext(aGlobalObject));
if (aIsMainThread) {
nsContentUtils::EnterMicroTask();
}
if (aIsMainThread && gRunToCompletionListeners > 0) {
mDocShellEntryMonitor.emplace(cx(), aReason);
@ -545,10 +541,6 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
AutoEntryScript::~AutoEntryScript()
{
if (mIsMainThread) {
nsContentUtils::LeaveMicroTask();
}
// GC when we pop a script entry point. This is a useful heuristic that helps
// us out on certain (flawed) benchmarks like sunspider, because it lets us
// avoid GCing during the timing loop.
@ -590,7 +582,10 @@ AutoEntryScript::DocshellEntryMonitor::Entry(JSContext* aCx, JSFunction* aFuncti
if (rootedFunction) {
JS::Rooted<JSString*> displayId(aCx, JS_GetFunctionDisplayId(rootedFunction));
if (displayId) {
functionName.initTwoByte(aCx, displayId);
if (!functionName.initTwoByte(aCx, displayId)) {
JS_ClearPendingException(aCx);
return;
}
}
}

Просмотреть файл

@ -375,8 +375,6 @@ private:
friend nsIPrincipal* GetWebIDLCallerPrincipal();
Maybe<DocshellEntryMonitor> mDocShellEntryMonitor;
bool mIsMainThread;
};
/*

Просмотреть файл

@ -219,6 +219,7 @@ nsJSUtils::EvaluateString(JSContext* aCx,
// aCompileOptions.noScriptRval set to true.
aRetValue.setUndefined();
nsAutoMicroTask mt;
nsresult rv = NS_OK;
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();

Просмотреть файл

@ -1210,14 +1210,18 @@ nsScriptLoader::ProcessPendingRequests()
child->RemoveExecuteBlocker();
}
if (mDocumentParsingDone && mDocument && !mParserBlockingRequest &&
mNonAsyncExternalScriptInsertedRequests.isEmpty() &&
mXSLTRequests.isEmpty() && mDeferRequests.isEmpty() &&
MaybeRemovedDeferRequests()) {
return ProcessPendingRequests();
}
if (mDocumentParsingDone && mDocument &&
!mParserBlockingRequest && mLoadingAsyncRequests.isEmpty() &&
mLoadedAsyncRequests.isEmpty() &&
mNonAsyncExternalScriptInsertedRequests.isEmpty() &&
mXSLTRequests.isEmpty() && mDeferRequests.isEmpty()) {
if (MaybeRemovedDeferRequests()) {
return ProcessPendingRequests();
}
// No more pending scripts; time to unblock onload.
// OK to unblock onload synchronously here, since callers must be
// prepared for the world changing anyway.

Просмотреть файл

@ -50,7 +50,7 @@ nsStyleLinkElement::~nsStyleLinkElement()
void
nsStyleLinkElement::Unlink()
{
mStyleSheet = nullptr;
nsStyleLinkElement::SetStyleSheet(nullptr);
}
void

Просмотреть файл

@ -211,7 +211,9 @@ nsresult TestDirectives() {
{ "script-src 'nonce-correctscriptnonce'",
"script-src 'nonce-correctscriptnonce'" },
{ "script-src 'sha256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='",
"script-src 'sha256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='" }
"script-src 'sha256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='" },
{ "referrer no-referrer",
"referrer no-referrer" }
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
@ -273,7 +275,9 @@ nsresult TestIgnoreUpperLowerCasePolicies() {
{ "script-src 'NoncE-NONCENEEDSTOBEUPPERCASE'",
"script-src 'nonce-NONCENEEDSTOBEUPPERCASE'" },
{ "script-src 'SHA256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='",
"script-src 'sha256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='" }
"script-src 'sha256-siVR8vAcqP06h2ppeNwqgjr0yZ6yned4X2VF84j4GmI='" },
{ "refERRer No-refeRRer",
"referrer No-refeRRer" }
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);

Просмотреть файл

@ -1456,6 +1456,11 @@ DOMInterfaces = {
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionDisjointTimerQuery': {
'nativeType': 'mozilla::WebGLExtensionDisjointTimerQuery',
'headerFile': 'WebGLExtensions.h'
},
'WebGLFramebuffer': {
'nativeType': 'mozilla::WebGLFramebuffer',
'headerFile': 'WebGLFramebuffer.h'
@ -1514,6 +1519,11 @@ DOMInterfaces = {
'headerFile': 'WebGLTexture.h'
},
'WebGLTimerQuery': {
'nativeType': 'mozilla::WebGLTimerQuery',
'headerFile': 'WebGLTimerQuery.h'
},
'WebGLTransformFeedback': {
'nativeType': 'mozilla::WebGLTransformFeedback',
'headerFile': 'WebGLTransformFeedback.h'

Просмотреть файл

@ -62,6 +62,10 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
, mExceptionHandling(aExceptionHandling)
, mIsMainThread(NS_IsMainThread())
{
if (mIsMainThread) {
nsContentUtils::EnterMicroTask();
}
// Compute the caller's subject principal (if necessary) early, before we
// do anything that might perturb the relevant state.
nsIPrincipal* webIDLCallerPrincipal = nullptr;
@ -302,6 +306,12 @@ CallbackObject::CallSetup::~CallSetup()
mAutoIncumbentScript.reset();
mAutoEntryScript.reset();
// It is important that this is the last thing we do, after leaving the
// compartment and undoing all our entry/incumbent script changes
if (mIsMainThread) {
nsContentUtils::LeaveMicroTask();
}
}
already_AddRefed<nsISupports>

Просмотреть файл

@ -34,12 +34,15 @@ function isTopBrowserElement(docShell) {
}
if (!('BrowserElementIsPreloaded' in this)) {
if (isTopBrowserElement(docShell) &&
Services.prefs.getBoolPref("dom.mozInputMethod.enabled")) {
try {
Services.scriptloader.loadSubScript("chrome://global/content/forms.js");
} catch (e) {
if (isTopBrowserElement(docShell)) {
if (Services.prefs.getBoolPref("dom.mozInputMethod.enabled")) {
try {
Services.scriptloader.loadSubScript("chrome://global/content/forms.js");
} catch (e) {
}
}
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js");
}
if (Services.prefs.getIntPref("dom.w3c_touch_events.enabled") == 1) {

Просмотреть файл

@ -0,0 +1,90 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
dump("###################################### BrowserElementCopyPaste.js loaded\n");
let CopyPasteAssistent = {
COMMAND_MAP: {
'cut': 'cmd_cut',
'copy': 'cmd_copyAndCollapseToEnd',
'paste': 'cmd_paste',
'selectall': 'cmd_selectAll'
},
init: function() {
addEventListener('mozcaretstatechanged',
this._caretStateChangedHandler.bind(this),
/* useCapture = */ true,
/* wantsUntrusted = */ false);
addMessageListener('browser-element-api:call', this._browserAPIHandler.bind(this));
},
_browserAPIHandler: function(e) {
switch (e.data.msg_name) {
case 'copypaste-do-command':
if (this._isCommandEnabled(e.data.command)) {
docShell.doCommand(COMMAND_MAP[e.data.command]);
}
break;
}
},
_isCommandEnabled: function(cmd) {
let command = this.COMMAND_MAP[cmd];
if (!command) {
return false;
}
return docShell.isCommandEnabled(command);
},
_caretStateChangedHandler: function(e) {
e.stopPropagation();
let boundingClientRect = e.boundingClientRect;
let canPaste = this._isCommandEnabled("paste");
let zoomFactor = content.innerWidth == 0 ? 1 : content.screen.width / content.innerWidth;
let detail = {
rect: {
width: boundingClientRect ? boundingClientRect.width : 0,
height: boundingClientRect ? boundingClientRect.height : 0,
top: boundingClientRect ? boundingClientRect.top : 0,
bottom: boundingClientRect ? boundingClientRect.bottom : 0,
left: boundingClientRect ? boundingClientRect.left : 0,
right: boundingClientRect ? boundingClientRect.right : 0,
},
commands: {
canSelectAll: this._isCommandEnabled("selectall"),
canCut: this._isCommandEnabled("cut"),
canCopy: this._isCommandEnabled("copy"),
canPaste: this._isCommandEnabled("paste"),
},
zoomFactor: zoomFactor,
reason: e.reason,
collapsed: e.collapsed,
caretVisible: e.caretVisible,
selectionVisible: e.selectionVisible
};
// Get correct geometry information if we have nested iframe.
let currentWindow = e.target.defaultView;
while (currentWindow.realFrameElement) {
let currentRect = currentWindow.realFrameElement.getBoundingClientRect();
detail.rect.top += currentRect.top;
detail.rect.bottom += currentRect.top;
detail.rect.left += currentRect.left;
detail.rect.right += currentRect.left;
currentWindow = currentWindow.realFrameElement.ownerDocument.defaultView;
}
sendAsyncMsg('caretstatechanged', detail);
},
};
CopyPasteAssistent.init();

Просмотреть файл

@ -87,6 +87,7 @@ function BrowserElementParent() {
Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true);
Services.obs.addObserver(this, 'copypaste-docommand', /* ownsWeak = */ true);
Services.obs.addObserver(this, 'ask-children-to-execute-copypaste-command', /* ownsWeak = */ true);
}
BrowserElementParent.prototype = {
@ -203,6 +204,7 @@ BrowserElementParent.prototype = {
"got-set-input-method-active": this._gotDOMRequestResult,
"selectionstatechanged": this._handleSelectionStateChanged,
"scrollviewchange": this._handleScrollViewChange,
"caretstatechanged": this._handleCaretStateChanged,
};
let mmSecuritySensitiveCalls = {
@ -438,6 +440,34 @@ BrowserElementParent.prototype = {
this._frameElement.dispatchEvent(evt);
},
// Called when state of accessible caret in child has changed.
// The fields of data is as following:
// - rect: Contains bounding rectangle of selection, Include width, height,
// top, bottom, left and right.
// - commands: Describe what commands can be executed in child. Include canSelectAll,
// canCut, canCopy and canPaste. For example: if we want to check if cut
// command is available, using following code, if (data.commands.canCut) {}.
// - zoomFactor: Current zoom factor in child frame.
// - reason: The reason causes the state changed. Include "visibilitychange",
// "updateposition", "longpressonemptycontent", "taponcaret", "presscaret",
// "releasecaret".
// - collapsed: Indicate current selection is collapsed or not.
// - caretVisible: Indicate the caret visiibility.
// - selectionVisible: Indicate current selection is visible or not.
_handleCaretStateChanged: function(data) {
let evt = this._createEvent('caretstatechanged', data.json,
/* cancelable = */ false);
let self = this;
function sendDoCommandMsg(cmd) {
let data = { command: cmd };
self._sendAsyncMsg('copypaste-do-command', data);
}
Cu.exportFunction(sendDoCommandMsg, evt.detail, { defineAs: 'sendDoCommandMsg' });
this._frameElement.dispatchEvent(evt);
},
_handleScrollViewChange: function(data) {
let evt = this._createEvent("scrollviewchange", data.json,
/* cancelable = */ false);
@ -979,6 +1009,11 @@ BrowserElementParent.prototype = {
this._sendAsyncMsg('do-command', { command: data });
}
break;
case 'ask-children-to-execute-copypaste-command':
if (this._isAlive() && this._frameElement == subject.wrappedJSObject) {
this._sendAsyncMsg('copypaste-do-command', { command: data });
}
break;
default:
debug('Unknown topic: ' + topic);
break;

Просмотреть файл

@ -65,6 +65,10 @@ const browserElementTestHelpers = {
this._setPref('selectioncaret.enabled', value);
},
setAccessibleCaretEnabledPref: function(value) {
this._setPref('layout.accessiblecaret.enabled', value);
},
getOOPByDefaultPref: function() {
return this._getBoolPref("dom.ipc.browser_frames.oop_by_default");
},

Просмотреть файл

@ -6,8 +6,10 @@
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout("untriaged");
SimpleTest.requestLongerTimeout(2); // slow on android
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.setSelectionChangeEnabledPref(true);
browserElementTestHelpers.setSelectionChangeEnabledPref(false);
browserElementTestHelpers.setAccessibleCaretEnabledPref(true);
browserElementTestHelpers.addPermission();
const { Services } = SpecialPowers.Cu.import('resource://gre/modules/Services.jsm');
@ -21,6 +23,7 @@ var defaultData;
var pasteData;
var focusScript;
var createEmbededFrame = false;
var testSelectionChange = false;
function copyToClipboard(str) {
gTextarea.value = str;
@ -89,6 +92,14 @@ function doCommand(cmd) {
'copypaste-docommand', cmd);
}
function rerunTest() {
// clean up and run test again.
document.body.removeChild(iframeOuter);
document.body.removeChild(gTextarea);
state = 0;
runTest();
}
function dispatchTest(e) {
iframeInner.addEventListener("mozbrowserloadend", function onloadend2(e) {
iframeInner.removeEventListener("mozbrowserloadend", onloadend2);
@ -160,15 +171,23 @@ function dispatchTest(e) {
break;
default:
if (createEmbededFrame || browserElementTestHelpers.getOOPByDefaultPref()) {
SimpleTest.finish();
if (testSelectionChange) {
SimpleTest.finish();
return;
} else {
testSelectionChange = true;
createEmbededFrame = false;
SpecialPowers.pushPrefEnv(
{'set':
[['selectioncaret.enabled', true],
['layout.accessiblecaret.enabled', false]]},
function() {
rerunTest();
});
}
} else {
createEmbededFrame = true;
// clean up and run test again.
document.body.removeChild(iframeOuter);
document.body.removeChild(gTextarea);
state = 0;
runTest();
rerunTest();
}
break;
}
@ -183,14 +202,17 @@ function isChildProcess() {
function testSelectAll(e) {
// Skip mozbrowser test if we're at child process.
if (!isChildProcess()) {
iframeOuter.addEventListener("mozbrowserselectionstatechanged", function selectchangeforselectall(e) {
if (e.detail.states.indexOf('selectall') == 0) {
iframeOuter.removeEventListener("mozbrowserselectionstatechanged", selectchangeforselectall, true);
let eventName = testSelectionChange ? "mozbrowserselectionstatechanged" : "mozbrowsercaretstatechanged";
iframeOuter.addEventListener(eventName, function selectchangeforselectall(e) {
if (!e.detail.states || e.detail.states.indexOf('selectall') == 0) {
iframeOuter.removeEventListener(eventName, selectchangeforselectall, true);
ok(true, "got mozbrowserselectionstatechanged event." + stateMeaning);
ok(e.detail, "event.detail is not null." + stateMeaning);
ok(e.detail.width != 0, "event.detail.width is not zero" + stateMeaning);
ok(e.detail.height != 0, "event.detail.height is not zero" + stateMeaning);
ok(e.detail.states, "event.detail.state " + e.detail.states);
if (testSelectionChange) {
ok(e.detail.states, "event.detail.state " + e.detail.states);
}
SimpleTest.executeSoon(function() { testCopy1(e); });
}
}, true);

Просмотреть файл

@ -170,6 +170,7 @@ class WebGLContext
friend class WebGLExtensionCompressedTexturePVRTC;
friend class WebGLExtensionCompressedTextureS3TC;
friend class WebGLExtensionDepthTexture;
friend class WebGLExtensionDisjointTimerQuery;
friend class WebGLExtensionDrawBuffers;
friend class WebGLExtensionLoseContext;
friend class WebGLExtensionVertexArray;
@ -1601,6 +1602,7 @@ public:
friend class WebGLSampler;
friend class WebGLShader;
friend class WebGLSync;
friend class WebGLTimerQuery;
friend class WebGLTransformFeedback;
friend class WebGLUniformLocation;
friend class WebGLVertexArray;

Просмотреть файл

@ -36,6 +36,7 @@ WebGLContext::GetExtensionString(WebGLExtensionID ext)
WEBGL_EXTENSION_IDENTIFIER(EXT_shader_texture_lod)
WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB)
WEBGL_EXTENSION_IDENTIFIER(EXT_texture_filter_anisotropic)
WEBGL_EXTENSION_IDENTIFIER(EXT_disjoint_timer_query)
WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint)
WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives)
WEBGL_EXTENSION_IDENTIFIER(OES_texture_float)
@ -179,13 +180,13 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
if (Preferences::GetBool("webgl.enable-draft-extensions", false) ||
IsWebGL2())
{
/* None for now.
switch (ext) {
case WebGLExtensionID::EXT_disjoint_timer_query:
return WebGLExtensionDisjointTimerQuery::IsSupported(this);
default:
// For warnings-as-errors.
break;
}
*/
}
return false;
@ -312,6 +313,9 @@ WebGLContext::EnableExtension(WebGLExtensionID ext)
case WebGLExtensionID::EXT_color_buffer_half_float:
obj = new WebGLExtensionColorBufferHalfFloat(this);
break;
case WebGLExtensionID::EXT_disjoint_timer_query:
obj = new WebGLExtensionDisjointTimerQuery(this);
break;
case WebGLExtensionID::EXT_frag_depth:
obj = new WebGLExtensionFragDepth(this);
break;

Просмотреть файл

@ -177,6 +177,21 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
}
}
if (IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
if (pname == LOCAL_GL_TIMESTAMP_EXT) {
GLuint64 iv = 0;
gl->fGetInteger64v(pname, (GLint64*) &iv);
return JS::NumberValue(uint64_t(iv));
} else if (pname == LOCAL_GL_GPU_DISJOINT_EXT) {
// When disjoint isn't supported, leave as false.
realGLboolean disjoint = 0;
if (gl->IsExtensionSupported(gl::GLContext::EXT_disjoint_timer_query)) {
gl->fGetBooleanv(pname, &disjoint);
}
return JS::BooleanValue(bool(disjoint));
}
}
if (IsWebGL2()) {
switch (pname) {
case LOCAL_GL_MAX_SAMPLES:

Просмотреть файл

@ -0,0 +1,247 @@
/* -*- 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 "WebGLExtensions.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "mozilla/dom/BindingUtils.h"
#include "GLContext.h"
#include "WebGLContext.h"
#include "WebGLTimerQuery.h"
namespace mozilla {
WebGLExtensionDisjointTimerQuery::WebGLExtensionDisjointTimerQuery(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
, mActiveQuery(nullptr)
{
MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
}
WebGLExtensionDisjointTimerQuery::~WebGLExtensionDisjointTimerQuery()
{
}
already_AddRefed<WebGLTimerQuery>
WebGLExtensionDisjointTimerQuery::CreateQueryEXT()
{
if (mIsLost)
return nullptr;
nsRefPtr<WebGLTimerQuery> query = WebGLTimerQuery::Create(mContext);
return query.forget();
}
void
WebGLExtensionDisjointTimerQuery::DeleteQueryEXT(WebGLTimerQuery* query)
{
if (mIsLost)
return;
if (!mContext->ValidateObject("deleteQueryEXT", query))
return;
query->RequestDelete();
}
bool
WebGLExtensionDisjointTimerQuery::IsQueryEXT(WebGLTimerQuery* query)
{
if (!query)
return false;
if (!mContext->ValidateObjectAllowDeleted("isQueryEXT", query))
return false;
if (query->IsDeleted())
return false;
return true;
}
void
WebGLExtensionDisjointTimerQuery::BeginQueryEXT(GLenum target,
WebGLTimerQuery* query)
{
if (mIsLost)
return;
if (!mContext->ValidateObject("beginQueryEXT", query))
return;
if (query->HasEverBeenBound() && query->Target() != target) {
mContext->ErrorInvalidOperation("beginQueryEXT: Query is already bound"
" to a different target.");
return;
}
if (target != LOCAL_GL_TIME_ELAPSED_EXT) {
mContext->ErrorInvalidEnumInfo("beginQueryEXT: Can only begin on target"
" TIME_ELAPSED_EXT.", target);
return;
}
if (mActiveQuery) {
mContext->ErrorInvalidOperation("beginQueryEXT: A query is already"
" active.");
return;
}
mContext->MakeContextCurrent();
gl::GLContext* gl = mContext->GL();
gl->fBeginQuery(target, query->GLName());
query->BindTo(LOCAL_GL_TIME_ELAPSED_EXT);
mActiveQuery = query;
}
void
WebGLExtensionDisjointTimerQuery::EndQueryEXT(GLenum target)
{
if (mIsLost)
return;
if (target != LOCAL_GL_TIME_ELAPSED_EXT) {
mContext->ErrorInvalidEnumInfo("endQueryEXT: Can only end on"
" TIME_ELAPSED_EXT.", target);
return;
}
if (!mActiveQuery) {
mContext->ErrorInvalidOperation("endQueryEXT: A query is not active.");
return;
}
mContext->MakeContextCurrent();
mContext->GL()->fEndQuery(target);
mActiveQuery = nullptr;
}
void
WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLTimerQuery* query,
GLenum target)
{
if (mIsLost)
return;
if (!mContext->ValidateObject("queryCounterEXT", query))
return;
if (target != LOCAL_GL_TIMESTAMP_EXT) {
mContext->ErrorInvalidEnumInfo("queryCounterEXT: requires"
" TIMESTAMP_EXT.", target);
return;
}
mContext->MakeContextCurrent();
mContext->GL()->fQueryCounter(query->GLName(), target);
query->BindTo(LOCAL_GL_TIMESTAMP_EXT);
}
void
WebGLExtensionDisjointTimerQuery::GetQueryEXT(JSContext* cx, GLenum target,
GLenum pname,
JS::MutableHandle<JS::Value> retval)
{
if (mIsLost)
return;
mContext->MakeContextCurrent();
switch (pname) {
case LOCAL_GL_CURRENT_QUERY_EXT: {
if (target != LOCAL_GL_TIME_ELAPSED_EXT) {
mContext->ErrorInvalidEnumInfo("getQueryEXT: Invalid query target.",
target);
return;
}
if (mActiveQuery) {
JS::Rooted<JS::Value> v(cx);
dom::GetOrCreateDOMReflector(cx, mActiveQuery.get(), &v);
retval.set(v);
} else {
retval.set(JS::NullValue());
}
break;
}
case LOCAL_GL_QUERY_COUNTER_BITS_EXT: {
if (target != LOCAL_GL_TIME_ELAPSED_EXT &&
target != LOCAL_GL_TIMESTAMP_EXT) {
mContext->ErrorInvalidEnumInfo("getQueryEXT: Invalid query target.",
target);
return;
}
GLint bits = 0;
mContext->GL()->fGetQueryiv(target, pname, &bits);
retval.set(JS::Int32Value(int32_t(bits)));
break;
}
default:
mContext->ErrorInvalidEnumInfo("getQueryEXT: Invalid query property.",
pname);
break;
}
}
void
WebGLExtensionDisjointTimerQuery::GetQueryObjectEXT(JSContext* cx,
WebGLTimerQuery* query,
GLenum pname,
JS::MutableHandle<JS::Value> retval)
{
if (mIsLost)
return;
if (!mContext->ValidateObject("getQueryObjectEXT", query))
return;
if (query == mActiveQuery.get()) {
mContext->ErrorInvalidOperation("getQueryObjectEXT: Query must not be"
" active.");
}
mContext->MakeContextCurrent();
// XXX: Note that the query result *may change* within the same task!
// This does not follow the specification, which states that all calls
// checking query results must return the same value until the event loop
// is empty.
switch (pname) {
case LOCAL_GL_QUERY_RESULT_EXT: {
GLuint64 result = 0;
mContext->GL()->fGetQueryObjectui64v(query->GLName(),
LOCAL_GL_QUERY_RESULT_EXT,
&result);
retval.set(JS::NumberValue(result));
break;
}
case LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT: {
GLuint avail = 0;
mContext->GL()->fGetQueryObjectuiv(query->GLName(),
LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT,
&avail);
retval.set(JS::BooleanValue(bool(avail)));
break;
}
default:
mContext->ErrorInvalidEnumInfo("getQueryObjectEXT: Invalid query"
" property.", pname);
break;
}
}
bool
WebGLExtensionDisjointTimerQuery::IsSupported(const WebGLContext* webgl)
{
webgl->MakeContextCurrent();
gl::GLContext* gl = webgl->GL();
return gl->IsSupported(gl::GLFeature::query_objects) &&
gl->IsSupported(gl::GLFeature::get_query_object_i64v) &&
gl->IsSupported(gl::GLFeature::query_counter); // provides GL_TIMESTAMP
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDisjointTimerQuery)
} // namespace mozilla

Просмотреть файл

@ -16,6 +16,8 @@ namespace mozilla {
class WebGLContext;
class WebGLShader;
class WebGLQuery;
class WebGLTimerQuery;
class WebGLVertexArray;
class WebGLExtensionBase
@ -329,6 +331,36 @@ public:
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionDisjointTimerQuery
: public WebGLExtensionBase
{
public:
explicit WebGLExtensionDisjointTimerQuery(WebGLContext* webgl);
virtual ~WebGLExtensionDisjointTimerQuery();
already_AddRefed<WebGLTimerQuery> CreateQueryEXT();
void DeleteQueryEXT(WebGLTimerQuery* query);
bool IsQueryEXT(WebGLTimerQuery* query);
void BeginQueryEXT(GLenum target, WebGLTimerQuery* query);
void EndQueryEXT(GLenum target);
void QueryCounterEXT(WebGLTimerQuery* query, GLenum target);
void GetQueryEXT(JSContext *cx, GLenum target, GLenum pname,
JS::MutableHandle<JS::Value> retval);
void GetQueryObjectEXT(JSContext *cx, WebGLTimerQuery* query,
GLenum pname,
JS::MutableHandle<JS::Value> retval);
static bool IsSupported(const WebGLContext*);
DECL_WEBGL_EXTENSION_GOOP
private:
/**
* An active TIME_ELAPSED query participating in a begin/end block.
*/
WebGLRefPtr<WebGLTimerQuery> mActiveQuery;
};
} // namespace mozilla
#endif // WEBGL_EXTENSIONS_H_

Просмотреть файл

@ -454,4 +454,10 @@ STRONG_GLENUM_BEGIN(BufferBinding)
STRONG_GLENUM_VALUE(TRANSFORM_FEEDBACK_BUFFER), // 0x8C8E
STRONG_GLENUM_END(BufferBinding)
STRONG_GLENUM_BEGIN(QueryBinding)
STRONG_GLENUM_VALUE(NONE),
STRONG_GLENUM_VALUE(TIME_ELAPSED_EXT),
STRONG_GLENUM_VALUE(TIMESTAMP_EXT),
STRONG_GLENUM_END(QueryBinding)
#endif // WEBGL_STRONG_TYPES_H_

Просмотреть файл

@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLTimerQuery.h"
#include "GLContext.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "nsContentUtils.h"
#include "WebGLContext.h"
namespace mozilla {
JSObject*
WebGLTimerQuery::WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto)
{
return dom::WebGLTimerQueryBinding::Wrap(cx, this, aGivenProto);
}
WebGLTimerQuery::WebGLTimerQuery(WebGLContext* webgl, GLuint aName)
: WebGLBindableName<QueryBinding>(aName)
, WebGLContextBoundObject(webgl)
{
}
WebGLTimerQuery*
WebGLTimerQuery::Create(WebGLContext* webgl)
{
GLuint name = 0;
webgl->MakeContextCurrent();
webgl->gl->fGenQueries(1, &name);
return new WebGLTimerQuery(webgl, name);
}
void
WebGLTimerQuery::Delete()
{
mContext->MakeContextCurrent();
mContext->gl->fDeleteQueries(1, &mGLName);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTimerQuery)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTimerQuery, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLTimerQuery, Release)
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef WEBGL_TIMER_QUERY_H_
#define WEBGL_TIMER_QUERY_H_
#include "nsWrapperCache.h"
#include "WebGLObjectModel.h"
namespace mozilla {
class WebGLTimerQuery final
: public nsWrapperCache
, public WebGLBindableName<QueryBinding>
, public WebGLRefCountedObject<WebGLTimerQuery>
, public WebGLContextBoundObject
{
public:
static WebGLTimerQuery* Create(WebGLContext* webgl);
// WebGLRefCountedObject
void Delete();
// nsWrapperCache
WebGLContext* GetParentObject() const {
return Context();
}
// NS
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override;
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTimerQuery)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTimerQuery)
private:
explicit WebGLTimerQuery(WebGLContext* webgl, GLuint aName);
~WebGLTimerQuery() {
DeleteOnce();
}
friend class WebGLExtensionDisjointTimerQuery;
};
} // namespace mozilla
#endif // WEBGL_TIMER_QUERY_H_

Просмотреть файл

@ -151,6 +151,7 @@ enum class WebGLExtensionID : uint8_t {
EXT_sRGB,
EXT_shader_texture_lod,
EXT_texture_filter_anisotropic,
EXT_disjoint_timer_query,
OES_element_index_uint,
OES_standard_derivatives,
OES_texture_float,

Просмотреть файл

@ -93,6 +93,7 @@ UNIFIED_SOURCES += [
'WebGLExtensionDebugRendererInfo.cpp',
'WebGLExtensionDebugShaders.cpp',
'WebGLExtensionDepthTexture.cpp',
'WebGLExtensionDisjointTimerQuery.cpp',
'WebGLExtensionDrawBuffers.cpp',
'WebGLExtensionElementIndexUint.cpp',
'WebGLExtensionFragDepth.cpp',
@ -120,6 +121,7 @@ UNIFIED_SOURCES += [
'WebGLSync.cpp',
'WebGLTexelConversions.cpp',
'WebGLTexture.cpp',
'WebGLTimerQuery.cpp',
'WebGLTransformFeedback.cpp',
'WebGLUniformLocation.cpp',
'WebGLValidateStrings.cpp',

Просмотреть файл

@ -30,6 +30,7 @@ skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests
# We haven't cleaned up the Try results yet, but let's get this on the books first.
[webgl-mochitest/test_webgl_conformance.html]
skip-if = buildapp == 'mulet' || toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
[webgl-mochitest/test_webgl_disjoint_timer_query.html]
[webgl-mochitest/test_webgl_request_context.html]
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
[webgl-mochitest/test_webgl_request_mismatch.html]

Просмотреть файл

@ -0,0 +1,65 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='UTF-8'>
<title>WebGL test: Test EXT_disjoint_timer_query.</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<script src="webgl-util.js"></script>
</head>
<body>
<canvas id="c"></canvas>
<script>
function doTest() {
var gl = WebGLUtil.getWebGL('c', true);
var ext = gl.getExtension('EXT_disjoint_timer_query');
if (!ext) {
ok(true, "EXT_disjoint_timer_query may be unsupported.");
SimpleTest.finish();
return;
}
ok(!ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT),
"No query is active initially.");
var elapsedQuery = ext.createQueryEXT();
ok(elapsedQuery, "Query creation works.");
ok(ext.isQueryEXT(elapsedQuery), "New query is valid after creation.");
ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, elapsedQuery);
is(ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT), elapsedQuery,
"Query is active after beginQueryEXT.");
ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
gl.flush();
ok(!ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT),
"Query is inactive after endQueryEXT.");
ok(ext.getQueryObjectEXT(elapsedQuery, ext.QUERY_RESULT_AVAILABLE_EXT),
"Time elapsed query is available immediately after flush.");
ext.deleteQueryEXT(elapsedQuery);
ok(!ext.isQueryEXT(elapsedQuery), "Query is no longer valid after deletion.");
var timestampQuery = ext.createQueryEXT();
ext.queryCounterEXT(timestampQuery, ext.TIMESTAMP_EXT);
gl.flush();
ok(ext.getQueryObjectEXT(timestampQuery, ext.QUERY_RESULT_AVAILABLE_EXT),
"Timestamp query should be available immediately after flush.");
ok(ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30,
"Timestamp must be at least 30 bits to hold at least 1 second of timing.");
ok(ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30,
"Time elapsed must be at least 30 bits to hold at least 1 second of timing.");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [['webgl.enable-draft-extensions', true]]}, doTest);
</script>
</body>
</html>

Просмотреть файл

@ -20,9 +20,6 @@
#include "TabChild.h"
#include "mozilla/Attributes.h"
#ifdef ACCESSIBILITY
#include "mozilla/a11y/DocAccessibleChild.h"
#endif
#include "mozilla/LookAndFeel.h"
#include "mozilla/Preferences.h"
#include "mozilla/ProcessHangMonitorIPC.h"
@ -857,22 +854,6 @@ ContentChild::InitXPCOM()
InitOnContentProcessCreated();
}
a11y::PDocAccessibleChild*
ContentChild::AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&)
{
MOZ_ASSERT(false, "should never call this!");
return nullptr;
}
bool
ContentChild::DeallocPDocAccessibleChild(a11y::PDocAccessibleChild* aChild)
{
#ifdef ACCESSIBILITY
delete static_cast<mozilla::a11y::DocAccessibleChild*>(aChild);
#endif
return true;
}
PMemoryReportRequestChild*
ContentChild::AllocPMemoryReportRequestChild(const uint32_t& aGeneration,
const bool &aAnonymize,

Просмотреть файл

@ -446,8 +446,6 @@ public:
const ContentParentId& aCpID,
const bool& aIsForApp,
const bool& aIsForBrowser) override;
virtual PDocAccessibleChild* AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&) override;
virtual bool DeallocPDocAccessibleChild(PDocAccessibleChild*) override;
void GetAvailableDictionaries(InfallibleTArray<nsString>& aDictionaries);

Просмотреть файл

@ -32,10 +32,6 @@
#include "IHistory.h"
#include "imgIContainer.h"
#include "mozIApplication.h"
#ifdef ACCESSIBILITY
#include "mozilla/a11y/DocAccessibleParent.h"
#include "nsAccessibilityService.h"
#endif
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
#include "mozilla/dom/DataStoreService.h"
@ -3155,42 +3151,6 @@ ContentParent::Observe(nsISupports* aSubject,
return NS_OK;
}
a11y::PDocAccessibleParent*
ContentParent::AllocPDocAccessibleParent(PDocAccessibleParent* aParent, const uint64_t&)
{
#ifdef ACCESSIBILITY
return new a11y::DocAccessibleParent();
#else
return nullptr;
#endif
}
bool
ContentParent::DeallocPDocAccessibleParent(PDocAccessibleParent* aParent)
{
#ifdef ACCESSIBILITY
delete static_cast<a11y::DocAccessibleParent*>(aParent);
#endif
return true;
}
bool
ContentParent::RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc, PDocAccessibleParent* aParentDoc, const uint64_t& aParentID)
{
#ifdef ACCESSIBILITY
auto doc = static_cast<a11y::DocAccessibleParent*>(aDoc);
if (aParentDoc) {
MOZ_ASSERT(aParentID);
auto parentDoc = static_cast<a11y::DocAccessibleParent*>(aParentDoc);
return parentDoc->AddChildDoc(doc, aParentID);
} else {
MOZ_ASSERT(!aParentID);
a11y::DocManager::RemoteDocAdded(doc);
}
#endif
return true;
}
PGMPServiceParent*
ContentParent::AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)

Просмотреть файл

@ -845,11 +845,6 @@ private:
int32_t* aSliceRefCnt,
bool* aResult) override;
virtual PDocAccessibleParent* AllocPDocAccessibleParent(PDocAccessibleParent*, const uint64_t&) override;
virtual bool DeallocPDocAccessibleParent(PDocAccessibleParent*) override;
virtual bool RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc,
PDocAccessibleParent* aParentDoc, const uint64_t& aParentID) override;
virtual PWebrtcGlobalParent* AllocPWebrtcGlobalParent() override;
virtual bool DeallocPWebrtcGlobalParent(PWebrtcGlobalParent *aActor) override;

Просмотреть файл

@ -9,6 +9,7 @@ include protocol PBlob;
include protocol PColorPicker;
include protocol PContent;
include protocol PContentBridge;
include protocol PDocAccessible;
include protocol PDocumentRenderer;
include protocol PFilePicker;
include protocol PIndexedDBPermissionRequest;
@ -98,6 +99,7 @@ prio(normal upto urgent) sync protocol PBrowser
manager PContent or PContentBridge;
manages PColorPicker;
manages PDocAccessible;
manages PDocumentRenderer;
manages PFilePicker;
manages PIndexedDBPermissionRequest;
@ -115,6 +117,14 @@ both:
PRenderFrame();
parent:
/**
* Tell the parent process a new accessible document has been created.
* aParentDoc is the accessible document it was created in if any, and
* aParentAcc is the id of the accessible in that document the new document
* is a child of.
*/
PDocAccessible(nullable PDocAccessible aParentDoc, uint64_t aParentAcc);
/*
* Creates a new remoted nsIWidget connection for windowed plugins
* in e10s mode. This is always initiated from the child in response

Просмотреть файл

@ -15,7 +15,6 @@ include protocol PContentBridge;
include protocol PContentPermissionRequest;
include protocol PCycleCollectWithLogs;
include protocol PCrashReporter;
include protocol PDocAccessible;
include protocol PPSMContentDownloader;
include protocol PExternalHelperApp;
include protocol PDeviceStorageRequest;
@ -422,7 +421,6 @@ prio(normal upto urgent) sync protocol PContent
manages PContentPermissionRequest;
manages PCrashReporter;
manages PCycleCollectWithLogs;
manages PDocAccessible;
manages PDeviceStorageRequest;
manages PFileSystemRequest;
manages PPSMContentDownloader;
@ -654,14 +652,6 @@ child:
*/
GamepadUpdate(GamepadChangeEvent aGamepadEvent);
parent:
/**
* Tell the parent process a new accessible document has been created.
* aParentDoc is the accessible document it was created in if any, and
* aParentAcc is the id of the accessible in that document the new document
* is a child of.
*/
PDocAccessible(nullable PDocAccessible aParentDoc, uint64_t aParentAcc);
/**
* Tell the content process some attributes of itself. This is
* among the first information queried by content processes after

Просмотреть файл

@ -8,6 +8,9 @@
#include "TabChild.h"
#ifdef ACCESSIBILITY
#include "mozilla/a11y/DocAccessibleChild.h"
#endif
#include "Layers.h"
#include "ContentChild.h"
#include "TabParent.h"
@ -202,6 +205,28 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(TabChildBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(TabChildBase)
// For the root frame, Screen and ParentLayer pixels are interchangeable.
// nsViewportInfo stores zoom values as CSSToScreenScale (because it's a
// data structure specific to the root frame), while FrameMetrics and
// ZoomConstraints store zoom values as CSSToParentLayerScale (because they
// are not specific to the root frame). We define convenience functions for
// converting between the two. As the name suggests, they should only be used
// when dealing with the root frame!
CSSToScreenScale ConvertScaleForRoot(CSSToParentLayerScale aScale)
{
return ViewTargetAs<ScreenPixel>(aScale, PixelCastJustification::ScreenIsParentLayerForRoot);
}
CSSToParentLayerScale ConvertScaleForRoot(CSSToScreenScale aScale)
{
return ViewTargetAs<ParentLayerPixel>(aScale, PixelCastJustification::ScreenIsParentLayerForRoot);
}
// Calculate the scale needed to fit the given viewport into the given display.
CSSToScreenScale CalculateIntrinsicScale(const ScreenIntSize& aDisplaySize, const CSSSize& aViewportSize)
{
return MaxScaleRatio(ScreenSize(aDisplaySize), aViewportSize);
}
void
TabChildBase::InitializeRootMetrics()
{
@ -212,7 +237,8 @@ TabChildBase::InitializeRootMetrics()
mLastRootMetrics.SetCompositionBounds(ParentLayerRect(
ParentLayerPoint(),
ParentLayerSize(ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenIsParentLayerForRoot))));
mLastRootMetrics.SetZoom(CSSToParentLayerScale2D(mLastRootMetrics.CalculateIntrinsicScale()));
mLastRootMetrics.SetZoom(CSSToParentLayerScale2D(
ConvertScaleForRoot(CalculateIntrinsicScale(mInnerSize, kDefaultViewportSize))));
mLastRootMetrics.SetDevPixelsPerCSSPixel(WebWidget()->GetDefaultScale());
// We use ParentLayerToLayerScale(1) below in order to turn the
// async zoom amount into the gecko zoom amount.
@ -264,20 +290,6 @@ TabChildBase::GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewp
std::max(htmlHeight, bodyHeight));
}
// For the root frame, Screen and ParentLayer pixels are interchangeable.
// nsViewportInfo stores zoom values as CSSToScreenScale (because it's a
// data structure specific to the root frame), while FrameMetrics and
// ZoomConstraints store zoom values as CSSToParentLayerScale (because they
// are not specific to the root frame). We define convenience functions for
// converting between the two. As the name suggests, they should only be used
// when dealing with the root frame!
CSSToScreenScale ConvertScaleForRoot(CSSToParentLayerScale aScale) {
return ViewTargetAs<ScreenPixel>(aScale, PixelCastJustification::ScreenIsParentLayerForRoot);
}
CSSToParentLayerScale ConvertScaleForRoot(CSSToScreenScale aScale) {
return ViewTargetAs<ParentLayerPixel>(aScale, PixelCastJustification::ScreenIsParentLayerForRoot);
}
bool
TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize)
{
@ -383,10 +395,9 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize)
// In all of these cases, we maintain how much actual content is visible
// within the screen width. Note that "actual content" may be different with
// respect to CSS pixels because of the CSS viewport size changing.
float oldIntrinsicScale =
std::max(oldScreenSize.width / oldBrowserSize.width,
oldScreenSize.height / oldBrowserSize.height);
metrics.ZoomBy(metrics.CalculateIntrinsicScale().scale / oldIntrinsicScale);
CSSToScreenScale oldIntrinsicScale = CalculateIntrinsicScale(oldScreenSize, oldBrowserSize);
CSSToScreenScale newIntrinsicScale = CalculateIntrinsicScale(mInnerSize, viewport);
metrics.ZoomBy(newIntrinsicScale.scale / oldIntrinsicScale.scale);
// Changing the zoom when we're not doing a first paint will get ignored
// by AsyncPanZoomController and causes a blurry flash.
@ -399,7 +410,7 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize)
// 0.0 to mean "did not calculate a zoom". In that case, we default
// it to the intrinsic scale.
if (viewportInfo.GetDefaultZoom().scale < 0.01f) {
viewportInfo.SetDefaultZoom(ConvertScaleForRoot(metrics.CalculateIntrinsicScale()));
viewportInfo.SetDefaultZoom(newIntrinsicScale);
}
CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom();
@ -2572,6 +2583,22 @@ TabChild::RecvSelectionEvent(const WidgetSelectionEvent& event)
return true;
}
a11y::PDocAccessibleChild*
TabChild::AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&)
{
MOZ_ASSERT(false, "should never call this!");
return nullptr;
}
bool
TabChild::DeallocPDocAccessibleChild(a11y::PDocAccessibleChild* aChild)
{
#ifdef ACCESSIBILITY
delete static_cast<mozilla::a11y::DocAccessibleChild*>(aChild);
#endif
return true;
}
PDocumentRendererChild*
TabChild::AllocPDocumentRendererChild(const nsRect& documentRect,
const mozilla::gfx::Matrix& transform,

Просмотреть файл

@ -391,6 +391,10 @@ public:
virtual bool RecvSwappedWithOtherRemoteLoader() override;
virtual PDocAccessibleChild* AllocPDocAccessibleChild(PDocAccessibleChild*,
const uint64_t&)
override;
virtual bool DeallocPDocAccessibleChild(PDocAccessibleChild*) override;
virtual PDocumentRendererChild*
AllocPDocumentRendererChild(const nsRect& documentRect, const gfx::Matrix& transform,
const nsString& bgcolor,

Просмотреть файл

@ -10,6 +10,10 @@
#include "AppProcessChecker.h"
#include "mozIApplication.h"
#ifdef ACCESSIBILITY
#include "mozilla/a11y/DocAccessibleParent.h"
#include "nsAccessibilityService.h"
#endif
#include "mozilla/BrowserElementParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/DataTransfer.h"
@ -1107,6 +1111,45 @@ TabParent::SetDocShell(nsIDocShell *aDocShell)
return NS_OK;
}
a11y::PDocAccessibleParent*
TabParent::AllocPDocAccessibleParent(PDocAccessibleParent* aParent,
const uint64_t&)
{
#ifdef ACCESSIBILITY
return new a11y::DocAccessibleParent();
#else
return nullptr;
#endif
}
bool
TabParent::DeallocPDocAccessibleParent(PDocAccessibleParent* aParent)
{
#ifdef ACCESSIBILITY
delete static_cast<a11y::DocAccessibleParent*>(aParent);
#endif
return true;
}
bool
TabParent::RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc,
PDocAccessibleParent* aParentDoc,
const uint64_t& aParentID)
{
#ifdef ACCESSIBILITY
auto doc = static_cast<a11y::DocAccessibleParent*>(aDoc);
if (aParentDoc) {
MOZ_ASSERT(aParentID);
auto parentDoc = static_cast<a11y::DocAccessibleParent*>(aParentDoc);
return parentDoc->AddChildDoc(doc, aParentID);
} else {
MOZ_ASSERT(!aParentID);
a11y::DocManager::RemoteDocAdded(doc);
}
#endif
return true;
}
PDocumentRendererParent*
TabParent::AllocPDocumentRendererParent(const nsRect& documentRect,
const gfx::Matrix& transform,

Просмотреть файл

@ -247,6 +247,14 @@ public:
AllocPColorPickerParent(const nsString& aTitle, const nsString& aInitialColor) override;
virtual bool DeallocPColorPickerParent(PColorPickerParent* aColorPicker) override;
virtual PDocAccessibleParent*
AllocPDocAccessibleParent(PDocAccessibleParent*, const uint64_t&) override;
virtual bool DeallocPDocAccessibleParent(PDocAccessibleParent*) override;
virtual bool
RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc,
PDocAccessibleParent* aParentDoc,
const uint64_t& aParentID) override;
void LoadURL(nsIURI* aURI);
// XXX/cjones: it's not clear what we gain by hiding these
// message-sending functions under a layer of indirection and

Просмотреть файл

@ -7,6 +7,7 @@ toolkit.jar:
content/global/remote-test-ipc.js (remote-test.js)
content/global/BrowserElementChild.js (../browser-element/BrowserElementChild.js)
content/global/BrowserElementChildPreload.js (../browser-element/BrowserElementChildPreload.js)
content/global/BrowserElementCopyPaste.js (../browser-element/BrowserElementCopyPaste.js)
content/global/BrowserElementPanning.js (../browser-element/BrowserElementPanning.js)
* content/global/BrowserElementPanningAPZDisabled.js (../browser-element/BrowserElementPanningAPZDisabled.js)
content/global/manifestMessages.js (manifestMessages.js)

Просмотреть файл

@ -103,6 +103,7 @@ const BrowserElementIsPreloaded = true;
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementPanning.js", global);
}
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js", global);
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementChildPreload.js", global);
Services.io.getProtocolHandler("app");

Просмотреть файл

@ -32,6 +32,7 @@ outlineitem = outline item
pagetab = tab
propertypage = property page
graphic = graphic
switch = switch
pushbutton = button
checkbutton = check button
radiobutton = radio button
@ -127,6 +128,8 @@ jumpAction = jumped
pressAction = pressed
checkAction = checked
uncheckAction = unchecked
onAction = on
offAction = off
selectAction = selected
unselectAction = unselected
openAction = opened
@ -151,7 +154,9 @@ tabReload = reloading
# Object states
stateChecked = checked
stateOn = on
stateNotChecked = not checked
stateOff = off
statePressed = pressed
# No string for a not pressed toggle button
stateExpanded = expanded

Просмотреть файл

@ -124,6 +124,8 @@ using dom::OwningBooleanOrMediaTrackConstraints;
using dom::SupportedAudioConstraints;
using dom::SupportedVideoConstraints;
static Atomic<bool> sInShutdown;
static bool
HostInDomain(const nsCString &aHost, const nsCString &aPattern)
{
@ -946,7 +948,7 @@ public:
nsRefPtr<nsDOMUserMediaStream> trackunion =
nsDOMUserMediaStream::CreateTrackUnionStream(window, mListener,
mAudioSource, mVideoSource);
if (!trackunion) {
if (!trackunion || sInShutdown) {
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
LOG(("Returning error for getUserMedia() - no stream"));
@ -954,7 +956,8 @@ public:
if (window) {
nsRefPtr<MediaStreamError> error = new MediaStreamError(window,
NS_LITERAL_STRING("InternalError"),
NS_LITERAL_STRING("No stream."));
sInShutdown ? NS_LITERAL_STRING("In shutdown") :
NS_LITERAL_STRING("No stream."));
onFailure->OnError(error);
}
return NS_OK;
@ -1009,7 +1012,7 @@ public:
// because that can take a while.
// Pass ownership of trackunion to the MediaOperationTask
// to ensure it's kept alive until the MediaOperationTask runs (at least).
MediaManager::GetMessageLoop()->PostTask(FROM_HERE,
MediaManager::PostTask(FROM_HERE,
new MediaOperationTask(MEDIA_START, mListener, trackunion,
tracksAvailableCallback,
mAudioSource, mVideoSource, false, mWindowID,
@ -1612,7 +1615,7 @@ MediaManager::Get() {
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (obs) {
obs->AddObserver(sSingleton, "xpcom-shutdown", false);
obs->AddObserver(sSingleton, "xpcom-will-shutdown", false);
obs->AddObserver(sSingleton, "getUserMedia:response:allow", false);
obs->AddObserver(sSingleton, "getUserMedia:response:deny", false);
obs->AddObserver(sSingleton, "getUserMedia:revoke", false);
@ -1644,12 +1647,17 @@ MediaManager::GetInstance()
}
/* static */
MessageLoop*
MediaManager::GetMessageLoop()
void
MediaManager::PostTask(const tracked_objects::Location& from_here, Task* task)
{
if (sInShutdown) {
// Can't safely delete task here since it may have items with specific
// thread-release requirements.
return;
}
NS_ASSERTION(Get(), "MediaManager singleton?");
NS_ASSERTION(Get()->mMediaThread, "No thread yet");
return Get()->mMediaThread->message_loop();
Get()->mMediaThread->message_loop()->PostTask(from_here, task);
}
/* static */ nsresult
@ -1783,6 +1791,9 @@ MediaManager::GetUserMedia(
task = new GetUserMediaTask(c, onSuccess.forget(),
onFailure.forget(), windowID, listener, mPrefs);
}
if (sInShutdown) {
return task->Denied(NS_LITERAL_STRING("In shutdown"));
}
nsIURI* docURI = aWindow->GetDocumentURI();
@ -1889,7 +1900,7 @@ MediaManager::GetUserMedia(
// XXX No full support for picture in Desktop yet (needs proper UI)
if (privileged ||
(fake && !Preferences::GetBool("media.navigator.permission.fake"))) {
MediaManager::GetMessageLoop()->PostTask(FROM_HERE, task.forget());
MediaManager::PostTask(FROM_HERE, task.forget());
} else {
bool isHTTPS = false;
if (docURI) {
@ -1974,6 +1985,7 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
NS_ENSURE_TRUE(aOnFailure, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(aOnSuccess, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(!sInShutdown, NS_ERROR_FAILURE);
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
@ -1994,7 +2006,7 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
}
MediaManager::GetMessageLoop()->PostTask(FROM_HERE,
MediaManager::PostTask(FROM_HERE,
new GetUserMediaDevicesTask(
aConstraints, onSuccess.forget(), onFailure.forget(),
(aInnerWindowID ? aInnerWindowID : aWindow->WindowID()),
@ -2027,6 +2039,7 @@ MediaManager::GetBackend(uint64_t aWindowId)
// This IS called off main-thread.
MutexAutoLock lock(mMutex);
if (!mBackend) {
MOZ_RELEASE_ASSERT(!sInShutdown); // we should never create a new backend in shutdown
#if defined(MOZ_WEBRTC)
mBackend = new MediaEngineWebRTC(mPrefs);
#else
@ -2202,8 +2215,10 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
LOG(("%s: %dx%d @%dfps (min %d)", __FUNCTION__,
mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mMinFPS));
}
} else if (!strcmp(aTopic, "xpcom-shutdown")) {
obs->RemoveObserver(this, "xpcom-shutdown");
} else if (!strcmp(aTopic, "xpcom-will-shutdown")) {
sInShutdown = true;
obs->RemoveObserver(this, "xpcom-will-shutdown");
obs->RemoveObserver(this, "getUserMedia:response:allow");
obs->RemoveObserver(this, "getUserMedia:response:deny");
obs->RemoveObserver(this, "getUserMedia:revoke");
@ -2216,22 +2231,43 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
prefs->RemoveObserver("media.navigator.video.default_minfps", this);
}
// Close off any remaining active windows.
GetActiveWindows()->Clear();
mActiveCallbacks.Clear();
mCallIds.Clear();
{
MutexAutoLock lock(mMutex);
if (mBackend) {
mBackend->Shutdown(); // ok to invoke multiple times
}
}
// Because mMediaThread is not an nsThread, we must dispatch to it so it can
// clean up BackgroundChild. Continue stopping thread once this is done.
class ShutdownTask : public Task
{
public:
explicit ShutdownTask(nsRunnable* aReply) : mReply(aReply) {}
ShutdownTask(TemporaryRef<MediaEngine> aBackend,
nsRunnable* aReply)
: mReply(aReply)
, mBackend(aBackend) {}
private:
virtual void
Run()
{
LOG(("MediaManager Thread Shutdown"));
MOZ_ASSERT(MediaManager::IsInMediaThread());
mozilla::ipc::BackgroundChild::CloseForCurrentThread();
NS_DispatchToMainThread(mReply);
// must explicitly do this before dispatching the reply, since the reply may kill us with Stop()
mBackend = nullptr; // last reference, will invoke Shutdown() again
if (NS_FAILED(NS_DispatchToMainThread(mReply))) {
LOG(("Will leak thread: DispatchToMainthread of reply runnable failed in MediaManager shutdown"));
}
}
nsRefPtr<nsRunnable> mReply;
RefPtr<MediaEngine> mBackend;
};
// Post ShutdownTask to execute on mMediaThread and pass in a lambda
@ -2241,20 +2277,25 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
// This is safe since this is guaranteed to be here since sSingleton isn't
// cleared until the lambda function clears it.
MediaManager::GetMessageLoop()->PostTask(FROM_HERE, new ShutdownTask(
media::NewRunnableFrom([this]() mutable {
// Close off any remaining active windows.
// note that this == sSingleton
nsRefPtr<MediaManager> that(sSingleton);
// Release the backend (and call Shutdown()) from within the MediaManager thread
RefPtr<MediaEngine> temp;
{
MutexAutoLock lock(mMutex);
GetActiveWindows()->Clear();
mActiveCallbacks.Clear();
mCallIds.Clear();
LOG(("Releasing MediaManager singleton and thread"));
// Note: won't be released immediately as the Observer has a ref to us
sSingleton = nullptr;
temp = mBackend.forget();
}
// Don't use MediaManager::PostTask() because we're sInShutdown=true here!
mMediaThread->message_loop()->PostTask(FROM_HERE, new ShutdownTask(
temp.forget(),
media::NewRunnableFrom([this, that]() mutable {
LOG(("MediaManager shutdown lambda running, releasing MediaManager singleton and thread"));
if (mMediaThread) {
mMediaThread->Stop();
}
mBackend = nullptr;
// we hold a ref to 'that' which is the same as sSingleton
sSingleton = nullptr;
return NS_OK;
})));
return NS_OK;
@ -2299,8 +2340,11 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
}
}
if (sInShutdown) {
return task->Denied(NS_LITERAL_STRING("In shutdown"));
}
// Reuse the same thread to save memory.
MediaManager::GetMessageLoop()->PostTask(FROM_HERE, task.forget());
MediaManager::PostTask(FROM_HERE, task.forget());
return NS_OK;
} else if (!strcmp(aTopic, "getUserMedia:response:deny")) {
@ -2498,8 +2542,7 @@ MediaManager::SanitizeDeviceIds(int64_t aSinceWhen)
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
LOG(("%s: sinceWhen = %llu", __FUNCTION__, aSinceWhen));
MediaManager::GetMessageLoop()->PostTask(FROM_HERE,
new SanitizeDeviceIdsTask(aSinceWhen));
MediaManager::PostTask(FROM_HERE, new SanitizeDeviceIdsTask(aSinceWhen));
return NS_OK;
}
@ -2616,12 +2659,10 @@ GetUserMediaCallbackMediaStreamListener::AudioConfig(bool aEchoOn,
{
if (mAudioSource) {
#ifdef MOZ_WEBRTC
mMediaThread->message_loop()->PostTask(FROM_HERE,
MediaManager::PostTask(FROM_HERE,
NewRunnableMethod(mAudioSource.get(), &MediaEngineSource::Config,
aEchoOn, aEcho, aAgcOn, aAGC, aNoiseOn,
aNoise, aPlayoutDelay));
#else
unused << mMediaThread;
#endif
}
}
@ -2634,7 +2675,7 @@ GetUserMediaCallbackMediaStreamListener::Invalidate()
// thread.
// Pass a ref to us (which is threadsafe) so it can query us for the
// source stream info.
MediaManager::GetMessageLoop()->PostTask(FROM_HERE,
MediaManager::PostTask(FROM_HERE,
new MediaOperationTask(MEDIA_STOP,
this, nullptr, nullptr,
mAudioSource, mVideoSource,
@ -2652,7 +2693,7 @@ GetUserMediaCallbackMediaStreamListener::StopScreenWindowSharing()
mVideoSource->GetMediaSource() == dom::MediaSourceEnum::Application ||
mVideoSource->GetMediaSource() == dom::MediaSourceEnum::Window)) {
// Stop the whole stream if there's no audio; just the video track if we have both
MediaManager::GetMessageLoop()->PostTask(FROM_HERE,
MediaManager::PostTask(FROM_HERE,
new MediaOperationTask(mAudioSource ? MEDIA_STOP_TRACK : MEDIA_STOP,
this, nullptr, nullptr,
nullptr, mVideoSource,
@ -2670,7 +2711,7 @@ GetUserMediaCallbackMediaStreamListener::StopTrack(TrackID aID, bool aIsAudio)
{
// XXX to support multiple tracks of a type in a stream, this should key off
// the TrackID and not just the type
MediaManager::GetMessageLoop()->PostTask(FROM_HERE,
MediaManager::PostTask(FROM_HERE,
new MediaOperationTask(MEDIA_STOP_TRACK,
this, nullptr, nullptr,
aIsAudio ? mAudioSource : nullptr,
@ -2696,7 +2737,7 @@ void
GetUserMediaCallbackMediaStreamListener::NotifyDirectListeners(MediaStreamGraph* aGraph,
bool aHasListeners)
{
MediaManager::GetMessageLoop()->PostTask(FROM_HERE,
MediaManager::PostTask(FROM_HERE,
new MediaOperationTask(MEDIA_DIRECT_LISTENERS,
this, nullptr, nullptr,
mAudioSource, mVideoSource,

Просмотреть файл

@ -71,6 +71,7 @@ public:
~GetUserMediaCallbackMediaStreamListener()
{
unused << mMediaThread;
// It's OK to release mStream on any thread; they have thread-safe
// refcounts.
}
@ -514,7 +515,7 @@ public:
// from MediaManager thread.
static MediaManager* Get();
static MediaManager* GetIfExists();
static MessageLoop* GetMessageLoop();
static void PostTask(const tracked_objects::Location& from_here, Task* task);
#ifdef DEBUG
static bool IsInMediaThread();
#endif

Просмотреть файл

@ -67,7 +67,7 @@ GMPChild::~GMPChild()
static bool
GetFileBase(const std::string& aPluginPath,
#if defined(XP_MACOSX)
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
nsCOMPtr<nsIFile>& aLibDirectory,
#endif
nsCOMPtr<nsIFile>& aFileBase,
@ -81,7 +81,7 @@ GetFileBase(const std::string& aPluginPath,
return false;
}
#if defined(XP_MACOSX)
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
if (NS_FAILED(aFileBase->Clone(getter_AddRefs(aLibDirectory)))) {
return false;
}
@ -107,13 +107,13 @@ GetFileBase(const std::string& aPluginPath,
static bool
GetPluginFile(const std::string& aPluginPath,
#if defined(XP_MACOSX)
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
nsCOMPtr<nsIFile>& aLibDirectory,
#endif
nsCOMPtr<nsIFile>& aLibFile)
{
nsAutoString baseName;
#ifdef XP_MACOSX
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
GetFileBase(aPluginPath, aLibDirectory, aLibFile, baseName);
#else
GetFileBase(aPluginPath, aLibFile, baseName);
@ -592,7 +592,7 @@ GetPluginVoucherFile(const std::string& aPluginPath,
nsCOMPtr<nsIFile>& aOutVoucherFile)
{
nsAutoString baseName;
#if defined(XP_MACOSX)
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
nsCOMPtr<nsIFile> libDir;
GetFileBase(aPluginPath, aOutVoucherFile, libDir, baseName);
#else

Просмотреть файл

@ -80,7 +80,7 @@ public:
virtual void Shutdown() override;
#if defined(XP_MACOSX)
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
virtual void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) override;
#endif
@ -275,7 +275,7 @@ GMPLoaderImpl::Shutdown()
}
}
#if defined(XP_MACOSX)
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
void
GMPLoaderImpl::SetSandboxInfo(MacSandboxInfo* aSandboxInfo)
{

Просмотреть файл

@ -10,7 +10,7 @@
#include <stdint.h>
#include "gmp-entrypoints.h"
#if defined(XP_MACOSX)
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
#include "mozilla/Sandbox.h"
#endif
@ -21,7 +21,7 @@ class SandboxStarter {
public:
virtual ~SandboxStarter() {}
virtual bool Start(const char* aLibPath) = 0;
#if defined(XP_MACOSX)
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
// On OS X we need to set Mac-specific sandbox info just before we start the
// sandbox, which we don't yet know when the GMPLoader and SandboxStarter
// objects are created.
@ -65,7 +65,7 @@ public:
// plugin library.
virtual void Shutdown() = 0;
#if defined(XP_MACOSX)
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
// On OS X we need to set Mac-specific sandbox info just before we start the
// sandbox, which we don't yet know when the GMPLoader and SandboxStarter
// objects are created.

Просмотреть файл

@ -64,6 +64,8 @@ public:
virtual void EnumerateAudioDevices(dom::MediaSourceEnum,
nsTArray<nsRefPtr<MediaEngineAudioSource> >*) = 0;
virtual void Shutdown() = 0;
protected:
virtual ~MediaEngine() {}
};
@ -81,6 +83,8 @@ public:
virtual ~MediaEngineSource() {}
virtual void Shutdown() = 0;
/* Populate the human readable name of this device in the nsAString */
virtual void GetName(nsAString&) = 0;
@ -245,6 +249,7 @@ public:
/* This call reserves but does not start the device. */
virtual nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
const MediaEnginePrefs &aPrefs) = 0;
protected:
explicit MediaEngineAudioSource(MediaEngineState aState)
: MediaEngineSource(aState) {}

Просмотреть файл

@ -61,6 +61,8 @@ public:
uint32_t GetBestFitnessDistance(
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets) override;
virtual void Shutdown() override {};
protected:
struct CapabilityCandidate {
explicit CapabilityCandidate(uint8_t index, uint32_t distance = 0)

Просмотреть файл

@ -36,6 +36,8 @@ class MediaEngineDefaultVideoSource : public nsITimerCallback,
public:
MediaEngineDefaultVideoSource();
virtual void Shutdown() override {};
virtual void GetName(nsAString&) override;
virtual void GetUUID(nsAString&) override;
@ -104,6 +106,8 @@ class MediaEngineDefaultAudioSource : public nsITimerCallback,
public:
MediaEngineDefaultAudioSource();
virtual void Shutdown() override {};
virtual void GetName(nsAString&) override;
virtual void GetUUID(nsAString&) override;
@ -158,15 +162,23 @@ public:
{}
virtual void EnumerateVideoDevices(dom::MediaSourceEnum,
nsTArray<nsRefPtr<MediaEngineVideoSource> >*);
nsTArray<nsRefPtr<MediaEngineVideoSource> >*) override;
virtual void EnumerateAudioDevices(dom::MediaSourceEnum,
nsTArray<nsRefPtr<MediaEngineAudioSource> >*);
nsTArray<nsRefPtr<MediaEngineAudioSource> >*) override;
virtual void Shutdown() override {
MutexAutoLock lock(mMutex);
mVSources.Clear();
mASources.Clear();
};
protected:
bool mHasFakeTracks;
private:
~MediaEngineDefault() {}
~MediaEngineDefault() {
Shutdown();
}
Mutex mMutex;
// protected with mMutex:

Просмотреть файл

@ -18,6 +18,7 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList
NS_DECL_NSITIMERCALLBACK
MediaEngineTabVideoSource();
virtual void Shutdown() override {};
virtual void GetName(nsAString_internal&) override;
virtual void GetUUID(nsAString_internal&) override;
virtual nsresult Allocate(const dom::MediaTrackConstraints &,

Просмотреть файл

@ -274,10 +274,9 @@ MediaEngineWebRTC::EnumerateVideoDevices(dom::MediaSourceEnum aMediaSource,
}
}
if (mHasTabVideoSource || dom::MediaSourceEnum::Browser == aMediaSource)
if (mHasTabVideoSource || dom::MediaSourceEnum::Browser == aMediaSource) {
aVSources->AppendElement(new MediaEngineTabVideoSource());
return;
}
#endif
}
@ -372,15 +371,43 @@ MediaEngineWebRTC::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource,
}
}
static PLDHashOperator
ClearVideoSource (const nsAString&, // unused
MediaEngineVideoSource* aData,
void *userArg)
{
if (aData) {
aData->Shutdown();
}
return PL_DHASH_NEXT;
}
static PLDHashOperator
ClearAudioSource (const nsAString&, // unused
MediaEngineWebRTCAudioSource* aData,
void *userArg)
{
if (aData) {
aData->Shutdown();
}
return PL_DHASH_NEXT;
}
void
MediaEngineWebRTC::Shutdown()
{
// This is likely paranoia
MutexAutoLock lock(mMutex);
// Clear callbacks before we go away since the engines may outlive us
LOG(("%s", __FUNCTION__));
// Shutdown all the sources, since we may have dangling references to the
// sources in nsDOMUserMediaStreams waiting for GC/CC
mVideoSources.EnumerateRead(ClearVideoSource, nullptr);
mAudioSources.EnumerateRead(ClearAudioSource, nullptr);
mVideoSources.Clear();
mAudioSources.Clear();
// Clear callbacks before we go away since the engines may outlive us
if (mVideoEngine) {
mVideoEngine->SetTraceCallback(nullptr);
webrtc::VideoEngine::Delete(mVideoEngine);

Просмотреть файл

@ -109,19 +109,20 @@ public:
void Refresh(int aIndex);
virtual void Shutdown() override;
protected:
~MediaEngineWebRTCVideoSource() { Shutdown(); }
private:
// Initialize the needed Video engine interfaces.
void Init();
void Shutdown();
// Engine variables.
webrtc::VideoEngine* mVideoEngine; // Weak reference, don't free.
webrtc::ViEBase* mViEBase;
webrtc::ViECapture* mViECapture;
webrtc::ViERender* mViERender;
ScopedCustomReleasePtr<webrtc::ViEBase> mViEBase;
ScopedCustomReleasePtr<webrtc::ViECapture> mViECapture;
ScopedCustomReleasePtr<webrtc::ViERender> mViERender;
int mMinFps; // Min rate we want to accept
dom::MediaSourceEnum mMediaSource; // source of media (camera | application | screen)
@ -195,12 +196,13 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS
virtual void Shutdown() override;
protected:
~MediaEngineWebRTCAudioSource() { Shutdown(); }
private:
void Init();
void Shutdown();
webrtc::VoiceEngine* mVoiceEngine;
ScopedCustomReleasePtr<webrtc::VoEBase> mVoEBase;
@ -239,12 +241,12 @@ public:
// Clients should ensure to clean-up sources video/audio sources
// before invoking Shutdown on this class.
void Shutdown();
void Shutdown() override;
virtual void EnumerateVideoDevices(dom::MediaSourceEnum,
nsTArray<nsRefPtr<MediaEngineVideoSource> >*);
nsTArray<nsRefPtr<MediaEngineVideoSource>>*) override;
virtual void EnumerateAudioDevices(dom::MediaSourceEnum,
nsTArray<nsRefPtr<MediaEngineAudioSource> >*);
nsTArray<nsRefPtr<MediaEngineAudioSource>>*) override;
private:
~MediaEngineWebRTC() {
Shutdown();

Просмотреть файл

@ -478,11 +478,12 @@ MediaEngineWebRTCAudioSource::Shutdown()
{
if (!mInitDone) {
// duplicate these here in case we failed during Init()
if (mChannel != -1) {
if (mChannel != -1 && mVoENetwork) {
mVoENetwork->DeRegisterExternalTransport(mChannel);
}
delete mNullTransport;
mNullTransport = nullptr;
return;
}
@ -514,6 +515,7 @@ MediaEngineWebRTCAudioSource::Shutdown()
}
delete mNullTransport;
mNullTransport = nullptr;
mVoEProcessing = nullptr;
mVoENetwork = nullptr;

Просмотреть файл

@ -266,7 +266,7 @@ MediaEngineWebRTCVideoSource::Deallocate()
// another thread anywhere else, b) ViEInputManager::DestroyCaptureDevice() grabs
// an exclusive object lock and deletes it in a critical section, so all in all
// this should be safe threadwise.
NS_DispatchToMainThread(WrapRunnable(mViECapture,
NS_DispatchToMainThread(WrapRunnable(mViECapture.get(),
&webrtc::ViECapture::ReleaseCaptureDevice,
mCaptureIndex),
NS_DISPATCH_SYNC);
@ -422,9 +422,10 @@ MediaEngineWebRTCVideoSource::Shutdown()
if (mState == kAllocated || mState == kStopped) {
Deallocate();
}
mViECapture->Release();
mViERender->Release();
mViEBase->Release();
mViECapture = nullptr;
mViERender = nullptr;
mViEBase = nullptr;
mState = kReleased;
mInitDone = false;
}

Просмотреть файл

@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PNecko;
include protocol PBackground;
include protocol PBlob;
include InputStreamParams;
@ -37,7 +38,7 @@ namespace net {
//-------------------------------------------------------------------
protocol PUDPSocket
{
manager PNecko;
manager PNecko or PBackground;
parent:
Bind(UDPAddressInfo addressInfo, bool addressReuse, bool loopback);

Просмотреть файл

@ -318,8 +318,10 @@ UDPSocket::Send(const StringOrBlobOrArrayBufferOrArrayBufferView& aData,
nsCString remoteAddress;
if (aRemoteAddress.WasPassed()) {
remoteAddress = NS_ConvertUTF16toUTF8(aRemoteAddress.Value());
UDPSOCKET_LOG(("%s: Send to %s", __FUNCTION__, remoteAddress.get()));
} else if (!mRemoteAddress.IsVoid()) {
remoteAddress = mRemoteAddress;
UDPSOCKET_LOG(("%s: Send to %s", __FUNCTION__, remoteAddress.get()));
} else {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return false;
@ -413,6 +415,7 @@ UDPSocket::InitLocal(const nsAString& aLocalAddress,
PRNetAddr prAddr;
PR_InitializeNetAddr(PR_IpAddrAny, aLocalPort, &prAddr);
PR_StringToNetAddr(NS_ConvertUTF16toUTF8(aLocalAddress).BeginReading(), &prAddr);
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, NS_ConvertUTF16toUTF8(aLocalAddress).get(), aLocalPort));
mozilla::net::NetAddr addr;
PRNetAddrToNetAddr(&prAddr, &addr);

Просмотреть файл

@ -18,6 +18,15 @@
struct JSContext;
#if defined(PR_LOGGING)
//
// set NSPR_LOG_MODULES=UDPSocket:5
//
extern PRLogModuleInfo *gUDPSocketLog;
#endif
#define UDPSOCKET_LOG(args) PR_LOG(gUDPSocketLog, PR_LOG_DEBUG, args)
#define UDPSOCKET_LOG_ENABLED() PR_LOG_TEST(gUDPSocketLog, PR_LOG_DEBUG)
namespace mozilla {
namespace dom {

Просмотреть файл

@ -9,9 +9,23 @@
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "nsIIPCBackgroundChildCreateCallback.h"
using mozilla::net::gNeckoChild;
#if defined(PR_LOGGING)
//
// set NSPR_LOG_MODULES=UDPSocket:5
//
extern PRLogModuleInfo *gUDPSocketLog;
#endif
#define UDPSOCKET_LOG(args) PR_LOG(gUDPSocketLog, PR_LOG_DEBUG, args)
#define UDPSOCKET_LOG_ENABLED() PR_LOG_TEST(gUDPSocketLog, PR_LOG_DEBUG)
namespace mozilla {
namespace dom {
@ -54,7 +68,8 @@ NS_IMETHODIMP_(MozExternalRefCountType) UDPSocketChild::Release(void)
}
UDPSocketChild::UDPSocketChild()
:mLocalPort(0)
:mBackgroundManager(nullptr)
,mLocalPort(0)
{
}
@ -62,8 +77,96 @@ UDPSocketChild::~UDPSocketChild()
{
}
class UDPSocketBackgroundChildCallback final :
public nsIIPCBackgroundChildCreateCallback
{
bool* mDone;
public:
explicit UDPSocketBackgroundChildCallback(bool* aDone)
: mDone(aDone)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(mDone);
MOZ_ASSERT(!*mDone);
}
NS_DECL_ISUPPORTS
private:
~UDPSocketBackgroundChildCallback()
{ }
virtual void
ActorCreated(PBackgroundChild* aActor) override
{
*mDone = true;
}
virtual void
ActorFailed() override
{
*mDone = true;
}
};
NS_IMPL_ISUPPORTS(UDPSocketBackgroundChildCallback, nsIIPCBackgroundChildCreateCallback)
nsresult
UDPSocketChild::CreatePBackgroundSpinUntilDone()
{
using mozilla::ipc::BackgroundChild;
// Spinning the event loop in MainThread would be dangerous
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!BackgroundChild::GetForCurrentThread());
bool done = false;
nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
new UDPSocketBackgroundChildCallback(&done);
if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(callback))) {
return NS_ERROR_FAILURE;
}
nsIThread* thread = NS_GetCurrentThread();
while (!done) {
if (NS_WARN_IF(!NS_ProcessNextEvent(thread, true /* aMayWait */))) {
return NS_ERROR_FAILURE;
}
}
if (NS_WARN_IF(!BackgroundChild::GetForCurrentThread())) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
// nsIUDPSocketChild Methods
NS_IMETHODIMP
UDPSocketChild::SetBackgroundSpinsEvents()
{
using mozilla::ipc::BackgroundChild;
PBackgroundChild* existingBackgroundChild =
BackgroundChild::GetForCurrentThread();
// If it's not spun up yet, block until it is, and retry
if (!existingBackgroundChild) {
nsresult rv = CreatePBackgroundSpinUntilDone();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
existingBackgroundChild =
BackgroundChild::GetForCurrentThread();
MOZ_ASSERT(existingBackgroundChild);
}
// By now PBackground is guaranteed to be/have-been up
mBackgroundManager = existingBackgroundChild;
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::Bind(nsIUDPSocketInternal* aSocket,
nsIPrincipal* aPrincipal,
@ -72,13 +175,22 @@ UDPSocketChild::Bind(nsIUDPSocketInternal* aSocket,
bool aAddressReuse,
bool aLoopback)
{
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort));
NS_ENSURE_ARG(aSocket);
mSocket = aSocket;
AddIPDLReference();
gNeckoChild->SendPUDPSocketConstructor(this, IPC::Principal(aPrincipal),
mFilterName);
if (mBackgroundManager) {
// If we want to support a passed-in principal here we'd need to
// convert it to a PrincipalInfo
MOZ_ASSERT(!aPrincipal);
mBackgroundManager->SendPUDPSocketConstructor(this, void_t(), mFilterName);
} else {
gNeckoChild->SendPUDPSocketConstructor(this, IPC::Principal(aPrincipal),
mFilterName);
}
SendBind(UDPAddressInfo(nsCString(aHost), aPort), aAddressReuse, aLoopback);
return NS_OK;
@ -99,6 +211,7 @@ UDPSocketChild::Send(const nsACString& aHost,
{
NS_ENSURE_ARG(aData);
UDPSOCKET_LOG(("%s: %s:%u - %u bytes", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort, aByteLength));
return SendDataInternal(UDPSocketAddr(UDPAddressInfo(nsCString(aHost), aPort)),
aData, aByteLength);
}
@ -114,6 +227,7 @@ UDPSocketChild::SendWithAddr(nsINetAddr* aAddr,
NetAddr addr;
aAddr->GetNetAddr(&addr);
UDPSOCKET_LOG(("%s: %u bytes", __FUNCTION__, aByteLength));
return SendDataInternal(UDPSocketAddr(addr), aData, aByteLength);
}
@ -125,6 +239,7 @@ UDPSocketChild::SendWithAddress(const NetAddr* aAddr,
NS_ENSURE_ARG(aAddr);
NS_ENSURE_ARG(aData);
UDPSOCKET_LOG(("%s: %u bytes", __FUNCTION__, aByteLength));
return SendDataInternal(UDPSocketAddr(*aAddr), aData, aByteLength);
}
@ -161,6 +276,7 @@ UDPSocketChild::SendBinaryStream(const nsACString& aHost,
MOZ_ASSERT(fds.IsEmpty());
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort));
SendOutgoingData(UDPData(stream), UDPSocketAddr(UDPAddressInfo(nsCString(aHost), aPort)));
return NS_OK;
@ -223,6 +339,7 @@ UDPSocketChild::RecvCallbackOpened(const UDPAddressInfo& aAddressInfo)
mLocalAddress = aAddressInfo.addr();
mLocalPort = aAddressInfo.port();
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, mLocalAddress.get(), mLocalPort));
nsresult rv = mSocket->CallListenerOpened();
mozilla::unused << NS_WARN_IF(NS_FAILED(rv));
@ -242,6 +359,8 @@ bool
UDPSocketChild::RecvCallbackReceivedData(const UDPAddressInfo& aAddressInfo,
InfallibleTArray<uint8_t>&& aData)
{
UDPSOCKET_LOG(("%s: %s:%u length %u", __FUNCTION__,
aAddressInfo.addr().get(), aAddressInfo.port(), aData.Length()));
nsresult rv = mSocket->CallListenerReceivedData(aAddressInfo.addr(), aAddressInfo.port(),
aData.Elements(), aData.Length());
mozilla::unused << NS_WARN_IF(NS_FAILED(rv));
@ -254,6 +373,7 @@ UDPSocketChild::RecvCallbackError(const nsCString& aMessage,
const nsCString& aFilename,
const uint32_t& aLineNumber)
{
UDPSOCKET_LOG(("%s: %s:%s:%u", __FUNCTION__, aMessage.get(), aFilename.get(), aLineNumber));
nsresult rv = mSocket->CallListenerError(aMessage, aFilename, aLineNumber);
mozilla::unused << NS_WARN_IF(NS_FAILED(rv));

Просмотреть файл

@ -42,6 +42,8 @@ public:
UDPSocketChild();
virtual ~UDPSocketChild();
nsresult CreatePBackgroundSpinUntilDone();
virtual bool RecvCallbackOpened(const UDPAddressInfo& aAddressInfo) override;
virtual bool RecvCallbackClosed() override;
virtual bool RecvCallbackReceivedData(const UDPAddressInfo& aAddressInfo,
@ -55,6 +57,7 @@ private:
const uint8_t* aData,
const uint32_t aByteLength);
mozilla::ipc::PBackgroundChild* mBackgroundManager;
uint16_t mLocalPort;
nsCString mLocalAddress;
nsCString mFilterName;

Просмотреть файл

@ -20,14 +20,34 @@
#include "mozilla/dom/TabParent.h"
#include "nsIPermissionManager.h"
#include "nsIScriptSecurityManager.h"
#include "mozilla/ipc/PBackgroundParent.h"
#if defined(PR_LOGGING)
//
// set NSPR_LOG_MODULES=UDPSocket:5
//
extern PRLogModuleInfo *gUDPSocketLog;
#endif
#define UDPSOCKET_LOG(args) PR_LOG(gUDPSocketLog, PR_LOG_DEBUG, args)
#define UDPSOCKET_LOG_ENABLED() PR_LOG_TEST(gUDPSocketLog, PR_LOG_DEBUG)
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS(UDPSocketParent, nsIUDPSocketListener)
UDPSocketParent::UDPSocketParent()
: mIPCOpen(true)
UDPSocketParent::UDPSocketParent(PBackgroundParent* aManager)
: mBackgroundManager(aManager)
, mNeckoManager(nullptr)
, mIPCOpen(true)
{
mObserver = new mozilla::net::OfflineObserver(this);
}
UDPSocketParent::UDPSocketParent(PNeckoParent* aManager)
: mBackgroundManager(nullptr)
, mNeckoManager(aManager)
, mIPCOpen(true)
{
mObserver = new mozilla::net::OfflineObserver(this);
}
@ -78,12 +98,22 @@ bool
UDPSocketParent::Init(const IPC::Principal& aPrincipal,
const nsACString& aFilter)
{
MOZ_ASSERT_IF(mBackgroundManager, !aPrincipal);
// will be used once we move all UDPSocket to PBackground, or
// if we add in Principal checking for mtransport
unused << mBackgroundManager;
mPrincipal = aPrincipal;
if (net::UsingNeckoIPCSecurity() &&
mPrincipal &&
!ContentParent::IgnoreIPCPrincipal()) {
if (!AssertAppPrincipal(Manager()->Manager(), mPrincipal)) {
return false;
if (mNeckoManager) {
if (!AssertAppPrincipal(mNeckoManager->Manager(), mPrincipal)) {
return false;
}
} else {
// PBackground is (for now) using a STUN filter for verification
// it's not being used for DoS
}
nsCOMPtr<nsIPermissionManager> permMgr =
@ -121,7 +151,7 @@ UDPSocketParent::Init(const IPC::Principal& aPrincipal,
}
// We don't have browser actors in xpcshell, and hence can't run automated
// tests without this loophole.
if (net::UsingNeckoIPCSecurity() && !mFilter &&
if (net::UsingNeckoIPCSecurity() && !mFilter &&
(!mPrincipal || ContentParent::IgnoreIPCPrincipal())) {
return false;
}
@ -134,6 +164,8 @@ bool
UDPSocketParent::RecvBind(const UDPAddressInfo& aAddressInfo,
const bool& aAddressReuse, const bool& aLoopback)
{
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, aAddressInfo.addr().get(), aAddressInfo.port()));
if (NS_FAILED(BindInternal(aAddressInfo.addr(), aAddressInfo.port(), aAddressReuse, aLoopback))) {
FireInternalError(__LINE__);
return true;
@ -154,6 +186,7 @@ UDPSocketParent::RecvBind(const UDPAddressInfo& aAddressInfo,
return true;
}
UDPSOCKET_LOG(("%s: SendCallbackOpened: %s:%u", __FUNCTION__, addr.get(), port));
mozilla::unused << SendCallbackOpened(UDPAddressInfo(addr, port));
return true;
@ -165,6 +198,8 @@ UDPSocketParent::BindInternal(const nsCString& aHost, const uint16_t& aPort,
{
nsresult rv;
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, nsCString(aHost).get(), aPort));
nsCOMPtr<nsIUDPSocket> sock =
do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv);
@ -398,6 +433,7 @@ UDPSocketParent::OnPacketReceived(nsIUDPSocket* aSocket, nsIUDPMessage* aMessage
const char* buffer = data.get();
uint32_t len = data.Length();
UDPSOCKET_LOG(("%s: %s:%u, length %u", __FUNCTION__, ip.get(), port, len));
if (mFilter) {
bool allowed;
@ -409,6 +445,9 @@ UDPSocketParent::OnPacketReceived(nsIUDPSocket* aSocket, nsIUDPMessage* aMessage
&allowed);
// Receiving unallowed data, drop.
if (NS_WARN_IF(NS_FAILED(rv)) || !allowed) {
if (!allowed) {
UDPSOCKET_LOG(("%s: not allowed", __FUNCTION__));
}
return NS_OK;
}
}

Просмотреть файл

@ -15,6 +15,10 @@
#include "mozilla/dom/PermissionMessageUtils.h"
namespace mozilla {
namespace net {
class PNeckoParent;
}
namespace dom {
class UDPSocketParent : public mozilla::net::PUDPSocketParent
@ -25,7 +29,8 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIUDPSOCKETLISTENER
UDPSocketParent();
explicit UDPSocketParent(PBackgroundParent* aManager);
explicit UDPSocketParent(PNeckoParent* aManager);
bool Init(const IPC::Principal& aPrincipal, const nsACString& aFilter);
@ -54,6 +59,10 @@ private:
void FireInternalError(uint32_t aLineNo);
// One of these will be null and the other non-null.
PBackgroundParent* mBackgroundManager;
PNeckoParent* mNeckoManager;
bool mIPCOpen;
nsCOMPtr<nsIUDPSocket> mSocket;
nsCOMPtr<nsIUDPSocketFilter> mFilter;

Просмотреть файл

@ -19,13 +19,16 @@ union NetAddr;
native NetAddr(mozilla::net::NetAddr);
[ptr] native NetAddrPtr(mozilla::net::NetAddr);
[scriptable, uuid(dd636fc5-05a0-401c-832f-2c07f3477c60)]
[scriptable, uuid(481f15ce-224a-40b6-9927-7effbc326776)]
interface nsIUDPSocketChild : nsISupports
{
readonly attribute unsigned short localPort;
readonly attribute AUTF8String localAddress;
attribute AUTF8String filterName;
// Allow hosting this over PBackground instead of PNecko
[noscript] void setBackgroundSpinsEvents();
// Tell the chrome process to bind the UDP socket to a given local host and port
void bind(in nsIUDPSocketInternal socket, in nsIPrincipal principal,
in AUTF8String host, in unsigned short port,

Просмотреть файл

@ -1954,7 +1954,7 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
return NPERR_GENERIC_ERROR;
#endif
#if defined(XP_WIN) || (MOZ_WIDGET_GTK == 2) || defined(MOZ_WIDGET_QT)
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
case NPNVnetscapeWindow: {
if (!npp || !npp->ndata)
return NPERR_INVALID_INSTANCE_ERROR;

Просмотреть файл

@ -481,7 +481,8 @@ PluginModuleChromeParent::LoadModule(const char* aFilePath, uint32_t aPluginId,
}
#endif
nsAutoPtr<PluginModuleChromeParent> parent(new PluginModuleChromeParent(aFilePath, aPluginId));
nsAutoPtr<PluginModuleChromeParent> parent(new PluginModuleChromeParent(aFilePath, aPluginId,
sandboxLevel));
UniquePtr<LaunchCompleteTask> onLaunchedRunnable(new LaunchedTask(parent));
parent->mSubprocess->SetCallRunnableImmediately(!parent->mIsStartingAsync);
TimeStamp launchStart = TimeStamp::Now();
@ -564,9 +565,11 @@ PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded)
#endif
#endif
#ifdef XP_WIN
#if defined(XP_WIN) && defined(_X86_)
// Protected mode only applies to Windows and only to x86.
if (!mIsBlocklisted && mIsFlashPlugin &&
Preferences::GetBool("dom.ipc.plugins.flash.disable-protected-mode", false)) {
(Preferences::GetBool("dom.ipc.plugins.flash.disable-protected-mode", false) ||
mSandboxLevel >= 2)) {
SendDisableFlashProtectedMode();
}
#endif
@ -662,7 +665,9 @@ PluginModuleContentParent::~PluginModuleContentParent()
bool PluginModuleChromeParent::sInstantiated = false;
PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId)
PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath,
uint32_t aPluginId,
int32_t aSandboxLevel)
: PluginModuleParent(true)
, mSubprocess(new PluginProcessParent(aFilePath))
, mPluginId(aPluginId)
@ -674,6 +679,7 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32
, mHangUIParent(nullptr)
, mHangUIEnabled(true)
, mIsTimerReset(true)
, mSandboxLevel(aSandboxLevel)
#ifdef MOZ_CRASHREPORTER
, mCrashReporterMutex("PluginModuleChromeParent::mCrashReporterMutex")
, mCrashReporter(nullptr)

Просмотреть файл

@ -443,7 +443,8 @@ private:
virtual void ActorDestroy(ActorDestroyReason why) override;
// aFilePath is UTF8, not native!
explicit PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId);
explicit PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId,
int32_t aSandboxLevel);
CrashReporterParent* CrashReporter();
@ -483,6 +484,7 @@ private:
PluginHangUIParent *mHangUIParent;
bool mHangUIEnabled;
bool mIsTimerReset;
int32_t mSandboxLevel;
#ifdef MOZ_CRASHREPORTER
/**
* This mutex protects the crash reporter when the Plugin Hang UI event

Просмотреть файл

@ -76,7 +76,7 @@ AddSandboxAllowedFiles(int32_t aSandboxLevel,
vector<std::wstring>& aAllowedFilesRead,
vector<std::wstring>& aAllowedFilesReadWrite)
{
if (aSandboxLevel < 3) {
if (aSandboxLevel < 2) {
return;
}
@ -87,16 +87,26 @@ AddSandboxAllowedFiles(int32_t aSandboxLevel,
return;
}
AddSandboxAllowedFile(aAllowedFilesRead, dirSvc, NS_WIN_HOME_DIR);
AddSandboxAllowedFile(aAllowedFilesRead, dirSvc, NS_WIN_HOME_DIR,
NS_LITERAL_STRING("\\*"));
// Higher than level 2 currently removes the users own rights.
if (aSandboxLevel > 2) {
AddSandboxAllowedFile(aAllowedFilesRead, dirSvc, NS_WIN_HOME_DIR);
AddSandboxAllowedFile(aAllowedFilesRead, dirSvc, NS_WIN_HOME_DIR,
NS_LITERAL_STRING("\\*"));
}
// Level 2 and above is now using low integrity, so we need to give write
// access to the Flash directories.
AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_APPDATA_DIR,
NS_LITERAL_STRING("\\Macromedia\\Flash Player\\*"));
AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_APPDATA_DIR,
NS_LITERAL_STRING("\\Adobe\\Flash Player\\*"));
#if defined(_X86_)
// Write access to the Temp directory should only be needed for 32-bit as
// it is used to turn off protected mode, which only applies to x86.
AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_OS_TEMP_DIR,
NS_LITERAL_STRING("\\*"));
#endif
}
#endif

Просмотреть файл

@ -0,0 +1,32 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
enum CaretChangedReason {
"visibilitychange",
"updateposition",
"longpressonemptycontent",
"taponcaret",
"presscaret",
"releasecaret"
};
dictionary CaretStateChangedEventInit : EventInit {
boolean collapsed = true;
DOMRectReadOnly? boundingClientRect = null;
CaretChangedReason reason = "visibilitychange";
boolean caretVisible = false;
boolean selectionVisible = false;
};
[Constructor(DOMString type, optional CaretStateChangedEventInit eventInit),
ChromeOnly]
interface CaretStateChangedEvent : Event {
readonly attribute boolean collapsed;
readonly attribute DOMRectReadOnly? boundingClientRect;
readonly attribute CaretChangedReason reason;
readonly attribute boolean caretVisible;
readonly attribute boolean selectionVisible;
};

Просмотреть файл

@ -8,7 +8,6 @@
*/
typedef long long GLint64; // Should this be int64?
typedef unsigned long long GLuint64; // Should this be uint64?
[Pref="webgl.enable-prototype-webgl2"]
interface WebGLQuery {

Просмотреть файл

@ -28,6 +28,7 @@ typedef long long GLsizeiptr;
typedef octet GLubyte; /* 'octet' should be an unsigned 8 bit type. */
typedef unsigned short GLushort;
typedef unsigned long GLuint;
typedef unsigned long long GLuint64;
typedef unrestricted float GLfloat;
typedef unrestricted float GLclampf;
@ -975,3 +976,29 @@ interface WebGLExtensionBlendMinMax {
const GLenum MIN_EXT = 0x8007;
const GLenum MAX_EXT = 0x8008;
};
// FIXME: Spec interface name is WebGLTimerQueryEXT.
[NoInterfaceObject]
interface WebGLTimerQuery {
};
// FIXME: Spec interface name is EXT_disjoint_timer_query.
[NoInterfaceObject]
interface WebGLExtensionDisjointTimerQuery {
const GLenum QUERY_COUNTER_BITS_EXT = 0x8864;
const GLenum CURRENT_QUERY_EXT = 0x8865;
const GLenum QUERY_RESULT_EXT = 0x8866;
const GLenum QUERY_RESULT_AVAILABLE_EXT = 0x8867;
const GLenum TIME_ELAPSED_EXT = 0x88BF;
const GLenum TIMESTAMP_EXT = 0x8E28;
const GLenum GPU_DISJOINT_EXT = 0x8FBB;
WebGLTimerQuery? createQueryEXT();
void deleteQueryEXT(WebGLTimerQuery? query);
[WebGLHandlesContextLoss] boolean isQueryEXT(WebGLTimerQuery? query);
void beginQueryEXT(GLenum target, WebGLTimerQuery? query);
void endQueryEXT(GLenum target);
void queryCounterEXT(WebGLTimerQuery? query, GLenum target);
any getQueryEXT(GLenum target, GLenum pname);
any getQueryObjectEXT(WebGLTimerQuery? query, GLenum pname);
};

Просмотреть файл

@ -727,6 +727,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
'CameraConfigurationEvent.webidl',
'CameraFacesDetectedEvent.webidl',
'CameraStateChangeEvent.webidl',
'CaretStateChangedEvent.webidl',
'CFStateChangeEvent.webidl',
'CloseEvent.webidl',
'CSSFontFaceLoadEvent.webidl',

Просмотреть файл

@ -393,6 +393,8 @@ nsXBLProtoImplField::InstallField(JS::Handle<JSObject*> aBoundNode,
return NS_OK;
}
nsAutoMicroTask mt;
nsAutoCString uriSpec;
aBindingDocURI->GetSpec(uriSpec);

Просмотреть файл

@ -293,6 +293,8 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement, JSAddonId* aAd
return NS_OK;
}
nsAutoMicroTask mt;
// We are going to run script via JS::Call, so we need a script entry point,
// but as this is XBL related it does not appear in the HTML spec.
dom::AutoEntryScript aes(global, "XBL <constructor>/<destructor> invocation");

Просмотреть файл

@ -3537,7 +3537,9 @@ XULDocument::ExecuteScript(nsXULPrototypeScript *aScript)
JS::HandleScript scriptObject = aScript->GetScriptObject();
NS_ENSURE_TRUE(scriptObject, NS_ERROR_UNEXPECTED);
// Execute the precompiled script with the given version.
// Execute the precompiled script with the given version
nsAutoMicroTask mt;
// We're about to run script via JS::CloneAndExecuteScript, so we need an
// AutoEntryScript. This is Gecko specific and not in any spec.
AutoEntryScript aes(mScriptGlobalObject, "precompiled XUL <script> element");

Просмотреть файл

@ -526,10 +526,69 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
AutoDWriteGlyphRun autoRun;
DWriteGlyphRunFromGlyphs(aBuffer, font, &autoRun);
bool needsRepushedLayers = false;
if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE && mFormat != SurfaceFormat::B8G8R8X8) {
D2D1_RECT_F rect;
bool isAligned;
needsRepushedLayers = mPushedClips.size() && !GetDeviceSpaceClipRect(rect, isAligned);
// If we have a complex clip in our stack and we have a transparent
// background, and subpixel AA is permitted, we need to repush our layer
// stack limited by the glyph run bounds initializing our layers for
// subpixel AA.
if (needsRepushedLayers) {
mDC->GetGlyphRunWorldBounds(D2D1::Point2F(), &autoRun,
DWRITE_MEASURING_MODE_NATURAL, &rect);
rect.left = std::floor(rect.left);
rect.right = std::ceil(rect.right);
rect.top = std::floor(rect.top);
rect.bottom = std::ceil(rect.bottom);
PopAllClips();
if (!mTransform.IsRectilinear()) {
// We must limit the pixels we touch to the -user space- bounds of
// the glyphs being drawn. In order not to get transparent pixels
// copied up in our pushed layer stack.
D2D1_RECT_F userRect;
mDC->SetTransform(D2D1::IdentityMatrix());
mDC->GetGlyphRunWorldBounds(D2D1::Point2F(), &autoRun,
DWRITE_MEASURING_MODE_NATURAL, &userRect);
RefPtr<ID2D1PathGeometry> path;
D2DFactory()->CreatePathGeometry(byRef(path));
RefPtr<ID2D1GeometrySink> sink;
path->Open(byRef(sink));
sink->BeginFigure(D2D1::Point2F(userRect.left, userRect.top), D2D1_FIGURE_BEGIN_FILLED);
sink->AddLine(D2D1::Point2F(userRect.right, userRect.top));
sink->AddLine(D2D1::Point2F(userRect.right, userRect.bottom));
sink->AddLine(D2D1::Point2F(userRect.left, userRect.bottom));
sink->EndFigure(D2D1_FIGURE_END_CLOSED);
sink->Close();
mDC->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), path, D2D1_ANTIALIAS_MODE_ALIASED,
D2DMatrix(mTransform), 1.0f, nullptr,
D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND |
D2D1_LAYER_OPTIONS1_IGNORE_ALPHA), nullptr);
}
PushClipsToDC(mDC, true, rect);
mDC->SetTransform(D2DMatrix(mTransform));
}
}
if (brush) {
mDC->DrawGlyphRun(D2D1::Point2F(), &autoRun, brush);
}
if (needsRepushedLayers) {
PopClipsFromDC(mDC);
if (!mTransform.IsRectilinear()) {
mDC->PopLayer();
}
}
FinalizeDrawing(aOptions.mCompositionOp, aPattern);
}
@ -1261,7 +1320,7 @@ DrawTargetD2D1::PushAllClips()
}
void
DrawTargetD2D1::PushClipsToDC(ID2D1DeviceContext *aDC)
DrawTargetD2D1::PushClipsToDC(ID2D1DeviceContext *aDC, bool aForceIgnoreAlpha, const D2D1_RECT_F& aMaxRect)
{
mDC->SetTransform(D2D1::IdentityMatrix());
mTransformDirty = true;
@ -1269,7 +1328,7 @@ DrawTargetD2D1::PushClipsToDC(ID2D1DeviceContext *aDC)
for (std::vector<PushedClip>::iterator iter = mPushedClips.begin();
iter != mPushedClips.end(); iter++) {
if (iter->mPath) {
PushD2DLayer(aDC, iter->mPath->mGeometry, iter->mTransform);
PushD2DLayer(aDC, iter->mPath->mGeometry, iter->mTransform, aForceIgnoreAlpha, aMaxRect);
} else {
mDC->PushAxisAlignedClip(iter->mBounds, iter->mIsPixelAligned ? D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
}
@ -1493,15 +1552,16 @@ DrawTargetD2D1::OptimizeSourceSurface(SourceSurface* aSurface) const
}
void
DrawTargetD2D1::PushD2DLayer(ID2D1DeviceContext *aDC, ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform)
DrawTargetD2D1::PushD2DLayer(ID2D1DeviceContext *aDC, ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform,
bool aForceIgnoreAlpha, const D2D1_RECT_F& aMaxRect)
{
D2D1_LAYER_OPTIONS1 options = D2D1_LAYER_OPTIONS1_NONE;
if (aDC->GetPixelFormat().alphaMode == D2D1_ALPHA_MODE_IGNORE) {
if (aDC->GetPixelFormat().alphaMode == D2D1_ALPHA_MODE_IGNORE || aForceIgnoreAlpha) {
options = D2D1_LAYER_OPTIONS1_IGNORE_ALPHA | D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND;
}
mDC->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), aGeometry,
mDC->PushLayer(D2D1::LayerParameters1(aMaxRect, aGeometry,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, aTransform,
1.0, nullptr, options), nullptr);
}

Просмотреть файл

@ -179,14 +179,15 @@ private:
void PopAllClips();
void PushAllClips();
void PushClipsToDC(ID2D1DeviceContext *aDC);
void PushClipsToDC(ID2D1DeviceContext *aDC, bool aForceIgnoreAlpha = false, const D2D1_RECT_F& aMaxRect = D2D1::InfiniteRect());
void PopClipsFromDC(ID2D1DeviceContext *aDC);
TemporaryRef<ID2D1Brush> CreateTransparentBlackBrush();
TemporaryRef<ID2D1SolidColorBrush> GetSolidColorBrush(const D2D_COLOR_F& aColor);
TemporaryRef<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f);
void PushD2DLayer(ID2D1DeviceContext *aDC, ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform);
void PushD2DLayer(ID2D1DeviceContext *aDC, ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform,
bool aForceIgnoreAlpha = false, const D2D1_RECT_F& aLayerRect = D2D1::InfiniteRect());
IntSize mSize;

Просмотреть файл

@ -70,6 +70,7 @@ static const char *sExtensionNames[] = {
"GL_ANGLE_instanced_arrays",
"GL_ANGLE_texture_compression_dxt3",
"GL_ANGLE_texture_compression_dxt5",
"GL_ANGLE_timer_query",
"GL_APPLE_client_storage",
"GL_APPLE_texture_range",
"GL_APPLE_vertex_array_object",
@ -97,6 +98,7 @@ static const char *sExtensionNames[] = {
"GL_ARB_texture_rectangle",
"GL_ARB_texture_storage",
"GL_ARB_texture_swizzle",
"GL_ARB_timer_query",
"GL_ARB_transform_feedback2",
"GL_ARB_uniform_buffer_object",
"GL_ARB_vertex_array_object",
@ -105,6 +107,7 @@ static const char *sExtensionNames[] = {
"GL_EXT_color_buffer_float",
"GL_EXT_color_buffer_half_float",
"GL_EXT_copy_texture",
"GL_EXT_disjoint_timer_query",
"GL_EXT_draw_buffers",
"GL_EXT_draw_buffers2",
"GL_EXT_draw_instanced",
@ -129,6 +132,7 @@ static const char *sExtensionNames[] = {
"GL_EXT_texture_format_BGRA8888",
"GL_EXT_texture_sRGB",
"GL_EXT_texture_storage",
"GL_EXT_timer_query",
"GL_EXT_transform_feedback",
"GL_EXT_unpack_subimage",
"GL_IMG_read_format",
@ -1043,6 +1047,26 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
}
}
if (IsSupported(GLFeature::query_counter)) {
SymLoadStruct coreSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fQueryCounter, { "QueryCounter", nullptr } },
END_SYMBOLS
};
SymLoadStruct extSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fQueryCounter, { "QueryCounterEXT", "QueryCounterANGLE", nullptr } },
END_SYMBOLS
};
bool useCore = IsFeatureProvidedByCoreSymbols(GLFeature::query_counter);
if (!LoadSymbols(useCore ? coreSymbols : extSymbols, trygl, prefix)) {
NS_ERROR("GL supports query counters without supplying its functions.");
MarkUnsupported(GLFeature::query_counter);
ClearSymbols(coreSymbols);
}
}
if (IsSupported(GLFeature::query_objects)) {
SymLoadStruct coreSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQuery", nullptr } },
@ -1056,13 +1080,13 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
};
SymLoadStruct extSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQueryEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueriesEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueriesEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQueryEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryivEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuivEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQueryEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQueryEXT", "BeginQueryANGLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueriesEXT", "GenQueriesANGLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueriesEXT", "DeleteQueriesANGLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQueryEXT", "EndQueryANGLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryivEXT", "GetQueryivANGLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuivEXT", "GetQueryObjectuivANGLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQueryEXT", "IsQueryANGLE", nullptr } },
END_SYMBOLS
};
@ -1072,6 +1096,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
NS_ERROR("GL supports query objects without supplying its functions.");
MarkUnsupported(GLFeature::query_objects);
MarkUnsupported(GLFeature::get_query_object_i64v);
MarkUnsupported(GLFeature::get_query_object_iv);
MarkUnsupported(GLFeature::occlusion_query);
MarkUnsupported(GLFeature::occlusion_query_boolean);
@ -1080,6 +1105,29 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
}
}
if (IsSupported(GLFeature::get_query_object_i64v)) {
SymLoadStruct coreSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, { "GetQueryObjecti64v", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, { "GetQueryObjectui64v", nullptr } },
END_SYMBOLS
};
SymLoadStruct extSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, { "GetQueryObjecti64vEXT", "GetQueryObjecti64vANGLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, { "GetQueryObjectui64vEXT", "GetQueryObjectui64vANGLE", nullptr } },
END_SYMBOLS
};
bool useCore = IsFeatureProvidedByCoreSymbols(GLFeature::get_query_object_i64v);
if (!LoadSymbols(useCore ? coreSymbols : extSymbols, trygl, prefix)) {
NS_ERROR("GL supports 64 bit query object getters without supplying its functions.");
MarkUnsupported(GLFeature::get_query_object_i64v);
MarkUnsupported(GLFeature::query_counter);
ClearSymbols(coreSymbols);
}
}
if (IsSupported(GLFeature::get_query_object_iv)) {
SymLoadStruct coreSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectiv", nullptr } },
@ -1087,7 +1135,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
};
SymLoadStruct extSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectivEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectivEXT", "GetQueryObjectivANGLE", nullptr } },
END_SYMBOLS
};

Просмотреть файл

@ -99,6 +99,7 @@ enum class GLFeature {
framebuffer_object,
get_integer_indexed,
get_integer64_indexed,
get_query_object_i64v,
get_query_object_iv,
get_string_indexed,
gpu_shader4,
@ -110,7 +111,9 @@ enum class GLFeature {
occlusion_query_boolean,
occlusion_query2,
packed_depth_stencil,
query_counter,
query_objects,
query_time_elapsed,
read_buffer,
renderbuffer_color_float,
renderbuffer_color_half_float,
@ -364,6 +367,7 @@ public:
ANGLE_instanced_arrays,
ANGLE_texture_compression_dxt3,
ANGLE_texture_compression_dxt5,
ANGLE_timer_query,
APPLE_client_storage,
APPLE_texture_range,
APPLE_vertex_array_object,
@ -391,6 +395,7 @@ public:
ARB_texture_rectangle,
ARB_texture_storage,
ARB_texture_swizzle,
ARB_timer_query,
ARB_transform_feedback2,
ARB_uniform_buffer_object,
ARB_vertex_array_object,
@ -399,6 +404,7 @@ public:
EXT_color_buffer_float,
EXT_color_buffer_half_float,
EXT_copy_texture,
EXT_disjoint_timer_query,
EXT_draw_buffers,
EXT_draw_buffers2,
EXT_draw_instanced,
@ -423,6 +429,7 @@ public:
EXT_texture_format_BGRA8888,
EXT_texture_sRGB,
EXT_texture_storage,
EXT_timer_query,
EXT_transform_feedback,
EXT_unpack_subimage,
IMG_read_format,
@ -2617,6 +2624,22 @@ public:
AFTER_GL_CALL;
}
// -----------------------------------------------------------------------------
// Package XXX_query_counter
/**
* XXX_query_counter:
* - depends on XXX_query_objects
* - provide all followed entry points
* - provide GL_TIMESTAMP
*/
public:
void fQueryCounter(GLuint id, GLenum target) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fQueryCounter);
mSymbols.fQueryCounter(id, target);
AFTER_GL_CALL;
}
// -----------------------------------------------------------------------------
// Package XXX_query_objects
@ -2671,6 +2694,28 @@ public:
return retval;
}
// -----------------------------------------------------------------------------
// Package XXX_get_query_object_i64v
/**
* XXX_get_query_object_i64v:
* - depends on XXX_query_objects
* - provide the followed entry point
*/
public:
void fGetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fGetQueryObjecti64v);
mSymbols.fGetQueryObjecti64v(id, pname, params);
AFTER_GL_CALL;
}
void fGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fGetQueryObjectui64v);
mSymbols.fGetQueryObjectui64v(id, pname, params);
AFTER_GL_CALL;
}
// -----------------------------------------------------------------------------
// Package XXX_get_query_object_iv

Просмотреть файл

@ -260,6 +260,18 @@ static const FeatureInfo sFeatureInfoArr[] = {
GLContext::Extensions_End
}
},
{
"get_query_object_i64v",
GLVersion::GL3_3,
GLESVersion::NONE,
GLContext::ARB_timer_query,
{
GLContext::ANGLE_timer_query,
GLContext::EXT_disjoint_timer_query,
GLContext::EXT_timer_query,
GLContext::Extensions_End
}
},
{
"get_query_object_iv",
GLVersion::GL2,
@ -392,21 +404,48 @@ static const FeatureInfo sFeatureInfoArr[] = {
GLContext::Extensions_End
}
},
{
"query_counter",
GLVersion::GL3_3,
GLESVersion::NONE,
GLContext::ARB_timer_query,
{
GLContext::ANGLE_timer_query,
GLContext::EXT_disjoint_timer_query,
// EXT_timer_query does NOT support GL_TIMESTAMP retrieval with
// QueryCounter.
GLContext::Extensions_End
}
},
{
"query_objects",
GLVersion::GL2,
GLESVersion::ES3,
GLContext::Extension_None,
{
GLContext::ANGLE_timer_query,
GLContext::EXT_disjoint_timer_query,
GLContext::EXT_occlusion_query_boolean,
GLContext::Extensions_End
}
/*
* XXX_query_objects only provide entry points commonly supported by
* ARB_occlusion_query (added in OpenGL 2.0) and EXT_occlusion_query_boolean
* (added in OpenGL ES 3.0)
* ARB_occlusion_query (added in OpenGL 2.0), EXT_occlusion_query_boolean
* (added in OpenGL ES 3.0), and ARB_timer_query (added in OpenGL 3.3)
*/
},
{
"query_time_elapsed",
GLVersion::GL3_3,
GLESVersion::NONE,
GLContext::ARB_timer_query,
{
GLContext::ANGLE_timer_query,
GLContext::EXT_disjoint_timer_query,
GLContext::EXT_timer_query,
GLContext::Extensions_End
}
},
{
"read_buffer",
GLVersion::GL2,

Просмотреть файл

@ -145,6 +145,12 @@ struct GLContextSymbols
PFNGLGETQUERYOBJECTIVPROC fGetQueryObjectiv;
typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params);
PFNGLGETQUERYOBJECTUIVPROC fGetQueryObjectuiv;
typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64* params);
PFNGLGETQUERYOBJECTI64VPROC fGetQueryObjecti64v;
typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64* params);
PFNGLGETQUERYOBJECTUI64VPROC fGetQueryObjectui64v;
typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target);
PFNGLQUERYCOUNTERPROC fQueryCounter;
typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
PFNGLTEXPARAMETERIPROC fTexParameteri;
typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint* param);

Просмотреть файл

@ -175,15 +175,6 @@ public:
return scrollableRect;
}
// Return the scale factor needed to fit the viewport
// into its composition bounds.
CSSToParentLayerScale CalculateIntrinsicScale() const
{
return CSSToParentLayerScale(
std::max(mCompositionBounds.width / mViewport.width,
mCompositionBounds.height / mViewport.height));
}
CSSSize CalculateCompositedSizeInCssPixels() const
{
return mCompositionBounds.Size() / GetZoom();

Просмотреть файл

@ -574,12 +574,26 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId);
break;
} case SCROLLWHEEL_INPUT: {
FlushRepaintsToClearScreenToGeckoTransform();
ScrollWheelInput& wheelInput = aEvent.AsScrollWheelInput();
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(wheelInput.mOrigin,
&hitResult);
if (apzc) {
MOZ_ASSERT(hitResult == HitLayer || hitResult == HitDispatchToContentRegion);
// For wheel events, the call to ReceiveInputEvent below may result in
// scrolling, which changes the async transform. However, the event we
// want to pass to gecko should be the pre-scroll event coordinates,
// transformed into the gecko space. (pre-scroll because the mouse
// cursor is stationary during wheel scrolling, unlike touchmove
// events). Also, since we just flushed the pending repaints the
// transform to gecko space is a no-op so we can just skip it.
MOZ_ASSERT(
(GetScreenToApzcTransform(apzc) * GetApzcToGeckoTransform(apzc))
.NudgeToIntegersFixedEpsilon()
.IsIdentity());
result = mInputQueue->ReceiveInputEvent(
apzc,
/* aTargetConfirmed = */ hitResult == HitLayer,
@ -587,10 +601,6 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
// Update the out-parameters so they are what the caller expects.
apzc->GetGuid(aOutTargetGuid);
Matrix4x4 transformToGecko = GetScreenToApzcTransform(apzc)
* GetApzcToGeckoTransform(apzc);
wheelInput.mOrigin =
TransformTo<ScreenPixel>(transformToGecko, wheelInput.mOrigin);
}
break;
} case PANGESTURE_INPUT: {
@ -668,17 +678,7 @@ APZCTreeManager::GetTouchInputBlockAPZC(const MultiTouchInput& aEvent,
return apzc.forget();
}
{ // In this block we flush repaint requests for the entire APZ tree. We need to do this
// at the start of an input block for a number of reasons. One of the reasons is so that
// after we untransform the event into gecko space, it doesn't end up under something
// else. Another reason is that if we hit-test this event and end up on a layer's
// dispatch-to-content region we cannot be sure we actually got the correct layer. We
// have to fall back to the gecko hit-test to handle this case, but we can't untransform
// the event we send to gecko because we don't know the layer to untransform with
// respect to.
MonitorAutoLock lock(mTreeLock);
FlushRepaintsRecursively(mRootNode);
}
FlushRepaintsToClearScreenToGeckoTransform();
apzc = GetTargetAPZC(aEvent.mTouches[0].mScreenPoint, aOutHitResult);
for (size_t i = 1; i < aEvent.mTouches.Length(); i++) {
@ -770,6 +770,12 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput,
Matrix4x4 transformToApzc = GetScreenToApzcTransform(mApzcForInputBlock);
Matrix4x4 transformToGecko = GetApzcToGeckoTransform(mApzcForInputBlock);
Matrix4x4 outTransform = transformToApzc * transformToGecko;
if (aInput.mType == MultiTouchInput::MULTITOUCH_START) {
// For touch-start events we should have flushed all pending repaints
// above as part of the GetTouchInputBlockAPZC call, and so we expect
// the apzc-to-gecko transform to be empty.
MOZ_ASSERT(outTransform.NudgeToIntegersFixedEpsilon().IsIdentity());
}
for (size_t i = 0; i < aInput.mTouches.Length(); i++) {
SingleTouchData& touchData = aInput.mTouches[i];
touchData.mScreenPoint = TransformTo<ScreenPixel>(
@ -1057,6 +1063,32 @@ APZCTreeManager::UpdateZoomConstraintsRecursively(HitTestingTreeNode* aNode,
}
}
void
APZCTreeManager::FlushRepaintsToClearScreenToGeckoTransform()
{
// As the name implies, we flush repaint requests for the entire APZ tree in
// order to clear the screen-to-gecko transform (aka the "untransform" applied
// to incoming input events before they can be passed on to Gecko).
//
// The primary reason we do this is to avoid the problem where input events,
// after being untransformed, end up hit-testing differently in Gecko. This
// might happen in cases where the input event lands on content that is async-
// scrolled into view, but Gecko still thinks it is out of view given the
// visible area of a scrollframe.
//
// Another reason we want to clear the untransform is that if our APZ hit-test
// hits a dispatch-to-content region then that's an ambiguous result and we
// need to ask Gecko what actually got hit. In order to do this we need to
// untransform the input event into Gecko space - but to do that we need to
// know which APZC got hit! This leads to a circular dependency; the only way
// to get out of it is to make sure that the untransform for all the possible
// matched APZCs is the same. It is simplest to ensure that by flushing the
// pending repaint requests, which makes all of the untransforms empty (and
// therefore equal).
MonitorAutoLock lock(mTreeLock);
FlushRepaintsRecursively(mRootNode);
}
void
APZCTreeManager::FlushRepaintsRecursively(HitTestingTreeNode* aNode)
{

Просмотреть файл

@ -429,6 +429,7 @@ private:
void UpdateWheelTransaction(WidgetInputEvent& aEvent);
void UpdateZoomConstraintsRecursively(HitTestingTreeNode* aNode,
const ZoomConstraints& aConstraints);
void FlushRepaintsToClearScreenToGeckoTransform();
void FlushRepaintsRecursively(HitTestingTreeNode* aNode);
already_AddRefed<HitTestingTreeNode> RecycleOrCreateNode(TreeBuildingState& aState,

Просмотреть файл

@ -1505,6 +1505,7 @@ AsyncPanZoomController::AllowScrollHandoffInWheelTransaction() const
nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEvent)
{
LayoutDevicePoint delta = GetScrollWheelDelta(aEvent);
APZC_LOG("%p got a scroll-wheel with delta %s\n", this, Stringify(delta).c_str());
if ((delta.x || delta.y) &&
!CanScrollWithWheel(delta) &&

Просмотреть файл

@ -125,16 +125,15 @@ void Axis::StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs) {
bool Axis::AdjustDisplacement(ParentLayerCoord aDisplacement,
/* ParentLayerCoord */ float& aDisplacementOut,
/* ParentLayerCoord */ float&
aOverscrollAmountOut,
bool forceOverscroll /* = false */)
/* ParentLayerCoord */ float& aOverscrollAmountOut,
bool aForceOverscroll /* = false */)
{
if (mAxisLocked) {
aOverscrollAmountOut = 0;
aDisplacementOut = 0;
return false;
}
if (forceOverscroll) {
if (aForceOverscroll) {
aOverscrollAmountOut = aDisplacement;
aDisplacementOut = 0;
return false;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше