Merge m-c to b2ginbound, a=merge

This commit is contained in:
Wes Kocher 2015-10-14 15:01:18 -07:00
Родитель 0c77e54e7f 57f74f6d6c
Коммит 5530340073
148 изменённых файлов: 2659 добавлений и 1219 удалений

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

@ -533,11 +533,6 @@ public:
*/
virtual void SetSelected(bool aSelect);
/**
* Extend selection to this accessible.
*/
void ExtendSelection() { };
/**
* Select the accessible within its container.
*/

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

@ -192,10 +192,5 @@ OuterDocAccessible::RemoteChildDoc() const
if (!tab)
return nullptr;
if (DocAccessibleParent* doc = tab->GetTopLevelDocAccessible()) {
return doc;
}
MOZ_ASSERT(false, "no top level tab document?");
return nullptr;
return tab->GetTopLevelDocAccessible();
}

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

@ -30,7 +30,7 @@ class Accessible;
* Mozilla creates the implementations of nsIAccessible on demand.
* See http://www.mozilla.org/projects/ui/accessibility for more information.
*/
[scriptable, uuid(66b110b0-c25a-4784-8623-f6ba40c7cfee)]
[scriptable, uuid(de2869d9-563c-4943-996b-31a4daa4d097)]
interface nsIAccessible : nsISupports
{
/**
@ -231,12 +231,6 @@ interface nsIAccessible : nsISupports
*/
void setSelected(in boolean isSelected);
/**
* Extend the current selection from its current accessible anchor node
* to this accessible
*/
void extendSelection();
/**
* Select this accessible node only
*/

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

@ -1621,6 +1621,28 @@ DocAccessibleChild::RecvUnselectAll(const uint64_t& aID,
return true;
}
bool
DocAccessibleChild::RecvTakeSelection(const uint64_t& aID)
{
Accessible* acc = IdToAccessible(aID);
if (acc) {
acc->TakeSelection();
}
return true;
}
bool
DocAccessibleChild::RecvSetSelected(const uint64_t& aID, const bool& aSelect)
{
Accessible* acc = IdToAccessible(aID);
if (acc) {
acc->SetSelected(aSelect);
}
return true;
}
bool
DocAccessibleChild::RecvDoAction(const uint64_t& aID,
const uint8_t& aIndex,

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

@ -401,6 +401,10 @@ public:
virtual bool RecvUnselectAll(const uint64_t& aID,
bool* aSuccess) override;
virtual bool RecvTakeSelection(const uint64_t& aID) override;
virtual bool RecvSetSelected(const uint64_t& aID,
const bool& aSelect) override;
virtual bool RecvDoAction(const uint64_t& aID,
const uint8_t& aIndex,
bool* aSuccess) override;

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

@ -216,6 +216,9 @@ child:
prio(high) sync SelectAll(uint64_t aID) returns(bool aSuccess);
prio(high) sync UnselectAll(uint64_t aID) returns(bool aSuccess);
async TakeSelection(uint64_t aID);
async SetSelected(uint64_t aID, bool aSelected);
prio(high) sync DoAction(uint64_t aID, uint8_t aIndex) returns(bool aSuccess);
prio(high) sync ActionCount(uint64_t aID) returns(uint8_t aCount);
prio(high) sync ActionDescriptionAt(uint64_t aID, uint8_t aIndex) returns(nsString aDescription);

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

@ -906,6 +906,18 @@ ProxyAccessible::UnselectAll()
return success;
}
void
ProxyAccessible::TakeSelection()
{
unused << mDoc->SendTakeSelection(mID);
}
void
ProxyAccessible::SetSelected(bool aSelect)
{
unused << mDoc->SendSetSelected(mID, aSelect);
}
bool
ProxyAccessible::DoAction(uint8_t aIndex)
{

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

@ -309,6 +309,9 @@ public:
bool SelectAll();
bool UnselectAll();
void TakeSelection();
void SetSelected(bool aSelect);
bool DoAction(uint8_t aIndex);
uint8_t ActionCount();
void ActionDescriptionAt(uint8_t aIndex, nsString& aDescription);

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

@ -913,9 +913,6 @@ AccessibleWrap::accSelect(
if (flagsSelect & SELFLAG_REMOVESELECTION)
xpAccessible->SetSelected(false);
if (flagsSelect & SELFLAG_EXTENDSELECTION)
xpAccessible->ExtendSelection();
return S_OK;
}

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

@ -498,16 +498,6 @@ xpcAccessible::SetSelected(bool aSelect)
return NS_OK;
}
NS_IMETHODIMP
xpcAccessible::ExtendSelection()
{
if (!Intl())
return NS_ERROR_FAILURE;
Intl()->ExtendSelection();
return NS_OK;
}
NS_IMETHODIMP
xpcAccessible::TakeSelection()
{

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

@ -73,7 +73,6 @@ public:
final override;
NS_IMETHOD SetSelected(bool aSelect) final override;
NS_IMETHOD ExtendSelection() final override;
NS_IMETHOD TakeSelection() final override;
NS_IMETHOD TakeFocus() final override;

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

@ -1104,9 +1104,6 @@ var PageInfoListener = {
serializeElementInfo: function(document, url, type, alt, item, isBG)
{
// Interface for image loading content.
const nsIImageLoadingContent = Components.interfaces.nsIImageLoadingContent;
let result = {};
let imageText;
@ -1130,10 +1127,9 @@ var PageInfoListener = {
result.mimeType = item.type;
}
if (!result.mimeType && !isBG && item instanceof nsIImageLoadingContent) {
if (!result.mimeType && !isBG && item instanceof Ci.nsIImageLoadingContent) {
// Interface for image loading content.
const nsIImageLoadingContent = Components.interfaces.nsIImageLoadingContent;
let imageRequest = item.getRequest(nsIImageLoadingContent.CURRENT_REQUEST);
let imageRequest = item.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
if (imageRequest) {
result.mimeType = imageRequest.mimeType;
let image = !(imageRequest.imageStatus & imageRequest.STATUS_ERROR) && imageRequest.image;
@ -1158,7 +1154,18 @@ var PageInfoListener = {
result.HTMLVideoElement = item instanceof content.HTMLVideoElement;
result.HTMLAudioElement = item instanceof content.HTMLAudioElement;
if (!isBG) {
if (isBG) {
// Items that are showing this image as a background
// image might not necessarily have a width or height,
// so we'll dynamically generate an image and send up the
// natural dimensions.
let img = content.document.createElement("img");
img.src = url;
result.naturalWidth = img.naturalWidth;
result.naturalHeight = img.naturalHeight;
} else {
// Otherwise, we can use the current width and height
// of the image.
result.width = item.width;
result.height = item.height;
}

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

@ -895,6 +895,14 @@ function makePreview(row)
// "width" and "height" attributes must be set to newImage,
// even if there is no "width" or "height attribute in item;
// otherwise, the preview image cannot be displayed correctly.
// Since the image might have been loaded out-of-process, we expect
// the item to tell us its width / height dimensions. Failing that
// the item should tell us the natural dimensions of the image. Finally
// failing that, we'll assume that the image was never loaded in the
// other process (this can be true for favicons, for example), and so
// we'll assume that we can use the natural dimensions of the newImage
// we just created. If the natural dimensions of newImage are not known
// then the image is probably broken.
if (!isBG) {
newImage.width = ("width" in item && item.width) || newImage.naturalWidth;
newImage.height = ("height" in item && item.height) || newImage.naturalHeight;
@ -902,8 +910,8 @@ function makePreview(row)
else {
// the Width and Height of an HTML tag should not be used for its background image
// (for example, "table" can have "width" or "height" attributes)
newImage.width = newImage.naturalWidth;
newImage.height = newImage.naturalHeight;
newImage.width = item.naturalWidth || newImage.naturalWidth;
newImage.height = item.naturalHeight || newImage.naturalHeight;
}
if (item.SVGImageElement) {

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

@ -635,8 +635,9 @@ Sanitizer.prototype = {
let newWindow = existingWindow.openDialog("chrome://browser/content/", "_blank",
features, defaultArgs);
let onFullScreen = null;
if (AppConstants.platform == "macosx") {
let onFullScreen = function(e) {
onFullScreen = function(e) {
newWindow.removeEventListener("fullscreen", onFullScreen);
let docEl = newWindow.document.documentElement;
let sizemode = docEl.getAttribute("sizemode");
@ -658,7 +659,7 @@ Sanitizer.prototype = {
// closes) and/or run too late (and not have a fully-formed window yet
// in existence). See bug 1088137.
let newWindowOpened = false;
function onWindowOpened(subject, topic, data) {
let onWindowOpened = function(subject, topic, data) {
if (subject != newWindow)
return;
@ -675,7 +676,7 @@ Sanitizer.prototype = {
}
let numWindowsClosing = windowList.length;
function onWindowClosed() {
let onWindowClosed = function() {
numWindowsClosing--;
if (numWindowsClosing == 0) {
Services.obs.removeObserver(onWindowClosed, "xul-window-destroyed");
@ -686,9 +687,9 @@ Sanitizer.prototype = {
}
}
}
Services.obs.addObserver(onWindowOpened, "browser-delayed-startup-finished", false);
Services.obs.addObserver(onWindowClosed, "xul-window-destroyed", false);
});
Services.obs.addObserver(onWindowOpened, "browser-delayed-startup-finished", false);
Services.obs.addObserver(onWindowClosed, "xul-window-destroyed", false);
// Start the process of closing windows
while (windowList.length) {

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

@ -243,10 +243,12 @@
see bug 492960 comment 20. -->
<menupopup id="customizationPanelItemContextMenu">
<menuitem oncommand="gCustomizeMode.addToToolbar(document.popupNode)"
closemenu="single"
class="customize-context-moveToToolbar"
accesskey="&customizeMenu.moveToToolbar.accesskey;"
label="&customizeMenu.moveToToolbar.label;"/>
<menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode)"
closemenu="single"
class="customize-context-removeFromPanel"
accesskey="&customizeMenu.removeFromMenu.accesskey;"
label="&customizeMenu.removeFromMenu.label;"/>

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

@ -2621,11 +2621,11 @@ ContentPermissionPrompt.prototype = {
},
_promptWebNotifications : function(aRequest) {
var message = gBrowserBundle.GetStringFromName("webNotifications.showFromSite2");
var message = gBrowserBundle.GetStringFromName("webNotifications.receiveFromSite");
var actions = [
{
stringId: "webNotifications.alwaysShow",
stringId: "webNotifications.alwaysReceive",
action: Ci.nsIPermissionManager.ALLOW_ACTION,
expireType: null,
callback: function() {},

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

@ -178,8 +178,9 @@ PlacesTreeView.prototype = {
let row = -1;
let useNodeIndex = typeof(aNodeIndex) == "number";
if (parent == this._rootNode)
if (parent == this._rootNode) {
row = useNodeIndex ? aNodeIndex : this._rootNode.getChildIndex(aNode);
}
else if (useNodeIndex && typeof(aParentRow) == "number") {
// If we have both the row of the parent node, and the node's index, we
// can avoid searching the rows array if the parent is a plain container.
@ -855,8 +856,7 @@ PlacesTreeView.prototype = {
.then(aLivemark => {
this._controller.cacheLivemarkInfo(aNode, aLivemark);
let properties = this._cellProperties.get(aNode);
this._cellProperties.set(aNode, properties += " livemark ");
this._cellProperties.set(aNode, properties += " livemark");
// The livemark attribute is set as a cell property on the title cell.
this._invalidateCellValue(aNode, this.COLUMN_TYPE_TITLE);
}, Components.utils.reportError);
@ -1175,7 +1175,8 @@ PlacesTreeView.prototype = {
PlacesUtils.livemarks.getLivemark({ id: node.itemId })
.then(aLivemark => {
this._controller.cacheLivemarkInfo(node, aLivemark);
properties += " livemark";
let props = this._cellProperties.get(node);
this._cellProperties.set(node, props += " livemark");
// The livemark attribute is set as a cell property on the title cell.
this._invalidateCellValue(node, this.COLUMN_TYPE_TITLE);
}, () => undefined);

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

@ -375,11 +375,11 @@ geolocation.neverShareLocation.accesskey=N
geolocation.shareWithSite2=Would you like to share your location with this site?
geolocation.shareWithFile2=Would you like to share your location with this file?
webNotifications.alwaysShow=Always Show Notifications
webNotifications.alwaysShow.accesskey=A
webNotifications.alwaysReceive=Always Receive Notifications
webNotifications.alwaysReceive.accesskey=A
webNotifications.neverShow=Always Block Notifications
webNotifications.neverShow.accesskey=N
webNotifications.showFromSite2=Would you like to show notifications from this site?
webNotifications.receiveFromSite=Would you like to receive notifications from this site?
# Pointer lock UI

21
devtools/client/shared/vendor/REACT_REDUX_LICENSE поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Dan Abramov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

9
devtools/client/shared/vendor/REACT_REDUX_UPGRADING поставляемый Normal file
Просмотреть файл

@ -0,0 +1,9 @@
"react-redux" uses UMD style loading to work in many different environments.
It assumes that "react" and "redux" are both included via `require("react")`
as in node or browserify, but the paths to our react and redux installation are different.
If upgrading react-redux, define the correct paths and replace the require statements
for the module.exports case with the correct paths.
Path to react: "devtools/client/shared/vendor/react"
Path to redux: "devtools/client/shared/vendor/redux"

1
devtools/client/shared/vendor/moz.build поставляемый
Просмотреть файл

@ -12,6 +12,7 @@ if CONFIG['DEBUG_JS_MODULES']:
]
modules += [
'react-redux.js',
'react.js',
'redux.js',
]

724
devtools/client/shared/vendor/react-redux.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,724 @@
var REACT_PATH = "devtools/client/shared/vendor/react";
var REDUX_PATH = "devtools/client/shared/vendor/redux";
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require(REACT_PATH), require(REDUX_PATH));
else if(typeof define === 'function' && define.amd)
define(["react", "redux"], factory);
else if(typeof exports === 'object')
exports["ReactRedux"] = factory(require("react"), require("redux"));
else
root["ReactRedux"] = factory(root["React"], root["Redux"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_10__, __WEBPACK_EXTERNAL_MODULE_11__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _react = __webpack_require__(10);
var _react2 = _interopRequireDefault(_react);
var _componentsCreateAll = __webpack_require__(2);
var _componentsCreateAll2 = _interopRequireDefault(_componentsCreateAll);
var _createAll = _componentsCreateAll2['default'](_react2['default']);
var Provider = _createAll.Provider;
var connect = _createAll.connect;
exports.Provider = Provider;
exports.connect = connect;
/***/ },
/* 1 */
/***/ function(module, exports) {
"use strict";
exports.__esModule = true;
exports["default"] = createStoreShape;
function createStoreShape(PropTypes) {
return PropTypes.shape({
subscribe: PropTypes.func.isRequired,
dispatch: PropTypes.func.isRequired,
getState: PropTypes.func.isRequired
});
}
module.exports = exports["default"];
/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
exports['default'] = createAll;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _createProvider = __webpack_require__(4);
var _createProvider2 = _interopRequireDefault(_createProvider);
var _createConnect = __webpack_require__(3);
var _createConnect2 = _interopRequireDefault(_createConnect);
function createAll(React) {
var Provider = _createProvider2['default'](React);
var connect = _createConnect2['default'](React);
return { Provider: Provider, connect: connect };
}
module.exports = exports['default'];
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
exports['default'] = createConnect;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var _utilsCreateStoreShape = __webpack_require__(1);
var _utilsCreateStoreShape2 = _interopRequireDefault(_utilsCreateStoreShape);
var _utilsShallowEqual = __webpack_require__(6);
var _utilsShallowEqual2 = _interopRequireDefault(_utilsShallowEqual);
var _utilsIsPlainObject = __webpack_require__(5);
var _utilsIsPlainObject2 = _interopRequireDefault(_utilsIsPlainObject);
var _utilsWrapActionCreators = __webpack_require__(7);
var _utilsWrapActionCreators2 = _interopRequireDefault(_utilsWrapActionCreators);
var _hoistNonReactStatics = __webpack_require__(8);
var _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics);
var _invariant = __webpack_require__(9);
var _invariant2 = _interopRequireDefault(_invariant);
var defaultMapStateToProps = function defaultMapStateToProps() {
return {};
};
var defaultMapDispatchToProps = function defaultMapDispatchToProps(dispatch) {
return { dispatch: dispatch };
};
var defaultMergeProps = function defaultMergeProps(stateProps, dispatchProps, parentProps) {
return _extends({}, parentProps, stateProps, dispatchProps);
};
function getDisplayName(Component) {
return Component.displayName || Component.name || 'Component';
}
// Helps track hot reloading.
var nextVersion = 0;
function createConnect(React) {
var Component = React.Component;
var PropTypes = React.PropTypes;
var storeShape = _utilsCreateStoreShape2['default'](PropTypes);
return function connect(mapStateToProps, mapDispatchToProps, mergeProps) {
var options = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];
var shouldSubscribe = Boolean(mapStateToProps);
var finalMapStateToProps = mapStateToProps || defaultMapStateToProps;
var finalMapDispatchToProps = _utilsIsPlainObject2['default'](mapDispatchToProps) ? _utilsWrapActionCreators2['default'](mapDispatchToProps) : mapDispatchToProps || defaultMapDispatchToProps;
var finalMergeProps = mergeProps || defaultMergeProps;
var shouldUpdateStateProps = finalMapStateToProps.length > 1;
var shouldUpdateDispatchProps = finalMapDispatchToProps.length > 1;
var _options$pure = options.pure;
var pure = _options$pure === undefined ? true : _options$pure;
// Helps track hot reloading.
var version = nextVersion++;
function computeStateProps(store, props) {
var state = store.getState();
var stateProps = shouldUpdateStateProps ? finalMapStateToProps(state, props) : finalMapStateToProps(state);
_invariant2['default'](_utilsIsPlainObject2['default'](stateProps), '`mapStateToProps` must return an object. Instead received %s.', stateProps);
return stateProps;
}
function computeDispatchProps(store, props) {
var dispatch = store.dispatch;
var dispatchProps = shouldUpdateDispatchProps ? finalMapDispatchToProps(dispatch, props) : finalMapDispatchToProps(dispatch);
_invariant2['default'](_utilsIsPlainObject2['default'](dispatchProps), '`mapDispatchToProps` must return an object. Instead received %s.', dispatchProps);
return dispatchProps;
}
function _computeNextState(stateProps, dispatchProps, parentProps) {
var mergedProps = finalMergeProps(stateProps, dispatchProps, parentProps);
_invariant2['default'](_utilsIsPlainObject2['default'](mergedProps), '`mergeProps` must return an object. Instead received %s.', mergedProps);
return mergedProps;
}
return function wrapWithConnect(WrappedComponent) {
var Connect = (function (_Component) {
_inherits(Connect, _Component);
Connect.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps, nextState) {
if (!pure) {
this.updateStateProps(nextProps);
this.updateDispatchProps(nextProps);
this.updateState(nextProps);
return true;
}
var storeChanged = nextState.storeState !== this.state.storeState;
var propsChanged = !_utilsShallowEqual2['default'](nextProps, this.props);
var mapStateProducedChange = false;
var dispatchPropsChanged = false;
if (storeChanged || propsChanged && shouldUpdateStateProps) {
mapStateProducedChange = this.updateStateProps(nextProps);
}
if (propsChanged && shouldUpdateDispatchProps) {
dispatchPropsChanged = this.updateDispatchProps(nextProps);
}
if (propsChanged || mapStateProducedChange || dispatchPropsChanged) {
this.updateState(nextProps);
return true;
}
return false;
};
function Connect(props, context) {
_classCallCheck(this, Connect);
_Component.call(this, props, context);
this.version = version;
this.store = props.store || context.store;
_invariant2['default'](this.store, 'Could not find "store" in either the context or ' + ('props of "' + this.constructor.displayName + '". ') + 'Either wrap the root component in a <Provider>, ' + ('or explicitly pass "store" as a prop to "' + this.constructor.displayName + '".'));
this.stateProps = computeStateProps(this.store, props);
this.dispatchProps = computeDispatchProps(this.store, props);
this.state = { storeState: null };
this.updateState();
}
Connect.prototype.computeNextState = function computeNextState() {
var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0];
return _computeNextState(this.stateProps, this.dispatchProps, props);
};
Connect.prototype.updateStateProps = function updateStateProps() {
var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0];
var nextStateProps = computeStateProps(this.store, props);
if (_utilsShallowEqual2['default'](nextStateProps, this.stateProps)) {
return false;
}
this.stateProps = nextStateProps;
return true;
};
Connect.prototype.updateDispatchProps = function updateDispatchProps() {
var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0];
var nextDispatchProps = computeDispatchProps(this.store, props);
if (_utilsShallowEqual2['default'](nextDispatchProps, this.dispatchProps)) {
return false;
}
this.dispatchProps = nextDispatchProps;
return true;
};
Connect.prototype.updateState = function updateState() {
var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0];
this.nextState = this.computeNextState(props);
};
Connect.prototype.isSubscribed = function isSubscribed() {
return typeof this.unsubscribe === 'function';
};
Connect.prototype.trySubscribe = function trySubscribe() {
if (shouldSubscribe && !this.unsubscribe) {
this.unsubscribe = this.store.subscribe(this.handleChange.bind(this));
this.handleChange();
}
};
Connect.prototype.tryUnsubscribe = function tryUnsubscribe() {
if (this.unsubscribe) {
this.unsubscribe();
this.unsubscribe = null;
}
};
Connect.prototype.componentDidMount = function componentDidMount() {
this.trySubscribe();
};
Connect.prototype.componentWillUnmount = function componentWillUnmount() {
this.tryUnsubscribe();
};
Connect.prototype.handleChange = function handleChange() {
if (!this.unsubscribe) {
return;
}
this.setState({
storeState: this.store.getState()
});
};
Connect.prototype.getWrappedInstance = function getWrappedInstance() {
return this.refs.wrappedInstance;
};
Connect.prototype.render = function render() {
return React.createElement(WrappedComponent, _extends({ ref: 'wrappedInstance'
}, this.nextState));
};
return Connect;
})(Component);
Connect.displayName = 'Connect(' + getDisplayName(WrappedComponent) + ')';
Connect.WrappedComponent = WrappedComponent;
Connect.contextTypes = {
store: storeShape
};
Connect.propTypes = {
store: storeShape
};
if (true) {
Connect.prototype.componentWillUpdate = function componentWillUpdate() {
if (this.version === version) {
return;
}
// We are hot reloading!
this.version = version;
// Update the state and bindings.
this.trySubscribe();
this.updateStateProps();
this.updateDispatchProps();
this.updateState();
};
}
return _hoistNonReactStatics2['default'](Connect, WrappedComponent);
};
};
}
module.exports = exports['default'];
/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
exports['default'] = createProvider;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var _utilsCreateStoreShape = __webpack_require__(1);
var _utilsCreateStoreShape2 = _interopRequireDefault(_utilsCreateStoreShape);
function isUsingOwnerContext(React) {
var version = React.version;
if (typeof version !== 'string') {
return true;
}
var sections = version.split('.');
var major = parseInt(sections[0], 10);
var minor = parseInt(sections[1], 10);
return major === 0 && minor === 13;
}
function createProvider(React) {
var Component = React.Component;
var PropTypes = React.PropTypes;
var Children = React.Children;
var storeShape = _utilsCreateStoreShape2['default'](PropTypes);
var requireFunctionChild = isUsingOwnerContext(React);
var didWarnAboutChild = false;
function warnAboutFunctionChild() {
if (didWarnAboutChild || requireFunctionChild) {
return;
}
didWarnAboutChild = true;
console.error( // eslint-disable-line no-console
'With React 0.14 and later versions, you no longer need to ' + 'wrap <Provider> child into a function.');
}
function warnAboutElementChild() {
if (didWarnAboutChild || !requireFunctionChild) {
return;
}
didWarnAboutChild = true;
console.error( // eslint-disable-line no-console
'With React 0.13, you need to ' + 'wrap <Provider> child into a function. ' + 'This restriction will be removed with React 0.14.');
}
var didWarnAboutReceivingStore = false;
function warnAboutReceivingStore() {
if (didWarnAboutReceivingStore) {
return;
}
didWarnAboutReceivingStore = true;
console.error( // eslint-disable-line no-console
'<Provider> does not support changing `store` on the fly. ' + 'It is most likely that you see this error because you updated to ' + 'Redux 2.x and React Redux 2.x which no longer hot reload reducers ' + 'automatically. See https://github.com/rackt/react-redux/releases/' + 'tag/v2.0.0 for the migration instructions.');
}
var Provider = (function (_Component) {
_inherits(Provider, _Component);
Provider.prototype.getChildContext = function getChildContext() {
return { store: this.store };
};
function Provider(props, context) {
_classCallCheck(this, Provider);
_Component.call(this, props, context);
this.store = props.store;
}
Provider.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
var store = this.store;
var nextStore = nextProps.store;
if (store !== nextStore) {
warnAboutReceivingStore();
}
};
Provider.prototype.render = function render() {
var children = this.props.children;
if (typeof children === 'function') {
warnAboutFunctionChild();
children = children();
} else {
warnAboutElementChild();
}
return Children.only(children);
};
return Provider;
})(Component);
Provider.childContextTypes = {
store: storeShape.isRequired
};
Provider.propTypes = {
store: storeShape.isRequired,
children: (requireFunctionChild ? PropTypes.func : PropTypes.element).isRequired
};
return Provider;
}
module.exports = exports['default'];
/***/ },
/* 5 */
/***/ function(module, exports) {
'use strict';
exports.__esModule = true;
exports['default'] = isPlainObject;
var fnToString = function fnToString(fn) {
return Function.prototype.toString.call(fn);
};
/**
* @param {any} obj The object to inspect.
* @returns {boolean} True if the argument appears to be a plain object.
*/
function isPlainObject(obj) {
if (!obj || typeof obj !== 'object') {
return false;
}
var proto = typeof obj.constructor === 'function' ? Object.getPrototypeOf(obj) : Object.prototype;
if (proto === null) {
return true;
}
var constructor = proto.constructor;
return typeof constructor === 'function' && constructor instanceof constructor && fnToString(constructor) === fnToString(Object);
}
module.exports = exports['default'];
/***/ },
/* 6 */
/***/ function(module, exports) {
"use strict";
exports.__esModule = true;
exports["default"] = shallowEqual;
function shallowEqual(objA, objB) {
if (objA === objB) {
return true;
}
var keysA = Object.keys(objA);
var keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
// Test for A's keys different from B.
var hasOwn = Object.prototype.hasOwnProperty;
for (var i = 0; i < keysA.length; i++) {
if (!hasOwn.call(objB, keysA[i]) || objA[keysA[i]] !== objB[keysA[i]]) {
return false;
}
}
return true;
}
module.exports = exports["default"];
/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
exports['default'] = wrapActionCreators;
var _redux = __webpack_require__(11);
function wrapActionCreators(actionCreators) {
return function (dispatch) {
return _redux.bindActionCreators(actionCreators, dispatch);
};
}
module.exports = exports['default'];
/***/ },
/* 8 */
/***/ function(module, exports) {
/**
* Copyright 2015, Yahoo! Inc.
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
'use strict';
var REACT_STATICS = {
childContextTypes: true,
contextTypes: true,
defaultProps: true,
displayName: true,
getDefaultProps: true,
mixins: true,
propTypes: true,
type: true
};
var KNOWN_STATICS = {
name: true,
length: true,
prototype: true,
caller: true,
arguments: true,
arity: true
};
module.exports = function hoistNonReactStatics(targetComponent, sourceComponent) {
var keys = Object.getOwnPropertyNames(sourceComponent);
for (var i=0; i<keys.length; ++i) {
if (!REACT_STATICS[keys[i]] && !KNOWN_STATICS[keys[i]]) {
targetComponent[keys[i]] = sourceComponent[keys[i]];
}
}
return targetComponent;
};
/***/ },
/* 9 */
/***/ function(module, exports, __webpack_require__) {
/**
* Copyright 2013-2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule invariant
*/
'use strict';
/**
* Use invariant() to assert state which your program assumes to be true.
*
* Provide sprintf-style format (only %s is supported) and arguments
* to provide information about what broke and what you were
* expecting.
*
* The invariant message will be stripped in production, but the invariant
* will remain to ensure logic does not differ in production.
*/
var invariant = function(condition, format, a, b, c, d, e, f) {
if (true) {
if (format === undefined) {
throw new Error('invariant requires an error message argument');
}
}
if (!condition) {
var error;
if (format === undefined) {
error = new Error(
'Minified exception occurred; use the non-minified dev environment ' +
'for the full error message and additional helpful warnings.'
);
} else {
var args = [a, b, c, d, e, f];
var argIndex = 0;
error = new Error(
'Invariant Violation: ' +
format.replace(/%s/g, function() { return args[argIndex++]; })
);
}
error.framesToPop = 1; // we don't care about invariant's own frame
throw error;
}
};
module.exports = invariant;
/***/ },
/* 10 */
/***/ function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_10__;
/***/ },
/* 11 */
/***/ function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_11__;
/***/ }
/******/ ])
});
;

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

@ -2432,13 +2432,8 @@ class nsAsyncMessageToChild : public nsSameProcessAsyncMessageBase,
public nsRunnable
{
public:
nsAsyncMessageToChild(JSContext* aCx,
nsFrameLoader* aFrameLoader,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
: nsSameProcessAsyncMessageBase(aCx, aMessage, aData, aCpows, aPrincipal)
nsAsyncMessageToChild(JSContext* aCx, JS::Handle<JSObject*> aCpows, nsFrameLoader* aFrameLoader)
: nsSameProcessAsyncMessageBase(aCx, aCpows)
, mFrameLoader(aFrameLoader)
{
}
@ -2457,7 +2452,7 @@ public:
nsRefPtr<nsFrameLoader> mFrameLoader;
};
bool
nsresult
nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
@ -2469,27 +2464,37 @@ nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
ClonedMessageData data;
nsIContentParent* cp = tabParent->Manager();
if (!BuildClonedMessageDataForParent(cp, aData, data)) {
return false;
MOZ_CRASH();
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
jsipc::CPOWManager* mgr = cp->GetCPOWManager();
if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) {
return false;
return NS_ERROR_UNEXPECTED;
}
if (tabParent->SendAsyncMessage(nsString(aMessage), data, cpows,
IPC::Principal(aPrincipal))) {
return NS_OK;
} else {
return NS_ERROR_UNEXPECTED;
}
return tabParent->SendAsyncMessage(nsString(aMessage), data, cpows,
IPC::Principal(aPrincipal));
}
if (mChildMessageManager) {
nsCOMPtr<nsIRunnable> ev = new nsAsyncMessageToChild(aCx, this, aMessage,
aData, aCpows,
aPrincipal);
NS_DispatchToCurrentThread(ev);
return true;
nsRefPtr<nsAsyncMessageToChild> ev = new nsAsyncMessageToChild(aCx, aCpows, this);
nsresult rv = ev->Init(aCx, aMessage, aData, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
}
rv = NS_DispatchToCurrentThread(ev);
if (NS_FAILED(rv)) {
return rv;
}
return rv;
}
// We don't have any targets to send our asynchronous message to.
return false;
return NS_ERROR_UNEXPECTED;
}
bool

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

@ -92,11 +92,11 @@ public:
*/
virtual bool DoLoadMessageManagerScript(const nsAString& aURL,
bool aRunInGlobalScope) override;
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
mozilla::dom::ipc::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override;
virtual nsresult DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
mozilla::dom::ipc::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override;
virtual bool CheckPermission(const nsAString& aPermission) override;
virtual bool CheckManifestURL(const nsAString& aManifestURL) override;
virtual bool CheckAppHasPermission(const nsAString& aPermission) override;

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

@ -31,6 +31,7 @@
#include "mozilla/CycleCollectedJSRuntime.h"
#include "mozilla/IntentionalCrash.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/nsIContentParent.h"
#include "mozilla/dom/PermissionMessageUtils.h"
@ -809,8 +810,9 @@ nsFrameMessageManager::DispatchAsyncMessageInternal(JSContext* aCx,
return NS_ERROR_NOT_INITIALIZED;
}
if (!mCallback->DoSendAsyncMessage(aCx, aMessage, aData, aCpows, aPrincipal)) {
return NS_ERROR_FAILURE;
nsresult rv = mCallback->DoSendAsyncMessage(aCx, aMessage, aData, aCpows, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
@ -1889,15 +1891,9 @@ class nsAsyncMessageToSameProcessChild : public nsSameProcessAsyncMessageBase,
public nsRunnable
{
public:
nsAsyncMessageToSameProcessChild(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
: nsSameProcessAsyncMessageBase(aCx, aMessage, aData, aCpows, aPrincipal)
{
}
nsAsyncMessageToSameProcessChild(JSContext* aCx, JS::Handle<JSObject*> aCpows)
: nsSameProcessAsyncMessageBase(aCx, aCpows)
{ }
NS_IMETHOD Run()
{
nsFrameMessageManager* ppm = nsFrameMessageManager::GetChildProcessManager();
@ -1931,17 +1927,24 @@ public:
return true;
}
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override
virtual nsresult DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override
{
nsCOMPtr<nsIRunnable> ev =
new nsAsyncMessageToSameProcessChild(aCx, aMessage, aData, aCpows,
aPrincipal);
NS_DispatchToCurrentThread(ev);
return true;
nsRefPtr<nsAsyncMessageToSameProcessChild> ev =
new nsAsyncMessageToSameProcessChild(aCx, aCpows);
nsresult rv = ev->Init(aCx, aMessage, aData, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
}
rv = NS_DispatchToCurrentThread(ev);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
bool CheckPermission(const nsAString& aPermission) override
@ -2014,29 +2017,32 @@ public:
IPC::Principal(aPrincipal), aRetVal);
}
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override
virtual nsresult DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override
{
mozilla::dom::ContentChild* cc =
mozilla::dom::ContentChild::GetSingleton();
if (!cc) {
return true;
return NS_OK;
}
ClonedMessageData data;
if (!BuildClonedMessageDataForChild(cc, aData, data)) {
return false;
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
if (aCpows && !cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
return NS_ERROR_UNEXPECTED;
}
if (!cc->SendAsyncMessage(PromiseFlatString(aMessage), data, cpows,
IPC::Principal(aPrincipal))) {
return NS_ERROR_UNEXPECTED;
}
return cc->SendAsyncMessage(PromiseFlatString(aMessage), data, cpows,
IPC::Principal(aPrincipal));
}
return NS_OK;
}
};
@ -2044,15 +2050,9 @@ class nsAsyncMessageToSameProcessParent : public nsSameProcessAsyncMessageBase,
public SameProcessMessageQueue::Runnable
{
public:
nsAsyncMessageToSameProcessParent(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
: nsSameProcessAsyncMessageBase(aCx, aMessage, aData, aCpows, aPrincipal)
{
}
nsAsyncMessageToSameProcessParent(JSContext* aCx, JS::Handle<JSObject*> aCpows)
: nsSameProcessAsyncMessageBase(aCx, aCpows)
{ }
virtual nsresult HandleMessage() override
{
nsFrameMessageManager* ppm = nsFrameMessageManager::sSameProcessParentManager;
@ -2096,7 +2096,7 @@ public:
return true;
}
virtual bool DoSendAsyncMessage(JSContext* aCx,
virtual nsresult DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
@ -2104,9 +2104,14 @@ public:
{
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
nsRefPtr<nsAsyncMessageToSameProcessParent> ev =
new nsAsyncMessageToSameProcessParent(aCx, aMessage, aData, aCpows, aPrincipal);
new nsAsyncMessageToSameProcessParent(aCx, aCpows);
nsresult rv = ev->Init(aCx, aMessage, aData, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
}
queue->Push(ev);
return true;
return NS_OK;
}
};
@ -2202,23 +2207,28 @@ nsFrameMessageManager::MarkForCC()
return true;
}
nsSameProcessAsyncMessageBase::nsSameProcessAsyncMessageBase(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal)
: mRuntime(js::GetRuntime(aCx)),
mMessage(aMessage),
mCpows(aCx, aCpows),
mPrincipal(aPrincipal)
nsSameProcessAsyncMessageBase::nsSameProcessAsyncMessageBase(JSContext* aCx, JS::Handle<JSObject*> aCpows)
: mRuntime(nullptr)
, mCpows(aCx, aCpows)
{ }
nsresult
nsSameProcessAsyncMessageBase::Init(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
nsIPrincipal* aPrincipal)
{
if (!mData.Copy(aData)) {
#ifdef MOZ_CRASHREPORTER
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AsyncMessageOOM"),
NS_ConvertUTF16toUTF8(aMessage));
#endif
NS_ABORT_OOM(aData.DataLength());
Telemetry::Accumulate(Telemetry::IPC_SAME_PROCESS_MESSAGE_COPY_OOM_KB, aData.DataLength());
return NS_ERROR_OUT_OF_MEMORY;
}
mRuntime = js::GetRuntime(aCx);
mMessage = aMessage;
mPrincipal = aPrincipal;
return NS_OK;
}
void
@ -2226,6 +2236,8 @@ nsSameProcessAsyncMessageBase::ReceiveMessage(nsISupports* aTarget,
nsIFrameLoader* aTargetFrameLoader,
nsFrameMessageManager* aManager)
{
// Make sure that we have called Init() and it has succeeded.
MOZ_ASSERT(mRuntime);
if (aManager) {
SameProcessCpowHolder cpows(mRuntime, mCpows);

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

@ -73,13 +73,13 @@ public:
return true;
}
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal)
virtual nsresult DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal)
{
return true;
return NS_OK;
}
virtual bool CheckPermission(const nsAString& aPermission)
@ -317,28 +317,32 @@ private:
class MyAsyncMessage : public nsSameProcessAsyncMessageBase, public nsRunnable
{
// Initialize nsSameProcessAsyncMessageBase...
NS_IMETHOD Run() {
ReceiveMessage(..., ...);
return NS_OK;
}
};
*/
nsRefPtr<nsSameProcessAsyncMessageBase> ev = new MyAsyncMessage();
nsresult rv = ev->Init(...);
if (NS_SUCCEEDED(rv)) {
NS_DispatchToMainThread(ev);
}
*/
class nsSameProcessAsyncMessageBase
{
public:
typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData;
nsSameProcessAsyncMessageBase(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal);
nsSameProcessAsyncMessageBase(JSContext* aCx, JS::Handle<JSObject*> aCpows);
nsresult Init(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
nsIPrincipal* aPrincipal);
void ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader,
nsFrameMessageManager* aManager);
private:
nsSameProcessAsyncMessageBase(const nsSameProcessAsyncMessageBase&);

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

@ -49,16 +49,10 @@ class nsAsyncMessageToParent : public nsSameProcessAsyncMessageBase,
public SameProcessMessageQueue::Runnable
{
public:
nsAsyncMessageToParent(JSContext* aCx,
nsInProcessTabChildGlobal* aTabChild,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
: nsSameProcessAsyncMessageBase(aCx, aMessage, aData, aCpows, aPrincipal),
mTabChild(aTabChild)
{
}
nsAsyncMessageToParent(JSContext* aCx, JS::Handle<JSObject*> aCpows, nsInProcessTabChildGlobal* aTabChild)
: nsSameProcessAsyncMessageBase(aCx, aCpows)
, mTabChild(aTabChild)
{ }
virtual nsresult HandleMessage() override
{
@ -69,7 +63,7 @@ public:
nsRefPtr<nsInProcessTabChildGlobal> mTabChild;
};
bool
nsresult
nsInProcessTabChildGlobal::DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
@ -78,9 +72,15 @@ nsInProcessTabChildGlobal::DoSendAsyncMessage(JSContext* aCx,
{
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
nsRefPtr<nsAsyncMessageToParent> ev =
new nsAsyncMessageToParent(aCx, this, aMessage, aData, aCpows, aPrincipal);
new nsAsyncMessageToParent(aCx, aCpows, this);
nsresult rv = ev->Init(aCx, aMessage, aData, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
}
queue->Push(ev);
return true;
return NS_OK;
}
nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,

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

@ -88,11 +88,11 @@ public:
nsIPrincipal* aPrincipal,
nsTArray<StructuredCloneData>* aRetVal,
bool aIsSync) override;
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override;
virtual nsresult DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override;
virtual nsresult PreHandleEvent(
mozilla::EventChainPreVisitor& aVisitor) override;

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

@ -189,11 +189,11 @@ nsScriptNameSpaceManager* GetNameSpaceManager();
nsScriptNameSpaceManager* PeekNameSpaceManager();
// Runnable that's used to do async error reporting
class AsyncErrorReporter : public nsRunnable
class AsyncErrorReporter final : public nsRunnable
{
public:
// aWindow may be null if this error report is not associated with a window
AsyncErrorReporter(JSRuntime* aRuntime, xpc::ErrorReport* aReport)
explicit AsyncErrorReporter(xpc::ErrorReport* aReport)
: mReport(aReport)
{}

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

@ -1235,7 +1235,7 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
mTarget->DrawSurface(snapshot, r, r);
// Restore the clips and transform
for (uint32_t i = 0; i < CurrentState().clipsPushed.size(); i++) {
for (uint32_t i = 0; i < CurrentState().clipsPushed.Length(); i++) {
mTarget->PushClip(CurrentState().clipsPushed[i]);
}
@ -1719,7 +1719,7 @@ CanvasRenderingContext2D::Restore()
TransformWillUpdate();
for (uint32_t i = 0; i < CurrentState().clipsPushed.size(); i++) {
for (uint32_t i = 0; i < CurrentState().clipsPushed.Length(); i++) {
mTarget->PopClip();
}
@ -2864,7 +2864,7 @@ CanvasRenderingContext2D::Clip(const CanvasWindingRule& winding)
}
mTarget->PushClip(mPath);
CurrentState().clipsPushed.push_back(mPath);
CurrentState().clipsPushed.AppendElement(mPath);
}
void
@ -2879,7 +2879,7 @@ CanvasRenderingContext2D::Clip(const CanvasPath& path, const CanvasWindingRule&
}
mTarget->PushClip(gfxpath);
CurrentState().clipsPushed.push_back(gfxpath);
CurrentState().clipsPushed.AppendElement(gfxpath);
}
void

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

@ -984,7 +984,7 @@ protected:
return std::min(SIGMA_MAX, shadowBlur / 2.0f);
}
std::vector<mozilla::RefPtr<mozilla::gfx::Path> > clipsPushed;
nsTArray<mozilla::RefPtr<mozilla::gfx::Path> > clipsPushed;
nsRefPtr<gfxFontGroup> fontGroup;
nsCOMPtr<nsIAtom> fontLanguage;

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

@ -24,6 +24,7 @@ class WebGLVertexArrayObject;
namespace dom {
class OwningUnsignedLongOrUint32ArrayOrBoolean;
class OwningWebGLBufferOrLongLong;
class ArrayBufferViewOrSharedArrayBufferView;
} // namespace dom
class WebGL2Context
@ -51,8 +52,16 @@ public:
void CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
private:
template<typename BufferT>
void GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT& data);
public:
void GetBufferSubData(GLenum target, GLintptr offset,
const dom::Nullable<dom::ArrayBuffer>& maybeData);
void GetBufferSubData(GLenum target, GLintptr offset,
const dom::SharedArrayBuffer& data);
// -------------------------------------------------------------------------
@ -88,12 +97,12 @@ public:
void TexImage3D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format, GLenum type,
const dom::Nullable<dom::ArrayBufferView>& pixels,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
ErrorResult& rv);
void TexSubImage3D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const dom::Nullable<dom::ArrayBufferView>& pixels,
GLenum format, GLenum type, const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
ErrorResult& rv);
void TexSubImage3D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
@ -109,10 +118,10 @@ public:
GLint x, GLint y, GLsizei width, GLsizei height);
void CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLsizei imageSize, const dom::ArrayBufferView& data);
GLint border, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& data);
void CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize, const dom::ArrayBufferView& data);
GLenum format, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& data);
// -------------------------------------------------------------------------

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

@ -138,9 +138,12 @@ WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
}
}
// BufferT may be one of
// const dom::ArrayBuffer&
// const dom::SharedArrayBuffer&
template<typename BufferT>
void
WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
const dom::Nullable<dom::ArrayBuffer>& maybeData)
WebGL2Context::GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT& data)
{
if (IsContextLost())
return;
@ -159,11 +162,6 @@ WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
if (offset < 0)
return ErrorInvalidValue("getBufferSubData: negative offset");
// If returnedData is null then an INVALID_VALUE error is
// generated.
if (maybeData.IsNull())
return ErrorInvalidValue("getBufferSubData: returnedData is null");
WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
WebGLBuffer* boundBuffer = bufferSlot.get();
if (!boundBuffer)
@ -171,7 +169,6 @@ WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
// If offset + returnedData.byteLength would extend beyond the end
// of the buffer an INVALID_VALUE error is generated.
const dom::ArrayBuffer& data = maybeData.Value();
data.ComputeLengthAndData();
CheckedInt<WebGLsizeiptr> neededByteLength = CheckedInt<WebGLsizeiptr>(offset) + data.Length();
@ -225,4 +222,22 @@ WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
}
}
void WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
const dom::Nullable<dom::ArrayBuffer>& maybeData)
{
// If returnedData is null then an INVALID_VALUE error is
// generated.
if (maybeData.IsNull())
return ErrorInvalidValue("getBufferSubData: returnedData is null");
const dom::ArrayBuffer& data = maybeData.Value();
GetBufferSubDataT(target, offset, data);
}
void WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
const dom::SharedArrayBuffer& data)
{
GetBufferSubDataT(target, offset, data);
}
} // namespace mozilla

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

@ -39,7 +39,7 @@ void
WebGL2Context::TexImage3D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult& out_rv)
{
const char funcName[] = "texImage3D";
@ -59,7 +59,7 @@ WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult& out_rv)
{
const char funcName[] = "texSubImage3D";
@ -95,7 +95,7 @@ WebGL2Context::CopyTexSubImage3D(GLenum target, GLint level,
void
WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLsizei imageSize, const dom::ArrayBufferView& view)
GLint border, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& view)
{
GenerateWarning("compressedTexImage3D: Not implemented.");
}
@ -103,7 +103,7 @@ WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalF
void
WebGL2Context::CompressedTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, GLsizei imageSize, const dom::ArrayBufferView& view)
GLenum unpackFormat, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& view)
{
GenerateWarning("compressedTexSubImage3D: Not implemented.");
}

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

@ -45,7 +45,7 @@
#include "mozilla/dom/HTMLCanvasElement.h"
#include "nsWrapperCache.h"
#include "nsLayoutUtils.h"
#include "mozilla/dom/UnionTypes.h"
class nsIDocShell;
@ -100,6 +100,7 @@ class Element;
class ImageData;
class OwningHTMLCanvasElementOrOffscreenCanvas;
struct WebGLContextAttributes;
class ArrayBufferViewOrSharedArrayBufferView;
template<typename> struct Nullable;
} // namespace dom
@ -528,7 +529,7 @@ public:
void PolygonOffset(GLfloat factor, GLfloat units);
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const dom::Nullable<dom::ArrayBufferView>& pixels,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
ErrorResult& rv);
void RenderbufferStorage(GLenum target, GLenum internalFormat,
GLsizei width, GLsizei height);
@ -749,8 +750,8 @@ public:
WebGLintptr offset, WebGLsizeiptr size);
private:
void BufferDataUnchecked(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
void BufferData(GLenum target, WebGLsizeiptr size, void* data, GLenum usage);
template<typename BufferT>
void BufferDataT(GLenum target, const BufferT& data, GLenum usage);
public:
void BufferData(GLenum target, WebGLsizeiptr size, GLenum usage);
@ -758,16 +759,25 @@ public:
GLenum usage);
void BufferData(GLenum target, const dom::Nullable<dom::ArrayBuffer>& maybeData,
GLenum usage);
void BufferData(GLenum target, const dom::SharedArrayBuffer& data,
GLenum usage);
void BufferData(GLenum target, const dom::SharedArrayBufferView& data,
GLenum usage);
private:
void BufferSubDataUnchecked(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
template<typename BufferT>
void BufferSubDataT(GLenum target, WebGLsizeiptr byteOffset,
const BufferT& data);
public:
void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
const dom::ArrayBufferView& data);
void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
const dom::Nullable<dom::ArrayBuffer>& maybeData);
void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
const dom::SharedArrayBuffer& data);
void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
const dom::SharedArrayBufferView& data);
already_AddRefed<WebGLBuffer> CreateBuffer();
void DeleteBuffer(WebGLBuffer* buf);
bool IsBuffer(WebGLBuffer* buf);
@ -864,10 +874,10 @@ protected:
public:
void CompressedTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border,
const dom::ArrayBufferView& view);
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
void CompressedTexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height,
GLenum unpackFormat, const dom::ArrayBufferView& view);
GLenum unpackFormat, const dom::ArrayBufferViewOrSharedArrayBufferView& view);
void CopyTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
@ -878,7 +888,7 @@ public:
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult& out_rv);
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
@ -891,7 +901,7 @@ public:
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLsizei width, GLsizei height, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult& out_rv);
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
@ -1634,6 +1644,11 @@ ValidateTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
// Returns x rounded to the next highest multiple of y.
CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y);
void
ComputeLengthAndData(const dom::ArrayBufferViewOrSharedArrayBufferView& view,
void** const out_data, size_t* const out_length,
js::Scalar::Type* const out_type);
} // namespace mozilla
#endif

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

@ -182,25 +182,25 @@ WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage)
}
}
// BufferT may be one of
// const dom::ArrayBuffer&
// const dom::SharedArrayBuffer&
// const dom::ArrayBufferView&
// const dom::SharedArrayBufferView&
template<typename BufferT>
void
WebGLContext::BufferData(GLenum target,
const dom::Nullable<dom::ArrayBuffer>& maybeData,
GLenum usage)
WebGLContext::BufferDataT(GLenum target,
const BufferT& data,
GLenum usage)
{
if (IsContextLost())
return;
if (maybeData.IsNull()) {
// see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
return ErrorInvalidValue("bufferData: null object passed");
}
if (!ValidateBufferTarget(target, "bufferData"))
return;
const WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
const dom::ArrayBuffer& data = maybeData.Value();
data.ComputeLengthAndData();
// Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr
@ -231,20 +231,61 @@ WebGLContext::BufferData(GLenum target,
return ErrorOutOfMemory("bufferData: out of memory");
}
void
WebGLContext::BufferData(GLenum target,
const dom::SharedArrayBuffer& data,
GLenum usage)
{
BufferDataT(target, data, usage);
}
void
WebGLContext::BufferData(GLenum target,
const dom::Nullable<dom::ArrayBuffer>& maybeData,
GLenum usage)
{
if (maybeData.IsNull()) {
// see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
return ErrorInvalidValue("bufferData: null object passed");
}
BufferDataT(target, maybeData.Value(), usage);
}
void
WebGLContext::BufferData(GLenum target, const dom::ArrayBufferView& data,
GLenum usage)
{
BufferDataT(target, data, usage);
}
void
WebGLContext::BufferData(GLenum target, const dom::SharedArrayBufferView& data,
GLenum usage)
{
BufferDataT(target, data, usage);
}
// BufferT may be one of
// const dom::ArrayBuffer&
// const dom::SharedArrayBuffer&
// const dom::ArrayBufferView&
// const dom::SharedArrayBufferView&
template<typename BufferT>
void
WebGLContext::BufferSubDataT(GLenum target,
WebGLsizeiptr byteOffset,
const BufferT& data)
{
if (IsContextLost())
return;
if (!ValidateBufferTarget(target, "bufferData"))
if (!ValidateBufferTarget(target, "bufferSubData"))
return;
WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
return;
if (byteOffset < 0)
return ErrorInvalidValue("bufferSubData: negative offset");
WebGLBuffer* boundBuffer = bufferSlot.get();
if (!boundBuffer)
@ -252,119 +293,60 @@ WebGLContext::BufferData(GLenum target, const dom::ArrayBufferView& data,
data.ComputeLengthAndData();
// Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr
// is like intptr_t.
if (!CheckedInt<GLsizeiptr>(data.Length()).isValid())
return ErrorOutOfMemory("bufferData: bad size");
CheckedInt<WebGLsizeiptr> checked_neededByteLength =
CheckedInt<WebGLsizeiptr>(byteOffset) + data.Length();
InvalidateBufferFetching();
MakeContextCurrent();
GLenum error = CheckedBufferData(target, data.Length(), data.Data(), usage);
if (error) {
GenerateWarning("bufferData generated error %s", ErrorName(error));
if (!checked_neededByteLength.isValid()) {
ErrorInvalidValue("bufferSubData: Integer overflow computing the needed"
" byte length.");
return;
}
boundBuffer->SetByteLength(data.Length());
if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length()))
return ErrorOutOfMemory("bufferData: out of memory");
if (checked_neededByteLength.value() > boundBuffer->ByteLength()) {
ErrorInvalidValue("bufferSubData: Not enough data. Operation requires"
" %d bytes, but buffer only has %d bytes.",
checked_neededByteLength.value(),
boundBuffer->ByteLength());
return;
}
boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(),
data.Length());
MakeContextCurrent();
gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
}
void
WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
const dom::Nullable<dom::ArrayBuffer>& maybeData)
{
if (IsContextLost())
return;
if (maybeData.IsNull()) {
// see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
return;
}
BufferSubDataT(target, byteOffset, maybeData.Value());
}
if (!ValidateBufferTarget(target, "bufferSubData"))
return;
WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
if (byteOffset < 0)
return ErrorInvalidValue("bufferSubData: negative offset");
WebGLBuffer* boundBuffer = bufferSlot.get();
if (!boundBuffer)
return ErrorInvalidOperation("bufferData: no buffer bound!");
const dom::ArrayBuffer& data = maybeData.Value();
data.ComputeLengthAndData();
CheckedInt<WebGLsizeiptr> checked_neededByteLength =
CheckedInt<WebGLsizeiptr>(byteOffset) + data.Length();
if (!checked_neededByteLength.isValid()) {
ErrorInvalidValue("bufferSubData: Integer overflow computing the needed"
" byte length.");
return;
}
if (checked_neededByteLength.value() > boundBuffer->ByteLength()) {
ErrorInvalidValue("bufferSubData: Not enough data. Operation requires"
" %d bytes, but buffer only has %d bytes.",
checked_neededByteLength.value(),
boundBuffer->ByteLength());
return;
}
boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(),
data.Length());
MakeContextCurrent();
gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
void
WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
const dom::SharedArrayBuffer& data)
{
BufferSubDataT(target, byteOffset, data);
}
void
WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
const dom::ArrayBufferView& data)
{
if (IsContextLost())
return;
BufferSubDataT(target, byteOffset, data);
}
if (!ValidateBufferTarget(target, "bufferSubData"))
return;
WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
if (byteOffset < 0)
return ErrorInvalidValue("bufferSubData: negative offset");
WebGLBuffer* boundBuffer = bufferSlot.get();
if (!boundBuffer)
return ErrorInvalidOperation("bufferSubData: no buffer bound!");
data.ComputeLengthAndData();
CheckedInt<WebGLsizeiptr> checked_neededByteLength =
CheckedInt<WebGLsizeiptr>(byteOffset) + data.Length();
if (!checked_neededByteLength.isValid()) {
ErrorInvalidValue("bufferSubData: Integer overflow computing the needed"
" byte length.");
return;
}
if (checked_neededByteLength.value() > boundBuffer->ByteLength()) {
ErrorInvalidValue("bufferSubData: Not enough data. Operation requires"
" %d bytes, but buffer only has %d bytes.",
checked_neededByteLength.value(),
boundBuffer->ByteLength());
return;
}
boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(),
data.Length());
MakeContextCurrent();
gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
void
WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
const dom::SharedArrayBufferView& data)
{
BufferSubDataT(target, byteOffset, data);
}
already_AddRefed<WebGLBuffer>

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

@ -1381,10 +1381,32 @@ IsFormatAndTypeUnpackable(GLenum format, GLenum type)
}
}
// This function is temporary, and will be removed once https://bugzilla.mozilla.org/show_bug.cgi?id=1176214 lands, which will
// collapse the SharedArrayBufferView and ArrayBufferView into one.
void
ComputeLengthAndData(const dom::ArrayBufferViewOrSharedArrayBufferView& view,
void** const out_data, size_t* const out_length,
js::Scalar::Type* const out_type)
{
if (view.IsArrayBufferView()) {
const dom::ArrayBufferView& pixbuf = view.GetAsArrayBufferView();
pixbuf.ComputeLengthAndData();
*out_length = pixbuf.Length();
*out_data = pixbuf.Data();
*out_type = JS_GetArrayBufferViewType(pixbuf.Obj());
} else {
const dom::SharedArrayBufferView& pixbuf = view.GetAsSharedArrayBufferView();
pixbuf.ComputeLengthAndData();
*out_length = pixbuf.Length();
*out_data = pixbuf.Data();
*out_type = JS_GetSharedArrayBufferViewType(pixbuf.Obj());
}
}
void
WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
GLsizei height, GLenum format,
GLenum type, const dom::Nullable<dom::ArrayBufferView>& pixels,
GLenum type, const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
ErrorResult& rv)
{
if (IsContextLost())
@ -1460,8 +1482,13 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
MOZ_CRASH("bad `type`");
}
const dom::ArrayBufferView& pixbuf = pixels.Value();
int dataType = pixbuf.Type();
const dom::ArrayBufferViewOrSharedArrayBufferView &view = pixels.Value();
// Compute length and data. Don't reenter after this point, lest the
// precomputed go out of sync with the instant length/data.
size_t dataByteLen;
void* data;
js::Scalar::Type dataType;
ComputeLengthAndData(view, &data, &dataByteLen, &dataType);
// Check the pixels param type
if (dataType != requiredDataType)
@ -1479,15 +1506,9 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("readPixels: integer overflow computing the needed buffer size");
// Compute length and data. Don't reenter after this point, lest the
// precomputed go out of sync with the instant length/data.
pixbuf.ComputeLengthAndData();
uint32_t dataByteLen = pixbuf.Length();
if (checked_neededByteLength.value() > dataByteLen)
return ErrorInvalidOperation("readPixels: buffer too small");
void* data = pixbuf.Data();
if (!data) {
ErrorOutOfMemory("readPixels: buffer storage is null. Did we run out of memory?");
return rv.Throw(NS_ERROR_OUT_OF_MEMORY);

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

@ -298,7 +298,7 @@ void
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult& out_rv)
{
TexImageTarget texImageTarget;
@ -356,7 +356,7 @@ void
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height,
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult& out_rv)
{
TexImageTarget texImageTarget;
@ -434,7 +434,7 @@ WebGLContext::CopyTexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOf
void
WebGLContext::CompressedTexImage2D(GLenum rawTexImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLint border, const dom::ArrayBufferView& view)
GLint border, const dom::ArrayBufferViewOrSharedArrayBufferView& view)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;
@ -452,7 +452,7 @@ void
WebGLContext::CompressedTexSubImage2D(GLenum rawTexImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLsizei width,
GLsizei height, GLenum unpackFormat,
const dom::ArrayBufferView& view)
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
{
TexImageTarget texImageTarget;
WebGLTexture* tex;

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

@ -24,6 +24,7 @@ class ErrorResult;
namespace dom {
class Element;
class ImageData;
class ArrayBufferViewOrSharedArrayBufferView;
} // namespace dom
// Zero is not an integer power of two.
@ -108,24 +109,24 @@ public:
void CompressedTexImage2D(TexImageTarget texImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLint border, const dom::ArrayBufferView& view);
GLint border, const dom::ArrayBufferViewOrSharedArrayBufferView& view);
void CompressedTexImage3D(TexImageTarget texImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLsizei depth, GLint border, GLsizei imageSize,
const dom::ArrayBufferView& view);
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
void CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLsizei width,
GLsizei height, GLenum unpackFormat,
const dom::ArrayBufferView& view);
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
void CompressedTexSubImage3D(TexImageTarget texImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, GLsizei imageSize,
const dom::ArrayBufferView& view);
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
void CopyTexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
@ -144,7 +145,7 @@ public:
void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult* const out_rv);
void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
@ -156,7 +157,7 @@ public:
void TexImage3D(TexImageTarget target, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth, GLint border,
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult* const out_rv);
@ -169,7 +170,7 @@ public:
void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult* const out_rv);
void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
@ -181,7 +182,7 @@ public:
void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
GLsizei depth, GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult* const out_rv);
void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum unpackFormat,

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

@ -58,7 +58,7 @@ WebGLTexture::CompressedTexImage2D(TexImageTarget texImageTarget,
GLint level,
GLenum internalFormat,
GLsizei width, GLsizei height, GLint border,
const dom::ArrayBufferView& view)
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
{
const WebGLTexImageFunc func = WebGLTexImageFunc::CompTexImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
@ -76,9 +76,11 @@ WebGLTexture::CompressedTexImage2D(TexImageTarget texImageTarget,
return;
}
view.ComputeLengthAndData();
size_t byteLength;
void* data;
js::Scalar::Type dataType;
ComputeLengthAndData(view, &data, &byteLength, &dataType);
uint32_t byteLength = view.Length();
if (!mContext->ValidateCompTexImageDataSize(level, internalFormat, width, height, byteLength, func, dims)) {
return;
}
@ -96,7 +98,7 @@ WebGLTexture::CompressedTexImage2D(TexImageTarget texImageTarget,
mContext->MakeContextCurrent();
gl::GLContext* gl = mContext->gl;
gl->fCompressedTexImage2D(texImageTarget.get(), level, internalFormat, width, height, border, byteLength, view.Data());
gl->fCompressedTexImage2D(texImageTarget.get(), level, internalFormat, width, height, border, byteLength, data);
SetImageInfo(texImageTarget, level, width, height, 1, internalFormat,
WebGLImageDataStatus::InitializedImageData);
@ -106,7 +108,7 @@ void
WebGLTexture::CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height,
GLenum internalFormat,
const dom::ArrayBufferView& view)
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
{
const WebGLTexImageFunc func = WebGLTexImageFunc::CompTexSubImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
@ -131,9 +133,11 @@ WebGLTexture::CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level
return mContext->ErrorInvalidOperation("compressedTexImage2D: internalFormat does not match the existing image");
}
view.ComputeLengthAndData();
size_t byteLength;
void* data;
js::Scalar::Type dataType;
ComputeLengthAndData(view, &data, &byteLength, &dataType);
uint32_t byteLength = view.Length();
if (!mContext->ValidateCompTexImageDataSize(level, internalFormat, width, height, byteLength, func, dims))
return;
@ -161,7 +165,7 @@ WebGLTexture::CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level
mContext->MakeContextCurrent();
gl::GLContext* gl = mContext->gl;
gl->fCompressedTexSubImage2D(texImageTarget.get(), level, xOffset, yOffset, width, height, internalFormat, byteLength, view.Data());
gl->fCompressedTexSubImage2D(texImageTarget.get(), level, xOffset, yOffset, width, height, internalFormat, byteLength, data);
}
void
@ -614,23 +618,19 @@ void
WebGLTexture::TexImage2D(TexImageTarget texImageTarget, GLint level,
GLenum internalFormat, GLsizei width,
GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType, const dom::Nullable<dom::ArrayBufferView>& maybeView,
GLenum unpackType, const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult* const out_rv)
{
void* data;
uint32_t length;
size_t length;
js::Scalar::Type jsArrayType;
if (maybeView.IsNull()) {
data = nullptr;
length = 0;
jsArrayType = js::Scalar::MaxTypedArrayViewType;
} else {
const dom::ArrayBufferView& view = maybeView.Value();
view.ComputeLengthAndData();
data = view.Data();
length = view.Length();
jsArrayType = view.Type();
const auto& view = maybeView.Value();
ComputeLengthAndData(view, &data, &length, &jsArrayType);
}
const char funcName[] = "texImage2D";
@ -850,14 +850,17 @@ WebGLTexture::TexSubImage2D(TexImageTarget texImageTarget, GLint level,
GLint xOffset, GLint yOffset,
GLsizei width, GLsizei height,
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult* const out_rv)
{
if (maybeView.IsNull())
return mContext->ErrorInvalidValue("texSubImage2D: pixels must not be null!");
const dom::ArrayBufferView& view = maybeView.Value();
view.ComputeLengthAndData();
const auto& view = maybeView.Value();
size_t length;
void* data;
js::Scalar::Type jsArrayType;
ComputeLengthAndData(view, &data, &length, &jsArrayType);
const char funcName[] = "texSubImage2D";
if (!DoesTargetMatchDimensions(mContext, texImageTarget, 2, funcName))
@ -865,7 +868,7 @@ WebGLTexture::TexSubImage2D(TexImageTarget texImageTarget, GLint level,
return TexSubImage2D_base(texImageTarget, level, xOffset, yOffset,
width, height, 0, unpackFormat, unpackType,
view.Data(), view.Length(), view.Type(),
data, length, jsArrayType,
WebGLTexelFormat::Auto, false);
}
@ -1211,7 +1214,7 @@ void
WebGLTexture::TexImage3D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult* const out_rv)
{
void* data;
@ -1222,12 +1225,8 @@ WebGLTexture::TexImage3D(TexImageTarget texImageTarget, GLint level, GLenum inte
dataLength = 0;
jsArrayType = js::Scalar::MaxTypedArrayViewType;
} else {
const dom::ArrayBufferView& view = maybeView.Value();
view.ComputeLengthAndData();
data = view.Data();
dataLength = view.Length();
jsArrayType = view.Type();
const auto& view = maybeView.Value();
ComputeLengthAndData(view, &data, &dataLength, &jsArrayType);
}
const char funcName[] = "texImage3D";
@ -1318,14 +1317,17 @@ WebGLTexture::TexSubImage3D(TexImageTarget texImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult* const out_rv)
{
if (maybeView.IsNull())
return mContext->ErrorInvalidValue("texSubImage3D: pixels must not be null!");
const dom::ArrayBufferView& view = maybeView.Value();
view.ComputeLengthAndData();
const auto& view = maybeView.Value();
void* data;
size_t dataLength;
js::Scalar::Type jsArrayType;
ComputeLengthAndData(view, &data, &dataLength, &jsArrayType);
const char funcName[] = "texSubImage3D";
if (!DoesTargetMatchDimensions(mContext, texImageTarget, 3, funcName))
@ -1358,10 +1360,6 @@ WebGLTexture::TexSubImage3D(TexImageTarget texImageTarget, GLint level,
return mContext->ErrorInvalidOperation("texSubImage3D: type differs from that of the existing image");
}
js::Scalar::Type jsArrayType = view.Type();
void* data = view.Data();
size_t dataLength = view.Length();
if (!mContext->ValidateTexInputData(unpackType, jsArrayType, func, dims))
return;

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

@ -23,6 +23,7 @@ skip-if = android_version == '10' || android_version == '18' #Android 2.3 and 4.
[webgl-mochitest/test_noprog_draw.html]
[webgl-mochitest/test_privileged_exts.html]
[webgl-mochitest/test_renderer_strings.html]
[webgl-mochitest/test_sab_with_webgl.html]
[webgl-mochitest/test_texsubimage_float.html]
[webgl-mochitest/test_uninit_data.html]
[webgl-mochitest/test_webgl_available.html]

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

@ -0,0 +1,200 @@
<html>
<head>
<meta charset='UTF-8'>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
</head>
<body>
<canvas id='c' width='200' height='200'></canvas>
<canvas id='c2' width='200' height='200'></canvas>
<script>
var gl;
function RGBAToString(arr) {
return '[' + arr[0].toPrecision(4) + ', ' +
arr[1].toPrecision(4) + ', ' +
arr[2].toPrecision(4) + ', ' +
arr[3].toPrecision(4) + ']';
}
function TestScreenColor(gl, r, g, b, a) {
var arr = new SharedArrayBuffer(4);
var view = new SharedUint8Array(arr);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, view);
var err = gl.getError();
ok(err == 0, 'Should be no errors.');
if (err)
return;
var floatArr;
floatArr = new Float32Array(4);
floatArr[0] = view[0] / 255.0;
floatArr[1] = view[1] / 255.0;
floatArr[2] = view[2] / 255.0;
floatArr[3] = view[3] / 255.0;
var testText = RGBAToString(floatArr);
var refText = RGBAToString([r, g, b, a]);
var eps = 1.0 / 255.0;
var isSame = (Math.abs(floatArr[0] - r) < eps &&
Math.abs(floatArr[1] - g) < eps &&
Math.abs(floatArr[2] - b) < eps &&
Math.abs(floatArr[3] - a) < eps);
ok(isSame, 'Should be ' + refText + ', was ' + testText + ',');
}
// Give ourselves a scope to return early from:
(function() {
var canvas = document.getElementById('c');
var attribs = {
antialias: false,
depth: false,
};
gl = canvas.getContext('experimental-webgl', attribs);
if (!gl) {
todo(false, 'WebGL is unavailable.');
return;
}
if (typeof SharedArrayBuffer === 'undefined') {
todo(false, 'SharedArrayBuffer is unavailable.');
return;
}
if (SharedFloat32Array === 'undefined') {
todo(false, 'SharedFloat32Array is unavailable.');
return;
}
var vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, "attribute vec2 aVertCoord; void main(void) { gl_Position = vec4(aVertCoord, 0.0, 1.0); }");
gl.compileShader(vs);
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, "precision mediump float; uniform vec4 uFragColor; void main(void) { gl_FragColor = uFragColor; }");
gl.compileShader(fs);
var prog = gl.createProgram();
gl.attachShader(prog, vs);
gl.attachShader(prog, fs);
gl.linkProgram(prog);
var success = gl.getProgramParameter(prog, gl.LINK_STATUS);
if (!success) {
console.log('Error linking program for \'' + vsId + '\' and \'' + fsId + '\'.');
console.log('\nLink log: ' + gl.getProgramInfoLog(prog));
console.log('\nVert shader log: ' + gl.getShaderInfoLog(vs));
console.log('\nFrag shader log: ' + gl.getShaderInfoLog(fs));
}
ok(prog, 'Program should link.');
if (!prog) {
return;
}
prog.aVertCoord = gl.getAttribLocation(prog, 'aVertCoord');
prog.uFragColor = gl.getUniformLocation(prog, 'uFragColor');
gl.useProgram(prog);
// Test gl.bufferData(), gl.bufferSubData() and gl.readPixels() APIs with SAB as input.
var arr = new SharedArrayBuffer(8*4);
var view = new SharedFloat32Array(arr);
view.set(new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]));
var vb = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.bufferData(gl.ARRAY_BUFFER, arr, gl.STATIC_DRAW);
ok(gl.getError() == 0, 'bufferData with SAB as input parameter works ok.');
gl.bufferSubData(gl.ARRAY_BUFFER, 0, arr);
ok(gl.getError() == 0, 'bufferSubData with SAB as input parameter works ok.');
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
gl.clearColor(0, 0, 0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.uniform4f(prog.uFragColor, 0.2, 0.4, 0.6, 1.0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
var arr = new Uint8Array(4);
TestScreenColor(gl, 0.2, 0.4, 0.6, 1.0);
// Test gl.texImage2D() and gl.texSubImage2D() APIs with SAB as input.
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
var width = 4;
var height = 4;
var numChannels = 4;
var sab = new SharedArrayBuffer(width * height * numChannels);
var data = new SharedUint8Array(sab);
for (var i = 0; i < data.length; ++i) {
data[i] = i;
}
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
ok(gl.getError() == 0, 'texImage2D() with SAB as input parameter works ok.');
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
ok(gl.getError() == 0, 'texSubImage2D() with SAB as input parameter works ok.');
ok(gl.getError() == 0, 'Should be no errors after test.');
})();
// Test WebGL 2
(function() {
var canvas = document.getElementById('c2');
var attribs = {
antialias: false,
depth: false,
};
gl = canvas.getContext('webgl2', attribs);
if (!gl) {
todo(false, 'WebGL 2 is unavailable.');
return;
}
if (typeof SharedArrayBuffer === 'undefined') {
todo(false, 'SharedArrayBuffer is unavailable.');
return;
}
if (SharedFloat32Array === 'undefined') {
todo(false, 'SharedFloat32Array is unavailable.');
return;
}
var arr = new SharedArrayBuffer(8*4);
var view = new SharedFloat32Array(arr);
view.set(new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]));
var vb = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.bufferData(gl.ARRAY_BUFFER, arr, gl.STATIC_DRAW);
var arr2 = new SharedArrayBuffer(8*4);
gl.getBufferSubData(gl.ARRAY_BUFFER, 0, arr2);
var view2 = new SharedFloat32Array(arr2);
var equal = true;
for(var i = 0; i < 8; ++i) {
if (view[i] != view2[i]) equal = false;
}
ok(equal, 'getBufferSubData with SAB as input parameter works ok.');
// Test gl.texImage3D() and gl.texSubImage3D() APIs with SAB as input.
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, tex);
var width = 4;
var height = 4;
var depth = 4;
var numChannels = 4;
var sab = new SharedArrayBuffer(width * height * depth* numChannels);
var data = new SharedUint8Array(sab);
for (var i = 0; i < data.length; ++i) {
data[i] = i;
}
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
ok(gl.getError() == 0, 'texImage3D() with SAB as input parameter works ok.');
gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl.RGBA, gl.UNSIGNED_BYTE, data);
ok(gl.getError() == 0, 'texSubImage3D() with SAB as input parameter works ok.');
ok(gl.getError() == 0, 'Should be no errors after test.');
})();
ok(true, 'TEST COMPLETE');
</script>
</body>
</html>

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

@ -46,7 +46,7 @@ TextEncoder::Encode(JSContext* aCx,
// Run the steps of the encoding algorithm.
int32_t srcLen = aString.Length();
int32_t maxLen;
const char16_t* data = PromiseFlatString(aString).get();
const char16_t* data = aString.BeginReading();
nsresult rv = mEncoder->GetMaxLength(data, srcLen, &maxLen);
if (NS_FAILED(rv)) {
aRv.Throw(rv);

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

@ -1277,7 +1277,7 @@ nsresult HTMLMediaElement::LoadResource()
if (IsAutoplayEnabled()) {
mJoinLatency.Start();
}
return FinishDecoderSetup(decoder, resource, nullptr, nullptr);
return FinishDecoderSetup(decoder, resource, nullptr);
}
// determine what security checks need to be performed in AsyncOpen2().
@ -2777,7 +2777,7 @@ nsresult HTMLMediaElement::InitializeDecoderAsClone(MediaDecoder* aOriginal)
return NS_ERROR_FAILURE;
}
return FinishDecoderSetup(decoder, resource, nullptr, aOriginal);
return FinishDecoderSetup(decoder, resource, nullptr);
}
nsresult HTMLMediaElement::InitializeDecoderForChannel(nsIChannel* aChannel,
@ -2821,14 +2821,13 @@ nsresult HTMLMediaElement::InitializeDecoderForChannel(nsIChannel* aChannel,
}
return NS_OK;
} else {
return FinishDecoderSetup(decoder, resource, aListener, nullptr);
return FinishDecoderSetup(decoder, resource, aListener);
}
}
nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
MediaResource* aStream,
nsIStreamListener** aListener,
MediaDecoder* aCloneDonor)
nsIStreamListener** aListener)
{
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_LOADING);
@ -2858,7 +2857,7 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
// can affect how we feed data to MediaStreams
NotifyDecoderPrincipalChanged();
nsresult rv = aDecoder->Load(aListener, aCloneDonor);
nsresult rv = aDecoder->Load(aListener);
if (NS_FAILED(rv)) {
ShutdownDecoder();
LOG(LogLevel::Debug, ("%p Failed to load for decoder %p", this, aDecoder));

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

@ -651,7 +651,7 @@ public:
* A public wrapper for FinishDecoderSetup()
*/
nsresult FinishDecoderSetup(MediaDecoder* aDecoder, MediaResource* aStream) {
return FinishDecoderSetup(aDecoder, aStream, nullptr, nullptr);
return FinishDecoderSetup(aDecoder, aStream, nullptr);
}
// Returns true if the media element is being destroyed. Used in
@ -811,8 +811,7 @@ protected:
*/
nsresult FinishDecoderSetup(MediaDecoder* aDecoder,
MediaResource* aStream,
nsIStreamListener **aListener,
MediaDecoder* aCloneDonor);
nsIStreamListener **aListener);
/**
* Call this after setting up mLoadingSrc and mDecoder.

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

@ -69,20 +69,14 @@ HTMLOptGroupElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
}
nsIContent*
Element*
HTMLOptGroupElement::GetSelect()
{
nsIContent* parent = this;
while ((parent = parent->GetParent()) && parent->IsHTMLElement()) {
if (parent->IsHTMLElement(nsGkAtoms::select)) {
return parent;
}
if (!parent->IsHTMLElement(nsGkAtoms::optgroup)) {
break;
}
Element* parent = nsINode::GetParentElement();
if (!parent || !parent->IsHTMLElement(nsGkAtoms::select)) {
return nullptr;
}
return nullptr;
return parent;
}
nsresult

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

@ -76,7 +76,7 @@ protected:
* Get the select content element that contains this option
* @param aSelectElement the select element [OUT]
*/
nsIContent* GetSelect();
Element* GetSelect();
};
} // namespace dom

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

@ -226,7 +226,33 @@ HTMLSelectElement::InsertOptionsIntoList(nsIContent* aOptions,
bool aNotify)
{
int32_t insertIndex = aListIndex;
InsertOptionsIntoListRecurse(aOptions, &insertIndex, aDepth);
HTMLOptionElement* optElement = HTMLOptionElement::FromContent(aOptions);
if (optElement) {
mOptions->InsertOptionAt(optElement, insertIndex);
insertIndex++;
} else {
// If it's at the top level, then we just found out there are non-options
// at the top level, which will throw off the insert count
if (aDepth == 0) {
mNonOptionChildren++;
}
// Deal with optgroups
if (aOptions->IsHTMLElement(nsGkAtoms::optgroup)) {
mOptGroupCount++;
for (nsIContent* child = aOptions->GetFirstChild();
child;
child = child->GetNextSibling()) {
optElement = HTMLOptionElement::FromContent(child);
if (optElement) {
mOptions->InsertOptionAt(optElement, insertIndex);
insertIndex++;
}
}
}
}
// Deal with the selected list
if (insertIndex - aListIndex) {
@ -282,9 +308,40 @@ HTMLSelectElement::RemoveOptionsFromList(nsIContent* aOptions,
bool aNotify)
{
int32_t numRemoved = 0;
nsresult rv = RemoveOptionsFromListRecurse(aOptions, aListIndex, &numRemoved,
aDepth);
NS_ENSURE_SUCCESS(rv, rv);
HTMLOptionElement* optElement = HTMLOptionElement::FromContent(aOptions);
if (optElement) {
if (mOptions->ItemAsOption(aListIndex) != optElement) {
NS_ERROR("wrong option at index");
return NS_ERROR_UNEXPECTED;
}
mOptions->RemoveOptionAt(aListIndex);
numRemoved++;
} else {
// Yay, one less artifact at the top level.
if (aDepth == 0) {
mNonOptionChildren--;
}
// Recurse down deeper for options
if (mOptGroupCount && aOptions->IsHTMLElement(nsGkAtoms::optgroup)) {
mOptGroupCount--;
for (nsIContent* child = aOptions->GetFirstChild();
child;
child = child->GetNextSibling()) {
optElement = HTMLOptionElement::FromContent(child);
if (optElement) {
if (mOptions->ItemAsOption(aListIndex) != optElement) {
NS_ERROR("wrong option at index");
return NS_ERROR_UNEXPECTED;
}
mOptions->RemoveOptionAt(aListIndex);
numRemoved++;
}
}
}
}
if (numRemoved) {
// Tell the widget we removed the options
@ -324,91 +381,6 @@ HTMLSelectElement::RemoveOptionsFromList(nsIContent* aOptions,
return NS_OK;
}
// If the document is such that recursing over these options gets us
// deeper than four levels, there is something terribly wrong with the
// world.
void
HTMLSelectElement::InsertOptionsIntoListRecurse(nsIContent* aOptions,
int32_t* aInsertIndex,
int32_t aDepth)
{
// We *assume* here that someone's brain has not gone horribly
// wrong by putting <option> inside of <option>. I'm sorry, I'm
// just not going to look for an option inside of an option.
// Sue me.
HTMLOptionElement* optElement = HTMLOptionElement::FromContent(aOptions);
if (optElement) {
mOptions->InsertOptionAt(optElement, *aInsertIndex);
(*aInsertIndex)++;
return;
}
// If it's at the top level, then we just found out there are non-options
// at the top level, which will throw off the insert count
if (aDepth == 0) {
mNonOptionChildren++;
}
// Recurse down into optgroups
if (aOptions->IsHTMLElement(nsGkAtoms::optgroup)) {
mOptGroupCount++;
for (nsIContent* child = aOptions->GetFirstChild();
child;
child = child->GetNextSibling()) {
InsertOptionsIntoListRecurse(child, aInsertIndex, aDepth + 1);
}
}
}
// If the document is such that recursing over these options gets us deeper than
// four levels, there is something terribly wrong with the world.
nsresult
HTMLSelectElement::RemoveOptionsFromListRecurse(nsIContent* aOptions,
int32_t aRemoveIndex,
int32_t* aNumRemoved,
int32_t aDepth)
{
// We *assume* here that someone's brain has not gone horribly
// wrong by putting <option> inside of <option>. I'm sorry, I'm
// just not going to look for an option inside of an option.
// Sue me.
nsCOMPtr<nsIDOMHTMLOptionElement> optElement(do_QueryInterface(aOptions));
if (optElement) {
if (mOptions->ItemAsOption(aRemoveIndex) != optElement) {
NS_ERROR("wrong option at index");
return NS_ERROR_UNEXPECTED;
}
mOptions->RemoveOptionAt(aRemoveIndex);
(*aNumRemoved)++;
return NS_OK;
}
// Yay, one less artifact at the top level.
if (aDepth == 0) {
mNonOptionChildren--;
}
// Recurse down deeper for options
if (mOptGroupCount && aOptions->IsHTMLElement(nsGkAtoms::optgroup)) {
mOptGroupCount--;
for (nsIContent* child = aOptions->GetFirstChild();
child;
child = child->GetNextSibling()) {
nsresult rv = RemoveOptionsFromListRecurse(child,
aRemoveIndex,
aNumRemoved,
aDepth + 1);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return NS_OK;
}
// XXXldb Doing the processing before the content nodes have been added
// to the document (as the name of this function seems to require, and
// as the callers do), is highly unusual. Passing around unparented
@ -420,10 +392,10 @@ HTMLSelectElement::WillAddOptions(nsIContent* aOptions,
int32_t aContentIndex,
bool aNotify)
{
int32_t level = GetContentDepth(aParent);
if (level == -1) {
return NS_ERROR_FAILURE;
if (this != aParent && this != aParent->GetParent()) {
return NS_OK;
}
int32_t level = aParent == this ? 0 : 1;
// Get the index where the options will be inserted
int32_t ind = -1;
@ -462,11 +434,10 @@ HTMLSelectElement::WillRemoveOptions(nsIContent* aParent,
int32_t aContentIndex,
bool aNotify)
{
int32_t level = GetContentDepth(aParent);
NS_ASSERTION(level >= 0, "getting notified by unexpected content");
if (level == -1) {
return NS_ERROR_FAILURE;
if (this != aParent && this != aParent->GetParent()) {
return NS_OK;
}
int32_t level = this == aParent ? 0 : 1;
// Get the index where the options will be removed
nsIContent* currentKid = aParent->GetChildAt(aContentIndex);
@ -489,24 +460,6 @@ HTMLSelectElement::WillRemoveOptions(nsIContent* aParent,
return NS_OK;
}
int32_t
HTMLSelectElement::GetContentDepth(nsIContent* aContent)
{
nsIContent* content = aContent;
int32_t retval = 0;
while (content != this) {
retval++;
content = content->GetParent();
if (!content) {
retval = -1;
break;
}
}
return retval;
}
int32_t
HTMLSelectElement::GetOptionIndexAt(nsIContent* aOptions)
{
@ -528,9 +481,7 @@ HTMLSelectElement::GetOptionIndexAfter(nsIContent* aOptions)
// in the parent.
// - If it's not there, search for the first option after the parent.
if (aOptions == this) {
uint32_t len;
GetLength(&len);
return len;
return Length();
}
int32_t retval = -1;
@ -558,8 +509,6 @@ HTMLSelectElement::GetFirstOptionIndex(nsIContent* aOptions)
HTMLOptionElement* optElement = HTMLOptionElement::FromContent(aOptions);
if (optElement) {
GetOptionIndex(optElement, 0, true, &listIndex);
// If you nested stuff under the option, you're just plain
// screwed. *I'm* not going to aid and abet your evil deed.
return listIndex;
}
@ -1785,16 +1734,23 @@ HTMLSelectElement::DispatchContentReset()
}
static void
AddOptionsRecurse(nsIContent* aRoot, HTMLOptionsCollection* aArray)
AddOptions(nsIContent* aRoot, HTMLOptionsCollection* aArray)
{
for (nsIContent* cur = aRoot->GetFirstChild();
cur;
cur = cur->GetNextSibling()) {
HTMLOptionElement* opt = HTMLOptionElement::FromContent(cur);
for (nsIContent* child = aRoot->GetFirstChild();
child;
child = child->GetNextSibling()) {
HTMLOptionElement* opt = HTMLOptionElement::FromContent(child);
if (opt) {
aArray->AppendOption(opt);
} else if (cur->IsHTMLElement(nsGkAtoms::optgroup)) {
AddOptionsRecurse(cur, aArray);
} else if (child->IsHTMLElement(nsGkAtoms::optgroup)) {
for (nsIContent* grandchild = child->GetFirstChild();
grandchild;
grandchild = grandchild->GetNextSibling()) {
opt = HTMLOptionElement::FromContent(grandchild);
if (opt) {
aArray->AppendOption(opt);
}
}
}
}
}
@ -1803,7 +1759,7 @@ void
HTMLSelectElement::RebuildOptionsArray(bool aNotify)
{
mOptions->Clear();
AddOptionsRecurse(this, mOptions);
AddOptions(this, mOptions);
FindSelectedIndex(0, aNotify);
}
@ -1863,28 +1819,29 @@ HTMLSelectElement::GetValidationMessage(nsAString& aValidationMessage,
#ifdef DEBUG
static void
VerifyOptionsRecurse(nsIContent* aRoot, int32_t& aIndex,
HTMLOptionsCollection* aArray)
{
for (nsIContent* cur = aRoot->GetFirstChild();
cur;
cur = cur->GetNextSibling()) {
nsCOMPtr<nsIDOMHTMLOptionElement> opt = do_QueryInterface(cur);
if (opt) {
NS_ASSERTION(opt == aArray->ItemAsOption(aIndex++),
"Options collection broken");
} else if (cur->IsHTMLElement(nsGkAtoms::optgroup)) {
VerifyOptionsRecurse(cur, aIndex, aArray);
}
}
}
void
HTMLSelectElement::VerifyOptionsArray()
{
int32_t aIndex = 0;
VerifyOptionsRecurse(this, aIndex, mOptions);
int32_t index = 0;
for (nsIContent* child = nsINode::GetFirstChild();
child;
child = child->GetNextSibling()) {
HTMLOptionElement* opt = HTMLOptionElement::FromContent(child);
if (opt) {
NS_ASSERTION(opt == mOptions->ItemAsOption(index++),
"Options collection broken");
} else if (child->IsHTMLElement(nsGkAtoms::optgroup)) {
for (nsIContent* grandchild = child->GetFirstChild();
grandchild;
grandchild = grandchild->GetNextSibling()) {
opt = HTMLOptionElement::FromContent(grandchild);
if (opt) {
NS_ASSERTION(opt == mOptions->ItemAsOption(index++),
"Options collection broken");
}
}
}
}
}
#endif

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

@ -502,37 +502,11 @@ protected:
int32_t aListIndex,
int32_t aDepth,
bool aNotify);
/**
* Insert option(s) into the options[] array (called by InsertOptionsIntoList)
* @param aOptions the option or optgroup being added
* @param aInsertIndex the index to start adding options into the list at
* @param aDepth the depth of aOptions (1=direct child of select ...)
*/
void InsertOptionsIntoListRecurse(nsIContent* aOptions,
int32_t* aInsertIndex,
int32_t aDepth);
/**
* Remove option(s) from the options[] array (called by RemoveOptionsFromList)
* @param aOptions the option or optgroup being added
* @param aListIndex the index to start removing options from the list at
* @param aNumRemoved the number removed so far [OUT]
* @param aDepth the depth of aOptions (1=direct child of select ...)
*/
nsresult RemoveOptionsFromListRecurse(nsIContent* aOptions,
int32_t aRemoveIndex,
int32_t* aNumRemoved,
int32_t aDepth);
// nsIConstraintValidation
void UpdateBarredFromConstraintValidation();
bool IsValueMissing();
/**
* Find out how deep this content is from the select (1=direct child)
* @param aContent the content to check
* @return the depth
*/
int32_t GetContentDepth(nsIContent* aContent);
/**
* Get the index of the first option at, under or following the content in
* the select, or length of options[] if none are found

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

@ -4567,7 +4567,7 @@ ContentParent::DoLoadMessageManagerScript(const nsAString& aURL,
return SendLoadProcessScript(nsString(aURL));
}
bool
nsresult
ContentParent::DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aHelper,
@ -4576,18 +4576,21 @@ ContentParent::DoSendAsyncMessage(JSContext* aCx,
{
ClonedMessageData data;
if (!BuildClonedMessageDataForParent(this, aHelper, data)) {
return false;
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
InfallibleTArray<CpowEntry> cpows;
jsipc::CPOWManager* mgr = GetCPOWManager();
if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) {
return false;
return NS_ERROR_UNEXPECTED;
}
if (IsReadyNuwaProcess()) {
// Nuwa won't receive frame messages after it is frozen.
return true;
return NS_OK;
}
return SendAsyncMessage(nsString(aMessage), data, cpows, Principal(aPrincipal));
if (!SendAsyncMessage(nsString(aMessage), data, cpows, Principal(aPrincipal))) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
bool

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

@ -206,11 +206,11 @@ public:
*/
virtual bool DoLoadMessageManagerScript(const nsAString& aURL,
bool aRunInGlobalScope) override;
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override;
virtual nsresult DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override;
virtual bool CheckPermission(const nsAString& aPermission) override;
virtual bool CheckManifestURL(const nsAString& aManifestURL) override;
virtual bool CheckAppHasPermission(const nsAString& aPermission) override;

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

@ -2921,7 +2921,7 @@ TabChild::DoSendBlockingMessage(JSContext* aCx,
Principal(aPrincipal), aRetVal);
}
bool
nsresult
TabChild::DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
@ -2930,14 +2930,17 @@ TabChild::DoSendAsyncMessage(JSContext* aCx,
{
ClonedMessageData data;
if (!BuildClonedMessageDataForChild(Manager(), aData, data)) {
return false;
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
InfallibleTArray<CpowEntry> cpows;
if (aCpows && !Manager()->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
return NS_ERROR_UNEXPECTED;
}
return SendAsyncMessage(PromiseFlatString(aMessage), data, cpows,
Principal(aPrincipal));
if (!SendAsyncMessage(PromiseFlatString(aMessage), data, cpows,
Principal(aPrincipal))) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
TabChild*

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

@ -280,11 +280,11 @@ public:
nsIPrincipal* aPrincipal,
nsTArray<StructuredCloneData>* aRetVal,
bool aIsSync) override;
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override;
virtual nsresult DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override;
virtual bool DoUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const Maybe<ZoomConstraints>& aConstraints) override;

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

@ -1454,6 +1454,9 @@ TabParent::GetTopLevelDocAccessible() const
return doc;
}
}
MOZ_ASSERT(docCount == 0, "If there isn't a top level accessible doc "
"there shouldn't be an accessible doc at all!");
#endif
return nullptr;
}

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

@ -509,8 +509,7 @@ MediaDecoder::OpenResource(nsIStreamListener** aStreamListener)
}
nsresult
MediaDecoder::Load(nsIStreamListener** aStreamListener,
MediaDecoder* aCloneDonor)
MediaDecoder::Load(nsIStreamListener** aStreamListener)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mResource, "Can't load without a MediaResource");
@ -521,18 +520,16 @@ MediaDecoder::Load(nsIStreamListener** aStreamListener,
SetStateMachine(CreateStateMachine());
NS_ENSURE_TRUE(GetStateMachine(), NS_ERROR_FAILURE);
return InitializeStateMachine(aCloneDonor);
return InitializeStateMachine();
}
nsresult
MediaDecoder::InitializeStateMachine(MediaDecoder* aCloneDonor)
MediaDecoder::InitializeStateMachine()
{
MOZ_ASSERT(NS_IsMainThread());
NS_ASSERTION(mDecoderStateMachine, "Cannot initialize null state machine!");
MediaDecoder* cloneDonor = static_cast<MediaDecoder*>(aCloneDonor);
nsresult rv = mDecoderStateMachine->Init(
cloneDonor ? cloneDonor->mDecoderStateMachine.get() : nullptr);
nsresult rv = mDecoderStateMachine->Init();
NS_ENSURE_SUCCESS(rv, rv);
// If some parameters got set before the state machine got created,

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

@ -323,8 +323,7 @@ public:
// Start downloading the media. Decode the downloaded data up to the
// point of the first frame of data.
// This is called at most once per decoder, after Init().
virtual nsresult Load(nsIStreamListener** aListener,
MediaDecoder* aCloneDonor);
virtual nsresult Load(nsIStreamListener** aListener);
// Called in |Load| to open mResource.
nsresult OpenResource(nsIStreamListener** aStreamListener);
@ -363,7 +362,7 @@ public:
virtual nsresult Seek(double aTime, SeekTarget::Type aSeekType);
// Initialize state machine and schedule it.
nsresult InitializeStateMachine(MediaDecoder* aCloneDonor);
nsresult InitializeStateMachine();
// Start playback of a video. 'Load' must have previously been
// called.

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

@ -96,7 +96,28 @@ public:
// Release media resources they should be released in dormant state
// The reader can be made usable again by calling ReadMetadata().
virtual void ReleaseMediaResources() {};
void ReleaseMediaResources()
{
if (OnTaskQueue()) {
ReleaseMediaResourcesInternal();
return;
}
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
this, &MediaDecoderReader::ReleaseMediaResourcesInternal);
OwnerThread()->Dispatch(r.forget());
}
void DisableHardwareAcceleration()
{
if (OnTaskQueue()) {
DisableHardwareAccelerationInternal();
return;
}
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
this, &MediaDecoderReader::DisableHardwareAccelerationInternal);
OwnerThread()->Dispatch(r.forget());
}
// Breaks reference-counted cycles. Called during shutdown.
// WARNING: If you override this, you must call the base implementation
// in your override.
@ -243,6 +264,10 @@ public:
virtual size_t SizeOfVideoQueueInFrames();
virtual size_t SizeOfAudioQueueInFrames();
private:
virtual void ReleaseMediaResourcesInternal() {}
virtual void DisableHardwareAccelerationInternal() {}
protected:
friend class TrackBuffer;
virtual void NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset) { }
@ -322,8 +347,6 @@ public:
// decoding.
virtual bool VideoIsHardwareAccelerated() const { return false; }
virtual void DisableHardwareAcceleration() {}
TimedMetadataEventSource& TimedMetadataEvent() {
return mTimedMetadataEvent;
}

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

@ -1030,7 +1030,7 @@ bool MediaDecoderStateMachine::IsPlaying() const
return mMediaSink->IsPlaying();
}
nsresult MediaDecoderStateMachine::Init(MediaDecoderStateMachine* aCloneDonor)
nsresult MediaDecoderStateMachine::Init()
{
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = mReader->Init();
@ -1269,8 +1269,7 @@ MediaDecoderStateMachine::SetDormant(bool aDormant)
// that run after ResetDecode are supposed to run with a clean slate. We rely
// on that in other places (i.e. seeking), so it seems reasonable to rely on
// it here as well.
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(mReader, &MediaDecoderReader::ReleaseMediaResources);
DecodeTaskQueue()->Dispatch(r.forget());
mReader->ReleaseMediaResources();
} else if ((aDormant != true) && (mState == DECODER_STATE_DORMANT)) {
ScheduleStateMachine();
mDecodingFirstFrame = true;
@ -2464,9 +2463,7 @@ MediaDecoderStateMachine::CheckFrameValidity(VideoData* aData)
if (mReader->VideoIsHardwareAccelerated() &&
frameStats.GetPresentedFrames() > 60 &&
mCorruptFrames.mean() >= 2 /* 20% */) {
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableMethod(mReader, &MediaDecoderReader::DisableHardwareAcceleration);
DecodeTaskQueue()->Dispatch(task.forget());
mReader->DisableHardwareAcceleration();
mCorruptFrames.clear();
gfxCriticalNote << "Too many dropped/corrupted frames, disabling DXVA";
}

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

@ -134,7 +134,7 @@ public:
MediaDecoderReader* aReader,
bool aRealTime = false);
nsresult Init(MediaDecoderStateMachine* aCloneDonor);
nsresult Init();
// Enumeration for the valid decoding states
enum State {

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

@ -534,7 +534,7 @@ MediaFormatReader::GetDecoderData(TrackType aTrack)
}
void
MediaFormatReader::DisableHardwareAcceleration()
MediaFormatReader::DisableHardwareAccelerationInternal()
{
MOZ_ASSERT(OnTaskQueue());
if (HasVideo() && !mHardwareAccelerationDisabled) {
@ -1569,8 +1569,9 @@ MediaFormatReader::GetBuffered()
return intervals.Shift(media::TimeUnit::FromMicroseconds(-startTime));
}
void MediaFormatReader::ReleaseMediaResources()
void MediaFormatReader::ReleaseMediaResourcesInternal()
{
MOZ_ASSERT(OnTaskQueue());
// Before freeing a video codec, all video buffers needed to be released
// even from graphics pipeline.
VideoFrameContainer* container =

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

@ -70,9 +70,6 @@ public:
virtual bool ForceZeroStartTime() const override;
// For Media Resource Management
void ReleaseMediaResources() override;
nsresult ResetDecode() override;
nsRefPtr<ShutdownPromise> Shutdown() override;
@ -81,8 +78,6 @@ public:
bool VideoIsHardwareAccelerated() const override;
void DisableHardwareAcceleration() override;
bool IsWaitForDataSupported() override { return true; }
nsRefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType) override;
@ -436,6 +431,11 @@ private:
#if defined(READER_DORMANT_HEURISTIC)
const bool mDormantEnabled;
#endif
private:
// For Media Resource Management
void ReleaseMediaResourcesInternal() override;
void DisableHardwareAccelerationInternal() override;
};
} // namespace mozilla

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

@ -315,7 +315,7 @@ MediaKeySession::Close(ErrorResult& aRv)
return promise.forget();
}
PromiseId pid = mKeys->StorePromise(promise);
mKeys->GetCDMProxy()->CloseSession(mSessionId, mKeys->StorePromise(promise));
mKeys->GetCDMProxy()->CloseSession(mSessionId, pid);
EME_LOG("MediaKeySession[%p,'%s'] Close() sent to CDM, promiseId=%d",
this, NS_ConvertUTF16toUTF8(mSessionId).get(), pid);

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

@ -180,6 +180,13 @@ MediaKeys::StorePromise(DetailedPromise* aPromise)
// promises are rejected in Shutdown().
AddRef();
#ifdef DEBUG
// We should not have already stored this promise!
for (auto iter = mPromises.ConstIter(); !iter.Done(); iter.Next()) {
MOZ_ASSERT(iter.Data() != aPromise);
}
#endif
mPromises.Put(id, aPromise);
return id;
}
@ -274,6 +281,7 @@ MediaKeys::ResolvePromise(PromiseId aId)
} else {
promise->MaybeResolve(JS::UndefinedHandleValue);
}
MOZ_ASSERT(!mPromises.Contains(aId));
}
already_AddRefed<DetailedPromise>

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

@ -599,21 +599,10 @@ GMPChild::GetGMPStorage()
return mStorage;
}
static MOZ_NEVER_INLINE void
CrashForApiTimeout()
{
// Never inline so that crash reports are distinctive.
MOZ_CRASH("Bug 1209385; GMP API actor failed to respond.");
}
bool
GMPChild::RecvCrashPluginNow(const GMPCrashReason& aReason)
GMPChild::RecvCrashPluginNow()
{
if (aReason == kGmpApiTimeout) {
CrashForApiTimeout();
} else {
MOZ_CRASH();
}
MOZ_CRASH();
return true;
}

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

@ -71,7 +71,7 @@ private:
ProcessId aOtherPid) override;
void GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild);
virtual bool RecvCrashPluginNow(const GMPCrashReason& aReason) override;
virtual bool RecvCrashPluginNow() override;
virtual bool RecvBeginAsyncShutdown() override;
virtual bool RecvCloseActive() override;

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

@ -118,18 +118,6 @@ GMPContentParent::DecryptorDestroyed(GMPDecryptorParent* aSession)
CloseIfUnused();
}
void
GMPContentParent::CrashPluginNow(GMPCrashReason aReason)
{
if (mParent) {
mParent->Crash(aReason);
} else {
nsRefPtr<GeckoMediaPluginServiceChild> gmp(
GeckoMediaPluginServiceChild::GetSingleton());
gmp->CrashPluginNow(mPluginId, aReason);
}
}
void
GMPContentParent::CloseIfUnused()
{

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

@ -9,7 +9,6 @@
#include "mozilla/gmp/PGMPContentParent.h"
#include "GMPSharedMemManager.h"
#include "nsISupportsImpl.h"
#include "GMPUtils.h"
namespace mozilla {
namespace gmp {
@ -62,8 +61,6 @@ public:
return mPluginId;
}
void CrashPluginNow(GMPCrashReason aReason);
private:
~GMPContentParent();

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

@ -11,8 +11,6 @@
#include "gmp-audio-codec.h"
#include "gmp-decryption.h"
#include "GMPUtils.h"
namespace IPC {
template <>
@ -249,13 +247,6 @@ struct ParamTraits<GMPVideoCodec>
}
};
template <>
struct ParamTraits<mozilla::GMPCrashReason>
: public ContiguousEnumSerializer<mozilla::GMPCrashReason,
mozilla::kPrefChange,
mozilla::kInvalid>
{};
} // namespace IPC
#endif // GMPMessageUtils_h_

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

@ -119,10 +119,10 @@ GMPParent::Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir)
}
void
GMPParent::Crash(GMPCrashReason aReason)
GMPParent::Crash()
{
if (mState != GMPStateNotLoaded) {
unused << SendCrashPluginNow(aReason);
unused << SendCrashPluginNow();
}
}

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

@ -22,7 +22,6 @@
#include "nsTArray.h"
#include "nsIFile.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
#include "GMPUtils.h"
class nsIThread;
@ -80,7 +79,7 @@ public:
nsresult Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir);
nsresult CloneFrom(const GMPParent* aOther);
void Crash(GMPCrashReason aReason);
void Crash();
nsresult LoadProcess();

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

@ -215,38 +215,6 @@ GeckoMediaPluginServiceChild::UpdateTrialCreateState(const nsAString& aKeySystem
return NS_OK;
}
void
GeckoMediaPluginServiceChild::CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason)
{
if (NS_GetCurrentThread() != mGMPThread) {
mGMPThread->Dispatch(NS_NewRunnableMethodWithArgs<uint32_t, GMPCrashReason>(
this, &GeckoMediaPluginServiceChild::CrashPluginNow,
aPluginId, aReason), NS_DISPATCH_NORMAL);
return;
}
class Callback : public GetServiceChildCallback
{
public:
Callback(uint32_t aPluginId, GMPCrashReason aReason)
: mPluginId(aPluginId)
, mReason(aReason)
{ }
virtual void Done(GMPServiceChild* aService) override
{
aService->SendCrashPluginNow(mPluginId, mReason);
}
private:
uint32_t mPluginId;
GMPCrashReason mReason;
};
UniquePtr<GetServiceChildCallback> callback(new Callback(aPluginId, aReason));
GetServiceChild(Move(callback));
}
NS_IMETHODIMP
GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject,
const char* aTopic,

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

@ -11,7 +11,6 @@
#include "mozilla/ipc/Transport.h"
#include "mozilla/gmp/PGMPServiceChild.h"
#include "nsRefPtrHashtable.h"
#include "GMPUtils.h"
namespace mozilla {
namespace gmp {
@ -53,8 +52,6 @@ public:
NS_IMETHOD UpdateTrialCreateState(const nsAString& aKeySystem,
uint32_t aState) override;
void CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason);
NS_DECL_NSIOBSERVER
void SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild);

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

@ -84,7 +84,6 @@ NS_IMPL_ISUPPORTS_INHERITED(GeckoMediaPluginServiceParent,
static int32_t sMaxAsyncShutdownWaitMs = 0;
static bool sHaveSetTimeoutPrefCache = false;
static bool sKillHungPlugins = true;
GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent()
: mShuttingDown(false)
@ -100,9 +99,6 @@ GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent()
Preferences::AddIntVarCache(&sMaxAsyncShutdownWaitMs,
"media.gmp.async-shutdown-timeout",
GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT);
Preferences::AddBoolVarCache(&sKillHungPlugins,
"media.gmp.kill-hung-plugins",
true);
}
}
@ -668,7 +664,7 @@ GeckoMediaPluginServiceParent::CrashPlugins()
MutexAutoLock lock(mMutex);
for (size_t i = 0; i < mPlugins.Length(); i++) {
mPlugins[i]->Crash(kPrefChange);
mPlugins[i]->Crash();
}
}
@ -1378,24 +1374,6 @@ GeckoMediaPluginServiceParent::UpdateTrialCreateState(const nsAString& aKeySyste
#endif
}
void
GeckoMediaPluginServiceParent::CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
if (aReason == kGmpApiTimeout && !sKillHungPlugins) {
LOGD(("%s::%s(%u, %u) but killing hung plugins disabled.",
__CLASS__, __FUNCTION__, aPluginId, aReason));
return;
}
LOGD(("%s::%s(%u, %u)", __CLASS__, __FUNCTION__, aPluginId, aReason));
MutexAutoLock lock(mMutex);
for (const auto& plugin : mPlugins) {
if (plugin->GetPluginId() == aPluginId) {
plugin->Crash(aReason);
}
}
}
static bool
ExtractHostName(const nsACString& aOrigin, nsACString& aOutData)
{
@ -1730,14 +1708,6 @@ GMPServiceParent::~GMPServiceParent()
new DeleteTask<Transport>(GetTransport()));
}
bool
GMPServiceParent::RecvCrashPluginNow(const uint32_t& aPluginId,
const GMPCrashReason& aReason)
{
mService->CrashPluginNow(aPluginId, aReason);
return true;
}
bool
GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId,
const nsCString& aAPI,

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

@ -13,7 +13,6 @@
#include "nsDataHashtable.h"
#include "mozilla/Atomics.h"
#include "nsThreadUtils.h"
#include "GMPUtils.h"
template <class> struct already_AddRefed;
@ -58,8 +57,6 @@ public:
void SetAsyncShutdownPluginState(GMPParent* aGMPParent, char aId, const nsCString& aState);
#endif // MOZ_CRASHREPORTER
void CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason);
private:
friend class GMPServiceParent;
@ -226,8 +223,6 @@ public:
nsCString* aVersion);
virtual bool RecvUpdateGMPTrialCreateState(const nsString& aKeySystem,
const uint32_t& aState) override;
virtual bool RecvCrashPluginNow(const uint32_t& aPluginId,
const GMPCrashReason& aReason) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;

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

@ -37,12 +37,6 @@ SplitAt(const char* aDelims,
nsCString
ToBase64(const nsTArray<uint8_t>& aBytes);
enum GMPCrashReason {
kPrefChange, // media.gmp.plugin.crash has been toggled.
kGmpApiTimeout, // Some API did not respond.
kInvalid,
};
bool
FileExists(nsIFile* aFile);

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

@ -188,7 +188,6 @@ GMPVideoDecoderParent::Reset()
LOGD(("GMPVideoDecoderParent[%p]::ResetCompleteTimeout() timed out waiting for ResetComplete", self.get()));
self->mResetCompleteTimeout = nullptr;
LogToBrowserConsole(NS_LITERAL_STRING("GMPVideoDecoderParent timed out waiting for ResetComplete()"));
self->mPlugin->CrashPluginNow(kGmpApiTimeout);
});
CancelResetCompleteTimeout();
mResetCompleteTimeout = SimpleTimer::Create(task, 5000, mPlugin->GMPThread());

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

@ -9,7 +9,6 @@ include protocol PGMPTimer;
include protocol PGMPStorage;
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
using mozilla::GMPCrashReason from "GMPUtils.h";
namespace mozilla {
namespace gmp {
@ -34,7 +33,7 @@ parent:
child:
async BeginAsyncShutdown();
async CrashPluginNow(GMPCrashReason aReason);
async CrashPluginNow();
intr StartPlugin();
async SetNodeId(nsCString nodeId);
async CloseActive();

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

@ -6,7 +6,6 @@
include protocol PGMP;
using base::ProcessId from "base/process.h";
using mozilla::GMPCrashReason from "GMPUtils.h";
namespace mozilla {
namespace gmp {
@ -24,8 +23,6 @@ parent:
returns (nsCString id);
async UpdateGMPTrialCreateState(nsString keySystem, uint32_t status);
async CrashPluginNow(uint32_t pluginId, GMPCrashReason aReason);
};
} // namespace gmp

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

@ -51,7 +51,7 @@ MediaSourceDecoder::CreateStateMachine()
}
nsresult
MediaSourceDecoder::Load(nsIStreamListener**, MediaDecoder*)
MediaSourceDecoder::Load(nsIStreamListener**)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!GetStateMachine());
@ -61,7 +61,7 @@ MediaSourceDecoder::Load(nsIStreamListener**, MediaDecoder*)
return NS_ERROR_FAILURE;
}
nsresult rv = GetStateMachine()->Init(nullptr);
nsresult rv = GetStateMachine()->Init();
NS_ENSURE_SUCCESS(rv, rv);
SetStateMachineParameters();

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

@ -38,7 +38,7 @@ public:
virtual MediaDecoder* Clone() override;
virtual MediaDecoderStateMachine* CreateStateMachine() override;
virtual nsresult Load(nsIStreamListener**, MediaDecoder*) override;
virtual nsresult Load(nsIStreamListener**) override;
virtual media::TimeIntervals GetSeekable() override;
media::TimeIntervals GetBuffered() override;

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

@ -284,8 +284,10 @@ MediaCodecReader::~MediaCodecReader()
}
void
MediaCodecReader::ReleaseMediaResources()
MediaCodecReader::ReleaseMediaResourcesInternal()
{
MOZ_ASSERT(OnTaskQueue());
// Stop the mSource because we are in the dormant state and the stop function
// will rewind the mSource to the beginning of the stream.
if (mVideoTrack.mSource != nullptr && !mVideoTrack.mSourceIsStopped) {

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

@ -60,9 +60,6 @@ public:
MediaCodecReader(AbstractMediaDecoder* aDecoder);
virtual ~MediaCodecReader();
// Release media resources they should be released in dormant state
virtual void ReleaseMediaResources();
// Destroys the decoding state. The reader cannot be made usable again.
// This is different from ReleaseMediaResources() as Shutdown() is
// irreversible, whereas ReleaseMediaResources() is reversible.
@ -436,6 +433,10 @@ private:
nsTArray<ReleaseItem> mPendingReleaseItems;
NotifyDataArrivedFilter mFilter;
private:
// Release media resources they should be released in dormant state
virtual void ReleaseMediaResourcesInternal() override;
};
} // namespace mozilla

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

@ -170,8 +170,10 @@ MediaOmxReader::Shutdown()
return p;
}
void MediaOmxReader::ReleaseMediaResources()
void MediaOmxReader::ReleaseMediaResourcesInternal()
{
MOZ_ASSERT(OnTaskQueue());
mMediaResourceRequest.DisconnectIfExists();
mMetadataPromise.RejectIfExists(ReadMetadataFailureReason::METADATA_ERROR, __func__);

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

@ -95,8 +95,6 @@ public:
return mHasVideo;
}
virtual void ReleaseMediaResources();
virtual nsRefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata() override;
virtual nsRefPtr<SeekPromise>
@ -118,6 +116,8 @@ private:
class ProcessCachedDataTask;
class NotifyDataArrivedRunnable;
virtual void ReleaseMediaResourcesInternal() override;
bool IsShutdown() {
MutexAutoLock lock(mShutdownMutex);
return mIsShutdown;

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

@ -14,6 +14,7 @@
#include "mozilla/Logging.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "nsThreadUtils.h"
#include "nsXPCOM.h"
#undef LOG
#undef LOG_ENABLED
@ -142,6 +143,79 @@ private:
int mResult;
};
NS_IMPL_ISUPPORTS(CamerasParent, nsIObserver)
NS_IMETHODIMP
CamerasParent::Observe(nsISupports *aSubject,
const char *aTopic,
const char16_t *aData)
{
MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID));
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
MOZ_ASSERT(obs);
obs->RemoveObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID);
StopVideoCapture();
return NS_OK;
}
nsresult
CamerasParent::DispatchToVideoCaptureThread(nsRunnable *event)
{
MonitorAutoLock lock(mThreadMonitor);
while(mChildIsAlive && mWebRTCAlive &&
(!mVideoCaptureThread || !mVideoCaptureThread->IsRunning())) {
mThreadMonitor.Wait();
}
if (!mVideoCaptureThread || !mVideoCaptureThread->IsRunning()) {
return NS_ERROR_FAILURE;
}
mVideoCaptureThread->message_loop()->PostTask(FROM_HERE,
new RunnableTask(event));
return NS_OK;
}
void
CamerasParent::StopVideoCapture()
{
// We are called from the main thread (xpcom-shutdown) or
// from PBackground (when the Actor shuts down).
// Shut down the WebRTC stack (on the capture thread)
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self]() -> nsresult {
MonitorAutoLock lock(self->mThreadMonitor);
self->CloseEngines();
self->mThreadMonitor.NotifyAll();
return NS_OK;
});
DispatchToVideoCaptureThread(webrtc_runnable);
// Hold here until the WebRTC thread is gone. We need to dispatch
// the thread deletion *now*, or there will be no more possibility
// to get to the main thread.
MonitorAutoLock lock(mThreadMonitor);
while (mWebRTCAlive) {
mThreadMonitor.Wait();
}
// After closing the WebRTC stack, clean up the
// VideoCapture thread.
if (self->mVideoCaptureThread) {
base::Thread *thread = self->mVideoCaptureThread;
self->mVideoCaptureThread = nullptr;
nsRefPtr<nsRunnable> threadShutdown =
media::NewRunnableFrom([thread]() -> nsresult {
if (thread->IsRunning()) {
thread->Stop();
}
delete thread;
return NS_OK;
});
if (NS_FAILED(NS_DispatchToMainThread(threadShutdown))) {
LOG(("Could not dispatch VideoCaptureThread destruction"));
}
}
}
int
CamerasParent::DeliverFrameOverIPC(CaptureEngine cap_engine,
int cap_id,
@ -235,6 +309,7 @@ CamerasParent::RecvReleaseFrame(mozilla::ipc::Shmem&& s) {
bool
CamerasParent::SetupEngine(CaptureEngine aCapEngine)
{
MOZ_ASSERT(mVideoCaptureThread->thread_id() == PlatformThread::CurrentId());
EngineHelper *helper = &mEngines[aCapEngine];
// Already initialized
@ -308,51 +383,57 @@ CamerasParent::SetupEngine(CaptureEngine aCapEngine)
void
CamerasParent::CloseEngines()
{
{
MutexAutoLock lock(mCallbackMutex);
// Stop the callers
while (mCallbacks.Length()) {
auto capEngine = mCallbacks[0]->mCapEngine;
auto capNum = mCallbacks[0]->mCapturerId;
LOG(("Forcing shutdown of engine %d, capturer %d", capEngine, capNum));
{
MutexAutoUnlock unlock(mCallbackMutex);
RecvStopCapture(capEngine, capNum);
RecvReleaseCaptureDevice(capEngine, capNum);
}
// The callbacks list might have changed while we released the lock,
// but note that due to the loop construct this will not break us.
if (!mWebRTCAlive) {
return;
}
MOZ_ASSERT(mVideoCaptureThread->thread_id() == PlatformThread::CurrentId());
// Stop the callers
while (mCallbacks.Length()) {
auto capEngine = mCallbacks[0]->mCapEngine;
auto capNum = mCallbacks[0]->mCapturerId;
LOG(("Forcing shutdown of engine %d, capturer %d", capEngine, capNum));
RecvStopCapture(capEngine, capNum);
RecvReleaseCaptureDevice(capEngine, capNum);
}
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
if (mEngines[i].mEngineIsRunning) {
LOG(("Being closed down while engine %d is running!", i));
}
if (mEngines[i].mPtrViERender) {
mEngines[i].mPtrViERender->Release();
mEngines[i].mPtrViERender = nullptr;
}
if (mEngines[i].mPtrViECapture) {
mEngines[i].mPtrViECapture->Release();
mEngines[i].mPtrViECapture = nullptr;
}
if(mEngines[i].mPtrViEBase) {
mEngines[i].mPtrViEBase->Release();
mEngines[i].mPtrViEBase = nullptr;
}
if (mEngines[i].mEngine) {
mEngines[i].mEngine->SetTraceCallback(nullptr);
webrtc::VideoEngine::Delete(mEngines[i].mEngine);
mEngines[i].mEngine = nullptr;
}
}
{
MutexAutoLock lock(mEngineMutex);
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
if (mEngines[i].mEngineIsRunning) {
LOG(("Being closed down while engine %d is running!", i));
}
if (mEngines[i].mPtrViERender) {
mEngines[i].mPtrViERender->Release();
mEngines[i].mPtrViERender = nullptr;
}
if (mEngines[i].mPtrViECapture) {
mEngines[i].mPtrViECapture->Release();
mEngines[i].mPtrViECapture = nullptr;
}
if(mEngines[i].mPtrViEBase) {
mEngines[i].mPtrViEBase->Release();
mEngines[i].mPtrViEBase = nullptr;
}
}
}
mWebRTCAlive = false;
}
bool
CamerasParent::EnsureInitialized(int aEngine)
{
LOG((__PRETTY_FUNCTION__));
// We're shutting down, don't try to do new WebRTC ops.
if (!mWebRTCAlive) {
return false;
}
CaptureEngine capEngine = static_cast<CaptureEngine>(aEngine);
if (!SetupEngine(capEngine)) {
LOG(("CamerasParent failed to initialize engine"));
return false;
}
@ -368,18 +449,12 @@ bool
CamerasParent::RecvNumberOfCaptureDevices(const int& aCapEngine)
{
LOG((__PRETTY_FUNCTION__));
if (!EnsureInitialized(aCapEngine)) {
LOG(("RecvNumberOfCaptureDevices fails to initialize"));
unused << SendReplyFailure();
return false;
}
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine]() -> nsresult {
MutexAutoLock lock(self->mEngineMutex);
int num = -1;
if (self->mEngines[aCapEngine].mPtrViECapture) {
if (self->EnsureInitialized(aCapEngine)) {
num = self->mEngines[aCapEngine].mPtrViECapture->NumberOfCaptureDevices();
}
nsRefPtr<nsIRunnable> ipc_runnable =
@ -400,8 +475,7 @@ CamerasParent::RecvNumberOfCaptureDevices(const int& aCapEngine)
self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
return NS_OK;
});
mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
DispatchToVideoCaptureThread(webrtc_runnable);
return true;
}
@ -410,19 +484,13 @@ CamerasParent::RecvNumberOfCapabilities(const int& aCapEngine,
const nsCString& unique_id)
{
LOG((__PRETTY_FUNCTION__));
if (!EnsureInitialized(aCapEngine)) {
LOG(("RecvNumberOfCapabilities fails to initialize"));
unused << SendReplyFailure();
return false;
}
LOG(("Getting caps for %s", unique_id.get()));
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, unique_id, aCapEngine]() -> nsresult {
MutexAutoLock lock(self->mEngineMutex);
int num = -1;
if (self->mEngines[aCapEngine].mPtrViECapture) {
if (self->EnsureInitialized(aCapEngine)) {
num =
self->mEngines[aCapEngine].mPtrViECapture->NumberOfCapabilities(
unique_id.get(),
@ -446,7 +514,7 @@ CamerasParent::RecvNumberOfCapabilities(const int& aCapEngine,
self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
return NS_OK;
});
mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
DispatchToVideoCaptureThread(webrtc_runnable);
return true;
}
@ -456,21 +524,14 @@ CamerasParent::RecvGetCaptureCapability(const int &aCapEngine,
const int& num)
{
LOG((__PRETTY_FUNCTION__));
if (!EnsureInitialized(aCapEngine)) {
LOG(("Fails to initialize"));
unused << SendReplyFailure();
return false;
}
LOG(("RecvGetCaptureCapability: %s %d", unique_id.get(), num));
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, unique_id, aCapEngine, num]() -> nsresult {
webrtc::CaptureCapability webrtcCaps;
MutexAutoLock lock(self->mEngineMutex);
int error = -1;
if (self->mEngines[aCapEngine].mPtrViECapture) {
if (self->EnsureInitialized(aCapEngine)) {
error = self->mEngines[aCapEngine].mPtrViECapture->GetCaptureCapability(
unique_id.get(), MediaEngineSource::kMaxUniqueIdLength, num, webrtcCaps);
}
@ -503,7 +564,7 @@ CamerasParent::RecvGetCaptureCapability(const int &aCapEngine,
self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
return NS_OK;
});
mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
DispatchToVideoCaptureThread(webrtc_runnable);
return true;
}
@ -512,13 +573,7 @@ CamerasParent::RecvGetCaptureDevice(const int& aCapEngine,
const int& aListNumber)
{
LOG((__PRETTY_FUNCTION__));
if (!EnsureInitialized(aCapEngine)) {
LOG(("Fails to initialize"));
unused << SendReplyFailure();
return false;
}
LOG(("RecvGetCaptureDevice"));
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine, aListNumber]() -> nsresult {
@ -526,20 +581,18 @@ CamerasParent::RecvGetCaptureDevice(const int& aCapEngine,
char deviceUniqueId[MediaEngineSource::kMaxUniqueIdLength];
nsCString name;
nsCString uniqueId;
MutexAutoLock lock(self->mEngineMutex);
int error = -1;
if (self->mEngines[aCapEngine].mPtrViECapture) {
error = self->mEngines[aCapEngine].mPtrViECapture->GetCaptureDevice(aListNumber,
deviceName,
sizeof(deviceName),
deviceUniqueId,
sizeof(deviceUniqueId));
if (self->EnsureInitialized(aCapEngine)) {
error = self->mEngines[aCapEngine].mPtrViECapture->GetCaptureDevice(aListNumber,
deviceName,
sizeof(deviceName),
deviceUniqueId,
sizeof(deviceUniqueId));
}
if (!error) {
name.Assign(deviceName);
uniqueId.Assign(deviceUniqueId);
}
nsRefPtr<nsIRunnable> ipc_runnable =
media::NewRunnableFrom([self, error, name, uniqueId]() -> nsresult {
if (self->IsShuttingDown()) {
@ -558,7 +611,7 @@ CamerasParent::RecvGetCaptureDevice(const int& aCapEngine,
self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
return NS_OK;
});
mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
DispatchToVideoCaptureThread(webrtc_runnable);
return true;
}
@ -567,19 +620,13 @@ CamerasParent::RecvAllocateCaptureDevice(const int& aCapEngine,
const nsCString& unique_id)
{
LOG((__PRETTY_FUNCTION__));
if (!EnsureInitialized(aCapEngine)) {
LOG(("Fails to initialize"));
unused << SendReplyFailure();
return false;
}
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine, unique_id]() -> nsresult {
int numdev = -1;
MutexAutoLock lock(self->mEngineMutex);
int error = -1;
if (self->mEngines[aCapEngine].mPtrViECapture) {
if (self->EnsureInitialized(aCapEngine)) {
error = self->mEngines[aCapEngine].mPtrViECapture->AllocateCaptureDevice(
unique_id.get(), MediaEngineSource::kMaxUniqueIdLength, numdev);
}
@ -600,7 +647,7 @@ CamerasParent::RecvAllocateCaptureDevice(const int& aCapEngine,
self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
return NS_OK;
});
mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
DispatchToVideoCaptureThread(webrtc_runnable);
return true;
}
@ -609,19 +656,13 @@ CamerasParent::RecvReleaseCaptureDevice(const int& aCapEngine,
const int& numdev)
{
LOG((__PRETTY_FUNCTION__));
if (!EnsureInitialized(aCapEngine)) {
LOG(("Fails to initialize"));
unused << SendReplyFailure();
return false;
}
LOG(("RecvReleaseCamera device nr %d", numdev));
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine, numdev]() -> nsresult {
LOG(("RecvReleaseCamera device nr %d", numdev));
MutexAutoLock lock(self->mEngineMutex);
int error = -1;
if (self->mEngines[aCapEngine].mPtrViECapture) {
if (self->EnsureInitialized(aCapEngine)) {
error = self->mEngines[aCapEngine].mPtrViECapture->ReleaseCaptureDevice(numdev);
}
nsRefPtr<nsIRunnable> ipc_runnable =
@ -641,12 +682,7 @@ CamerasParent::RecvReleaseCaptureDevice(const int& aCapEngine,
self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
return NS_OK;
});
#ifndef XP_MACOSX
mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
#else
// Mac OS X hangs on shutdown if we don't do this on the main thread.
NS_DispatchToMainThread(webrtc_runnable);
#endif
DispatchToVideoCaptureThread(webrtc_runnable);
return true;
}
@ -656,11 +692,6 @@ CamerasParent::RecvStartCapture(const int& aCapEngine,
const CaptureCapability& ipcCaps)
{
LOG((__PRETTY_FUNCTION__));
if (!EnsureInitialized(aCapEngine)) {
LOG(("Failure to initialize"));
unused << SendReplyFailure();
return false;
}
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
@ -668,23 +699,15 @@ CamerasParent::RecvStartCapture(const int& aCapEngine,
CallbackHelper** cbh;
webrtc::ExternalRenderer* render;
EngineHelper* helper = nullptr;
int error;
{
MutexAutoLock lockCallback(self->mCallbackMutex);
int error = -1;
if (self->EnsureInitialized(aCapEngine)) {
cbh = self->mCallbacks.AppendElement(
new CallbackHelper(static_cast<CaptureEngine>(aCapEngine), capnum, self));
render = static_cast<webrtc::ExternalRenderer*>(*cbh);
}
{
MutexAutoLock lockEngine(self->mEngineMutex);
if (self->mEngines[aCapEngine].mPtrViECapture) {
helper = &self->mEngines[aCapEngine];
error =
helper->mPtrViERender->AddRenderer(capnum, webrtc::kVideoI420, render);
} else {
error = -1;
}
helper = &self->mEngines[aCapEngine];
error =
helper->mPtrViERender->AddRenderer(capnum, webrtc::kVideoI420, render);
if (!error) {
error = helper->mPtrViERender->StartRender(capnum);
}
@ -705,7 +728,6 @@ CamerasParent::RecvStartCapture(const int& aCapEngine,
helper->mEngineIsRunning = true;
}
}
nsRefPtr<nsIRunnable> ipc_runnable =
media::NewRunnableFrom([self, error]() -> nsresult {
if (self->IsShuttingDown()) {
@ -722,7 +744,7 @@ CamerasParent::RecvStartCapture(const int& aCapEngine,
self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
return NS_OK;
});
mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
DispatchToVideoCaptureThread(webrtc_runnable);
return true;
}
@ -731,40 +753,32 @@ CamerasParent::RecvStopCapture(const int& aCapEngine,
const int& capnum)
{
LOG((__PRETTY_FUNCTION__));
if (!EnsureInitialized(aCapEngine)) {
LOG(("Failure to initialize"));
unused << SendReplyFailure();
return false;
}
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine, capnum]() -> nsresult {
{
MutexAutoLock lock(self->mEngineMutex);
// We only need to check mPtrViECapture as all other engines are guaranteed
// to be nulled under the same lock.
if (self->mEngines[aCapEngine].mPtrViECapture) {
self->mEngines[aCapEngine].mPtrViECapture->StopCapture(capnum);
self->mEngines[aCapEngine].mPtrViERender->StopRender(capnum);
self->mEngines[aCapEngine].mPtrViERender->RemoveRenderer(capnum);
self->mEngines[aCapEngine].mEngineIsRunning = false;
}
}
MutexAutoLock lock(self->mCallbackMutex);
for (unsigned int i = 0; i < self->mCallbacks.Length(); i++) {
if (self->mCallbacks[i]->mCapEngine == aCapEngine
&& self->mCallbacks[i]->mCapturerId == capnum) {
delete self->mCallbacks[i];
self->mCallbacks.RemoveElementAt(i);
break;
if (self->EnsureInitialized(aCapEngine)) {
self->mEngines[aCapEngine].mPtrViECapture->StopCapture(capnum);
self->mEngines[aCapEngine].mPtrViERender->StopRender(capnum);
self->mEngines[aCapEngine].mPtrViERender->RemoveRenderer(capnum);
self->mEngines[aCapEngine].mEngineIsRunning = false;
for (size_t i = 0; i < self->mCallbacks.Length(); i++) {
if (self->mCallbacks[i]->mCapEngine == aCapEngine
&& self->mCallbacks[i]->mCapturerId == capnum) {
delete self->mCallbacks[i];
self->mCallbacks.RemoveElementAt(i);
break;
}
}
}
return NS_OK;
});
mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, new RunnableTask(webrtc_runnable));
return SendReplySuccess();
if (NS_SUCCEEDED(DispatchToVideoCaptureThread(webrtc_runnable))) {
return SendReplySuccess();
} else {
return SendReplyFailure();
}
}
void
@ -788,49 +802,24 @@ CamerasParent::RecvAllDone()
return Send__delete__(this);
}
void CamerasParent::DoShutdown()
{
LOG((__PRETTY_FUNCTION__));
CloseEngines();
{
MutexAutoLock lock(mEngineMutex);
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
if (mEngines[i].mEngine) {
mEngines[i].mEngine->SetTraceCallback(nullptr);
webrtc::VideoEngine::Delete(mEngines[i].mEngine);
mEngines[i].mEngine = nullptr;
}
}
}
mPBackgroundThread = nullptr;
if (mVideoCaptureThread) {
if (mVideoCaptureThread->IsRunning()) {
mVideoCaptureThread->Stop();
}
delete mVideoCaptureThread;
mVideoCaptureThread = nullptr;
}
}
void
CamerasParent::ActorDestroy(ActorDestroyReason aWhy)
{
// No more IPC from here
LOG((__PRETTY_FUNCTION__));
StopIPC();
CloseEngines();
// Shut down WebRTC (if we're not in full shutdown, else this
// will already have happened)
StopVideoCapture();
}
CamerasParent::CamerasParent()
: mCallbackMutex("CamerasParent.mCallbackMutex"),
mEngineMutex("CamerasParent.mEngineMutex"),
mShmemPool(CaptureEngine::MaxEngine),
: mShmemPool(CaptureEngine::MaxEngine),
mThreadMonitor("CamerasParent::mThreadMonitor"),
mVideoCaptureThread(nullptr),
mChildIsAlive(true),
mDestroyed(false)
mDestroyed(false),
mWebRTCAlive(true)
{
if (!gCamerasParentLog) {
gCamerasParentLog = PR_NewLogModule("CamerasParent");
@ -841,16 +830,37 @@ CamerasParent::CamerasParent()
MOZ_ASSERT(mPBackgroundThread != nullptr, "GetCurrentThread failed");
LOG(("Spinning up WebRTC Cameras Thread"));
mVideoCaptureThread = new base::Thread("VideoCapture");
base::Thread::Options options;
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> threadStart =
media::NewRunnableFrom([self]() -> nsresult {
// Register thread shutdown observer
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (NS_WARN_IF(!obs)) {
return NS_ERROR_FAILURE;
}
nsresult rv =
obs->AddObserver(self, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Start the thread
MonitorAutoLock lock(self->mThreadMonitor);
self->mVideoCaptureThread = new base::Thread("VideoCapture");
base::Thread::Options options;
#if defined(_WIN32)
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINUITHREAD;
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINUITHREAD;
#else
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINTHREAD;
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINTHREAD;
#endif
if (!mVideoCaptureThread->StartWithOptions(options)) {
MOZ_CRASH();
}
if (!self->mVideoCaptureThread->StartWithOptions(options)) {
MOZ_CRASH();
}
self->mThreadMonitor.NotifyAll();
return NS_OK;
});
NS_DispatchToMainThread(threadStart);
MOZ_COUNT_CTOR(CamerasParent);
}
@ -860,7 +870,15 @@ CamerasParent::~CamerasParent()
LOG(("~CamerasParent: %p", this));
MOZ_COUNT_DTOR(CamerasParent);
DoShutdown();
#ifdef DEBUG
// Verify we have shut down the webrtc engines, this is
// supposed to happen in ActorDestroy.
// That runnable takes a ref to us, so it must have finished
// by the time we get here.
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
MOZ_ASSERT(!mEngines[i].mEngine);
}
#endif
}
already_AddRefed<CamerasParent>

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

@ -7,10 +7,12 @@
#ifndef mozilla_CamerasParent_h
#define mozilla_CamerasParent_h
#include "nsIObserver.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/camera/PCamerasParent.h"
#include "mozilla/ipc/Shmem.h"
#include "mozilla/ShmemPool.h"
#include "mozilla/Atomics.h"
// conflicts with #include of scoped_ptr.h
#undef FF
@ -73,9 +75,11 @@ public:
bool mEngineIsRunning;
};
class CamerasParent : public PCamerasParent
class CamerasParent : public PCamerasParent,
public nsIObserver
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CamerasParent);
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOBSERVER
public:
static already_AddRefed<CamerasParent> Create();
@ -94,7 +98,9 @@ public:
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
nsIThread* GetBackgroundThread() { return mPBackgroundThread; };
bool IsShuttingDown() { return !mChildIsAlive || mDestroyed; };
bool IsShuttingDown() { return !mChildIsAlive
|| mDestroyed
|| !mWebRTCAlive; };
ShmemBuffer GetBuffer(size_t aSize);
// helper to forward to the PBackground thread
@ -116,15 +122,12 @@ protected:
bool SetupEngine(CaptureEngine aCapEngine);
void CloseEngines();
bool EnsureInitialized(int aEngine);
void DoShutdown();
void StopIPC();
void StopVideoCapture();
nsresult DispatchToVideoCaptureThread(nsRunnable *event);
EngineHelper mEngines[CaptureEngine::MaxEngine];
nsTArray<CallbackHelper*> mCallbacks;
// Protects the callback arrays
Mutex mCallbackMutex;
// Protects the engines array
Mutex mEngineMutex;
// image buffers
mozilla::ShmemPool mShmemPool;
@ -132,12 +135,18 @@ protected:
// PBackground parent thread
nsCOMPtr<nsIThread> mPBackgroundThread;
// Monitors creation of the thread below
Monitor mThreadMonitor;
// video processing thread - where webrtc.org capturer code runs
base::Thread* mVideoCaptureThread;
// Shutdown handling
bool mChildIsAlive;
bool mDestroyed;
// Above 2 are PBackground only, but this is potentially
// read cross-thread.
mozilla::Atomic<bool> mWebRTCAlive;
};
PCamerasParent* CreateCamerasParent();

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

@ -68,19 +68,19 @@ public:
Pledge& operator = (const Pledge&) = delete;
template<typename OnSuccessType>
void Then(OnSuccessType aOnSuccess)
void Then(OnSuccessType&& aOnSuccess)
{
Then(aOnSuccess, [](ErrorType&){});
Then(Forward<OnSuccessType>(aOnSuccess), [](ErrorType&){});
}
template<typename OnSuccessType, typename OnFailureType>
void Then(OnSuccessType aOnSuccess, OnFailureType aOnFailure)
void Then(OnSuccessType&& aOnSuccess, OnFailureType&& aOnFailure)
{
class Functors : public FunctorsBase
{
public:
Functors(OnSuccessType& aOnSuccess, OnFailureType& aOnFailure)
: mOnSuccess(aOnSuccess), mOnFailure(aOnFailure) {}
Functors(OnSuccessType&& aOnSuccess, OnFailureType&& aOnFailure)
: mOnSuccess(Move(aOnSuccess)), mOnFailure(Move(aOnFailure)) {}
void Succeed(ValueType& result)
{
@ -94,8 +94,8 @@ public:
OnSuccessType mOnSuccess;
OnFailureType mOnFailure;
};
mFunctors = new Functors(aOnSuccess, aOnFailure);
mFunctors = new Functors(Forward<OnSuccessType>(aOnSuccess),
Forward<OnFailureType>(aOnFailure));
if (mDone) {
if (!mRejected) {
mFunctors->Succeed(mValue);
@ -186,7 +186,7 @@ template<typename OnRunType>
class LambdaRunnable : public nsRunnable
{
public:
explicit LambdaRunnable(OnRunType& aOnRun) : mOnRun(aOnRun) {}
explicit LambdaRunnable(OnRunType&& aOnRun) : mOnRun(Move(aOnRun)) {}
private:
NS_IMETHODIMP
Run()
@ -198,16 +198,16 @@ private:
template<typename OnRunType>
LambdaRunnable<OnRunType>*
NewRunnableFrom(OnRunType aOnRun)
NewRunnableFrom(OnRunType&& aOnRun)
{
return new LambdaRunnable<OnRunType>(aOnRun);
return new LambdaRunnable<OnRunType>(Forward<OnRunType>(aOnRun));
}
template<typename OnRunType>
class LambdaTask : public Task
{
public:
explicit LambdaTask(OnRunType& aOnRun) : mOnRun(aOnRun) {}
explicit LambdaTask(OnRunType&& aOnRun) : mOnRun(Move(aOnRun)) {}
private:
void
Run()
@ -219,9 +219,9 @@ private:
template<typename OnRunType>
LambdaTask<OnRunType>*
NewTaskFrom(OnRunType aOnRun)
NewTaskFrom(OnRunType&& aOnRun)
{
return new LambdaTask<OnRunType>(aOnRun);
return new LambdaTask<OnRunType>(Forward<OnRunType>(aOnRun));
}
/* media::CoatCheck - There and back again. Park an object in exchange for an id.

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

@ -277,6 +277,19 @@ function SetupEME(test, token, params)
{
var v = document.createElement("video");
v.crossOrigin = test.crossOrigin || false;
v.sessions = [];
v.closeSessions = function() {
return Promise.all(v.sessions.map(s => s.close().then(() => s.closed))).then(
() => {
v.setMediaKeys(null);
if (v.parentNode) {
v.parentNode.removeChild(v);
}
v.onerror = null;
v.src = null;
});
};
// Log events dispatched to make debugging easier...
[ "canplay", "canplaythrough", "ended", "error", "loadeddata",
@ -311,6 +324,7 @@ function SetupEME(test, token, params)
if (params && params.onsessioncreated) {
params.onsessioncreated(session);
}
v.sessions.push(session);
return new Promise(function (resolve, reject) {
session.addEventListener("message", UpdateSessionFunc(test, token, sessionType, resolve, reject));

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

@ -95,7 +95,7 @@ function startTest(test, token)
ok(keyIdsReceived[kid], TimeStamp(token) + " key with id " + kid + " was usable as expected");
}
manager.finished(token);
v.closeSessions().then(() => manager.finished(token));
});
LoadTest(test, v, token)

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

@ -1231,8 +1231,7 @@ Promise::MaybeReportRejected()
NS_WARNING("!!! Trying to report rejected Promise after MainThread shutdown");
}
if (mainThread) {
nsRefPtr<AsyncErrorReporter> r =
new AsyncErrorReporter(CycleCollectedJSRuntime::Get()->Runtime(), xpcReport);
nsRefPtr<AsyncErrorReporter> r = new AsyncErrorReporter(xpcReport);
mainThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
}
}

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

@ -319,6 +319,7 @@ interface WebGL2RenderingContext : WebGLRenderingContext
void copyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset,
GLintptr writeOffset, GLsizeiptr size);
void getBufferSubData(GLenum target, GLintptr offset, ArrayBuffer? returnedData);
void getBufferSubData(GLenum target, GLintptr offset, SharedArrayBuffer returnedData);
/* Framebuffer objects */
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0,
@ -347,10 +348,10 @@ interface WebGL2RenderingContext : WebGLRenderingContext
void texImage3D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format,
GLenum type, ArrayBufferView? pixels);
GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
ArrayBufferView? pixels);
(ArrayBufferView or SharedArrayBufferView)? pixels);
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLenum format, GLenum type, ImageData? data);
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
@ -363,10 +364,10 @@ interface WebGL2RenderingContext : WebGLRenderingContext
GLint x, GLint y, GLsizei width, GLsizei height);
void compressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLsizei imageSize, ArrayBufferView data);
GLint border, GLsizei imageSize, (ArrayBufferView or SharedArrayBufferView) data);
void compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize, ArrayBufferView data);
GLenum format, GLsizei imageSize, (ArrayBufferView or SharedArrayBufferView) data);
/* Programs and shaders */
[WebGLHandlesContextLoss] GLint getFragDataLocation(WebGLProgram? program, DOMString name);

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

@ -552,9 +552,13 @@ interface WebGLRenderingContext {
void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
void bufferData(GLenum target, ArrayBufferView data, GLenum usage);
void bufferData(GLenum target, SharedArrayBufferView data, GLenum usage);
void bufferData(GLenum target, ArrayBuffer? data, GLenum usage);
void bufferData(GLenum target, SharedArrayBuffer data, GLenum usage);
void bufferSubData(GLenum target, GLintptr offset, ArrayBufferView data);
void bufferSubData(GLenum target, GLintptr offset, SharedArrayBufferView data);
void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? data);
void bufferSubData(GLenum target, GLintptr offset, SharedArrayBuffer data);
[WebGLHandlesContextLoss] GLenum checkFramebufferStatus(GLenum target);
void clear(GLbitfield mask);
@ -566,11 +570,11 @@ interface WebGLRenderingContext {
void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLint border,
ArrayBufferView data);
(ArrayBufferView or SharedArrayBufferView) data);
void compressedTexSubImage2D(GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLenum format,
ArrayBufferView data);
(ArrayBufferView or SharedArrayBufferView) data);
void copyTexImage2D(GLenum target, GLint level, GLenum internalformat,
GLint x, GLint y, GLsizei width, GLsizei height,
@ -673,7 +677,7 @@ interface WebGLRenderingContext {
[Throws]
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type, ArrayBufferView? pixels);
GLenum format, GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
void renderbufferStorage(GLenum target, GLenum internalformat,
GLsizei width, GLsizei height);
@ -693,7 +697,7 @@ interface WebGLRenderingContext {
[Throws]
void texImage2D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLint border, GLenum format,
GLenum type, ArrayBufferView? pixels);
GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
[Throws]
void texImage2D(GLenum target, GLint level, GLenum internalformat,
GLenum format, GLenum type, ImageData? pixels);
@ -713,7 +717,7 @@ interface WebGLRenderingContext {
[Throws]
void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type, ArrayBufferView? pixels);
GLenum format, GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
[Throws]
void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum format, GLenum type, ImageData? pixels);

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

@ -338,8 +338,7 @@ public:
xpcReport->Init(report.report(), report.message(),
/* aIsChrome = */ false, /* aWindowID = */ 0);
nsRefPtr<AsyncErrorReporter> aer =
new AsyncErrorReporter(CycleCollectedJSRuntime::Get()->Runtime(), xpcReport);
nsRefPtr<AsyncErrorReporter> aer = new AsyncErrorReporter(xpcReport);
NS_DispatchToMainThread(aer);
}
};

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

@ -1,4 +1,4 @@
54851
54852
0/nm
0th/pt
1/n1
@ -42923,6 +42923,7 @@ prekindergarten/SM
prelacy/M
prelate/SM
prelim/SM
preliminarily
preliminary/SM
preliterate
prelude/MS

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

@ -681,17 +681,19 @@ ClientLayerManager::SetIsFirstPaint()
}
TextureClientPool*
ClientLayerManager::GetTexturePool(SurfaceFormat aFormat)
ClientLayerManager::GetTexturePool(SurfaceFormat aFormat, TextureFlags aFlags)
{
for (size_t i = 0; i < mTexturePools.Length(); i++) {
if (mTexturePools[i]->GetFormat() == aFormat) {
if (mTexturePools[i]->GetFormat() == aFormat &&
mTexturePools[i]->GetFlags() == aFlags) {
return mTexturePools[i];
}
}
mTexturePools.AppendElement(
new TextureClientPool(aFormat, IntSize(gfxPlatform::GetPlatform()->GetTileWidth(),
gfxPlatform::GetPlatform()->GetTileHeight()),
new TextureClientPool(aFormat, aFlags,
IntSize(gfxPlatform::GetPlatform()->GetTileWidth(),
gfxPlatform::GetPlatform()->GetTileHeight()),
gfxPrefs::LayersTileMaxPoolSize(),
gfxPrefs::LayersTileShrinkPoolTimeout(),
mForwarder));
@ -701,17 +703,20 @@ ClientLayerManager::GetTexturePool(SurfaceFormat aFormat)
void
ClientLayerManager::ReturnTextureClientDeferred(TextureClient& aClient) {
GetTexturePool(aClient.GetFormat())->ReturnTextureClientDeferred(&aClient);
GetTexturePool(aClient.GetFormat(),
aClient.GetFlags())->ReturnTextureClientDeferred(&aClient);
}
void
ClientLayerManager::ReturnTextureClient(TextureClient& aClient) {
GetTexturePool(aClient.GetFormat())->ReturnTextureClient(&aClient);
GetTexturePool(aClient.GetFormat(),
aClient.GetFlags())->ReturnTextureClient(&aClient);
}
void
ClientLayerManager::ReportClientLost(TextureClient& aClient) {
GetTexturePool(aClient.GetFormat())->ReportClientLost();
GetTexturePool(aClient.GetFormat(),
aClient.GetFlags())->ReportClientLost();
}
void

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

@ -121,7 +121,7 @@ public:
virtual void SetIsFirstPaint() override;
TextureClientPool* GetTexturePool(gfx::SurfaceFormat aFormat);
TextureClientPool* GetTexturePool(gfx::SurfaceFormat aFormat, TextureFlags aFlags);
/// Utility methods for managing texture clients.
void ReturnTextureClientDeferred(TextureClient& aClient);

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

@ -110,7 +110,7 @@ ClientSingleTiledLayerBuffer::GetTextureClient()
{
return mCompositableClient->CreateTextureClientForDrawing(
gfx::ImageFormatToSurfaceFormat(mFormat), mSize, BackendSelector::Content,
TextureFlags::IMMEDIATE_UPLOAD);
TextureFlags::DISALLOW_BIGIMAGE | TextureFlags::IMMEDIATE_UPLOAD);
}
void

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

@ -24,11 +24,13 @@ ShrinkCallback(nsITimer *aTimer, void *aClosure)
}
TextureClientPool::TextureClientPool(gfx::SurfaceFormat aFormat,
TextureFlags aFlags,
gfx::IntSize aSize,
uint32_t aMaxTextureClients,
uint32_t aShrinkTimeoutMsec,
CompositableForwarder* aAllocator)
: mFormat(aFormat)
, mFlags(aFlags)
, mSize(aSize)
, mMaxTextureClients(aMaxTextureClients)
, mShrinkTimeoutMsec(aShrinkTimeoutMsec)
@ -108,10 +110,10 @@ TextureClientPool::GetTextureClient()
// gfx::BackendType::NONE means use the content backend
textureClient = TextureClient::CreateForRawBufferAccess(mSurfaceAllocator,
mFormat, mSize, gfx::BackendType::NONE,
TextureFlags::IMMEDIATE_UPLOAD, ALLOC_DEFAULT);
mFlags, ALLOC_DEFAULT);
} else {
textureClient = TextureClient::CreateForDrawing(mSurfaceAllocator,
mFormat, mSize, BackendSelector::Content, TextureFlags::IMMEDIATE_UPLOAD);
mFormat, mSize, BackendSelector::Content, mFlags);
}
mOutstandingClients++;

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

@ -42,7 +42,9 @@ class TextureClientPool final : public TextureClientAllocator
~TextureClientPool();
public:
TextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
TextureClientPool(gfx::SurfaceFormat aFormat,
TextureFlags aFlags,
gfx::IntSize aSize,
uint32_t aMaxTextureClients,
uint32_t aShrinkTimeoutMsec,
CompositableForwarder* aAllocator);
@ -101,6 +103,7 @@ public:
void Clear();
gfx::SurfaceFormat GetFormat() { return mFormat; }
TextureFlags GetFlags() const { return mFlags; }
private:
// The minimum size of the pool (the number of tiles that will be kept after
@ -110,6 +113,9 @@ private:
/// Format is passed to the TextureClient for buffer creation.
gfx::SurfaceFormat mFormat;
/// Flags passed to the TextureClient for buffer creation.
const TextureFlags mFlags;
/// The width and height of the tiles to be used.
gfx::IntSize mSize;

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

@ -1240,7 +1240,8 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
if (aTile.IsPlaceholderTile()) {
aTile.SetLayerManager(mManager);
aTile.SetTextureAllocator(mManager->GetTexturePool(
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(content)));
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(content),
TextureFlags::DISALLOW_BIGIMAGE | TextureFlags::IMMEDIATE_UPLOAD));
}
aTile.SetCompositableClient(mCompositableClient);

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