merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-07-15 14:58:57 +02:00
Родитель c82ead15d7 e2fa0f3b8e
Коммит 4b4bf0951c
342 изменённых файлов: 8174 добавлений и 3135 удалений

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

@ -955,32 +955,30 @@ chatbox:-moz-full-screen-ancestor > .chat-titlebar {
opacity: 1.0;
}
#BMB_bookmarksPopup[arrowposition="after_start"] {
#BMB_bookmarksPopup[animate="cancel"] {
transform: none;
}
#BMB_bookmarksPopup[arrowposition="after_start"]:-moz-locale-dir(ltr),
#BMB_bookmarksPopup[arrowposition="after_end"]:-moz-locale-dir(rtl) {
transform-origin: 20px top;
}
#BMB_bookmarksPopup[arrowposition="after_end"] {
#BMB_bookmarksPopup[arrowposition="after_end"]:-moz-locale-dir(ltr),
#BMB_bookmarksPopup[arrowposition="after_start"]:-moz-locale-dir(rtl) {
transform-origin: calc(100% - 20px) top;
}
#BMB_bookmarksPopup[arrowposition="before_start"] {
#BMB_bookmarksPopup[arrowposition="before_start"]:-moz-locale-dir(ltr),
#BMB_bookmarksPopup[arrowposition="before_end"]:-moz-locale-dir(rtl) {
transform-origin: 20px bottom;
}
#BMB_bookmarksPopup[arrowposition="before_end"] {
#BMB_bookmarksPopup[arrowposition="before_end"]:-moz-locale-dir(ltr),
#BMB_bookmarksPopup[arrowposition="before_start"]:-moz-locale-dir(rtl) {
transform-origin: calc(100% - 20px) bottom;
}
#BMB_bookmarksPopup[arrowposition="after_start"][animate="cancel"],
#BMB_bookmarksPopup[arrowposition="before_end"][animate="cancel"] {
transform: none;
}
#BMB_bookmarksPopup[arrowposition="after_end"][animate="cancel"],
#BMB_bookmarksPopup[arrowposition="before_start"][animate="cancel"] {
transform: none;
}
%endif
/* Customize mode */

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

@ -5,8 +5,19 @@
<script>
function init() {
window.addEventListener("message", function process(e) {doTest(e)}, false);
doTest();
window.addEventListener("message", function process(e) {
// The init function of abouthealth.js schedules an initial payload event,
// which will be sent after the payload data has been collected. This extra
// event can cause unexpected successes/failures in this test, so we wait
// for the extra event to arrive here before progressing with the actual
// test.
if (e.data.type == "payload") {
window.removeEventListener("message", process, false);
window.addEventListener("message", doTest, false);
doTest();
}
}, false);
}
function checkSubmissionValue(payload, expectedValue) {

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

@ -5,8 +5,8 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
PARALLEL_DIRS += [
'content',
'src',
'content',
'src',
]
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

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

@ -26,6 +26,7 @@
window.OTProperties.cssURL = window.OTProperties.assetURL + 'css/ot.css';
</script>
<script type="text/javascript" src="loop/libs/sdk.js"></script>
<script type="text/javascript" src="loop/shared/libs/react-0.10.0.js"></script>
<script type="text/javascript" src="loop/shared/libs/jquery-2.1.0.js"></script>
<script type="text/javascript" src="loop/shared/libs/lodash-2.4.1.js"></script>
<script type="text/javascript" src="loop/shared/libs/backbone-1.1.2.js"></script>

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

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* jshint esnext:true */
/* jshint newcap:false, esnext:true */
/* global loop:true */
var loop = loop || {};
@ -164,10 +164,10 @@ loop.conversation = (function(OT, mozL10n) {
return;
}
this.loadView(
new loop.shared.views.ConversationView({
sdk: OT,
model: this._conversation
/*jshint newcap:false*/
this.loadReactComponent(sharedViews.ConversationView({
sdk: OT,
model: this._conversation
}));
},

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

@ -58,7 +58,7 @@
/* Common media control buttons behavior */
.conversation .controls .media-control {
background-color: transparent;
opacity: .7; /* reduce the opacity for a non-streaming media */
opacity: 1;
}
.conversation .controls .media-control:hover {
background-color: rgba(255, 255, 255, .35);
@ -68,58 +68,35 @@
background-color: #0096DD;
opacity: 1;
}
.conversation .controls .media-control.streaming {
opacity: 1;
}
.conversation .controls .media-control:not(.streaming):hover {
background-color: transparent;
opacity: 1;
}
/* Audio mute button */
.conversation .controls .btn-mute-audio {
.conversation .controls .local-media.btn-mute-audio {
background-image: url(../img/audio-inverse-14x14.png);
}
.conversation .controls .btn-mute-audio.streaming {
background-image: url(../img/audio-highlight-14x14.png);
}
.conversation .controls .btn-mute-audio.muted,
.conversation .controls .btn-mute-audio.streaming:hover {
.conversation .controls .local-media.btn-mute-audio.muted {
background-image: url(../img/mute-inverse-14x14.png);
}
@media (min-resolution: 2dppx) {
.conversation .controls .btn-mute-audio {
.conversation .controls .local-media.btn-mute-audio {
background-image: url(../img/audio-inverse-14x14@2x.png);
}
.conversation .controls .btn-mute-audio.streaming {
background-image: url(../img/audio-highlight-14x14@2x.png);
}
.conversation .controls .btn-mute-audio.muted,
.conversation .controls .btn-mute-audio.streaming:hover {
.conversation .controls .local-media.btn-mute-audio.muted {
background-image: url(../img/mute-inverse-14x14@2x.png);
}
}
/* Video mute button */
.conversation .controls .btn-mute-video {
.conversation .controls .local-media.btn-mute-video {
background-image: url(../img/video-inverse-14x14.png);
}
.conversation .controls .btn-mute-video.streaming {
background-image: url(../img/video-highlight-14x14.png);
}
.conversation .controls .btn-mute-video.muted,
.conversation .controls .btn-mute-video.streaming:hover {
.conversation .controls .local-media.btn-mute-video.muted {
background-image: url(../img/facemute-14x14.png);
}
@media (min-resolution: 2dppx) {
.conversation .controls .btn-mute-video {
.conversation .controls .local-media.btn-mute-video {
background-image: url(../img/video-inverse-14x14@2x.png);
}
.conversation .controls .btn-mute-video.streaming {
background-image: url(../img/video-highlight-14x14@2x.png);
}
.conversation .controls .btn-mute-video.muted,
.conversation .controls .btn-mute-video.streaming:hover {
.conversation .controls .local-media.btn-mute-video.muted {
background-image: url(../img/facemute-14x14@2x.png);
}
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 226 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 439 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 190 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 301 B

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

@ -1,15 +1,18 @@
/** @jsx React.DOM */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global loop:true */
/* jshint newcap:false */
/* global loop:true, React */
var loop = loop || {};
loop.shared = loop.shared || {};
loop.shared.views = (function(_, OT, l10n) {
"use strict";
var sharedModels = loop.shared.models;
var __ = l10n.get;
/**
* L10n view. Translates resulting view DOM fragment once rendered.
@ -89,35 +92,113 @@ loop.shared.views = (function(_, OT, l10n) {
});
/**
* Conversation view.
* Media control button.
*
* Required props:
* - {String} scope Media scope, can be "local" or "remote".
* - {String} type Media type, can be "audio" or "video".
* - {Function} action Function to be executed on click.
* - {Enabled} enabled Stream activation status (default: true).
*/
var ConversationView = BaseView.extend({
className: "conversation",
var MediaControlButton = React.createClass({displayName: 'MediaControlButton',
propTypes: {
scope: React.PropTypes.string.isRequired,
type: React.PropTypes.string.isRequired,
action: React.PropTypes.func.isRequired,
enabled: React.PropTypes.bool.isRequired
},
/**
* Local stream object.
* @type {OT.Stream|null}
*/
localStream: null,
getDefaultProps: function() {
return {enabled: true};
},
template: _.template([
'<ul class="controls cf">',
' <li><button class="btn btn-hangup" ',
' data-l10n-id="hangup_button"></button></li>',
' <li><button class="btn media-control btn-mute-video"',
' data-l10n-id="mute_local_video_button"></button></li>',
' <li><button class="btn media-control btn-mute-audio"',
' data-l10n-id="mute_local_audio_button"></button></li>',
'</ul>',
'<div class="media nested">',
// Both these wrappers are required by the SDK; this is fragile and
// will break if a future version of the SDK updates this generated DOM,
// especially as the SDK seems to actually move wrapped contents into
// their own generated stuff.
' <div class="remote"><div class="incoming"></div></div>',
' <div class="local"><div class="outgoing"></div></div>',
'</div>'
].join("")),
handleClick: function() {
this.props.action();
},
_getClasses: function() {
var cx = React.addons.classSet;
// classes
var classesObj = {
"btn": true,
"media-control": true,
"local-media": this.props.scope === "local",
"muted": !this.props.enabled
};
classesObj["btn-mute-" + this.props.type] = true;
return cx(classesObj);
},
_getTitle: function(enabled) {
var prefix = this.props.enabled ? "mute" : "unmute";
var suffix = "button_title";
var msgId = [prefix, this.props.scope, this.props.type, suffix].join("_");
return __(msgId);
},
render: function() {
return (
React.DOM.button( {className:this._getClasses(),
title:this._getTitle(),
onClick:this.handleClick})
);
}
});
/**
* Conversation controls.
*/
var ConversationToolbar = React.createClass({displayName: 'ConversationToolbar',
getDefaultProps: function() {
return {
video: {enabled: true},
audio: {enabled: true}
};
},
propTypes: {
video: React.PropTypes.object.isRequired,
audio: React.PropTypes.object.isRequired,
hangup: React.PropTypes.func.isRequired,
publishStream: React.PropTypes.func.isRequired
},
handleClickHangup: function() {
this.props.hangup();
},
handleToggleVideo: function() {
this.props.publishStream("video", !this.props.video.enabled);
},
handleToggleAudio: function() {
this.props.publishStream("audio", !this.props.audio.enabled);
},
render: function() {
return (
React.DOM.ul( {className:"controls"},
React.DOM.li(null, React.DOM.button( {className:"btn btn-hangup",
onClick:this.handleClickHangup,
title:__("hangup_button_title")})),
React.DOM.li(null, MediaControlButton( {action:this.handleToggleVideo,
enabled:this.props.video.enabled,
scope:"local", type:"video"} )),
React.DOM.li(null, MediaControlButton( {action:this.handleToggleAudio,
enabled:this.props.audio.enabled,
scope:"local", type:"audio"} ))
)
);
}
});
var ConversationView = React.createClass({displayName: 'ConversationView',
mixins: [Backbone.Events],
propTypes: {
sdk: React.PropTypes.object.isRequired,
model: React.PropTypes.object.isRequired
},
// height set to "auto" to fix video layout on Google Chrome
// @see https://bugzilla.mozilla.org/show_bug.cgi?id=991122
@ -126,32 +207,40 @@ loop.shared.views = (function(_, OT, l10n) {
height: "auto",
style: {
bugDisplayMode: "off",
buttonDisplayMode: "off"
buttonDisplayMode: "off",
nameDisplayMode: "off"
}
},
events: {
'click .btn-hangup': 'hangup',
'click .btn-mute-audio': 'toggleMuteAudio',
'click .btn-mute-video': 'toggleMuteVideo'
getInitialState: function() {
return {
video: {enabled: false},
audio: {enabled: false}
};
},
/**
* Establishes webrtc communication using OT sdk.
*/
initialize: function(options) {
options = options || {};
if (!options.sdk) {
throw new Error("missing required sdk");
}
this.sdk = options.sdk;
componentDidMount: function() {
this.props.model.startSession();
},
this.listenTo(this.model, "session:connected", this.publish);
this.listenTo(this.model, "session:stream-created", this._streamCreated);
this.listenTo(this.model, ["session:peer-hungup",
"session:network-disconnected",
"session:ended"].join(" "), this.unpublish);
this.model.startSession();
componentWillMount: function() {
this.listenTo(this.props.model, "session:connected",
this.startPublishing);
this.listenTo(this.props.model, "session:stream-created",
this._streamCreated);
this.listenTo(this.props.model, ["session:peer-hungup",
"session:network-disconnected",
"session:ended"].join(" "),
this.stopPublishing);
},
componentWillUnmount: function() {
this.hangup();
},
hangup: function() {
this.stopPublishing();
this.props.model.endSession();
},
/**
@ -165,74 +254,16 @@ loop.shared.views = (function(_, OT, l10n) {
* @param {StreamEvent} event
*/
_streamCreated: function(event) {
var incoming = this.$(".incoming").get(0);
var incoming = this.getDOMNode().querySelector(".incoming");
event.streams.forEach(function(stream) {
if (stream.connection.connectionId !==
this.model.session.connection.connectionId) {
this.model.session.subscribe(stream, incoming, this.publisherConfig);
this.props.model.session.connection.connectionId) {
this.props.model.session.subscribe(stream, incoming,
this.publisherConfig);
}
}, this);
},
/**
* Hangs up current conversation.
*
* @param {MouseEvent} event
*/
hangup: function(event) {
event.preventDefault();
this.unpublish();
this.model.endSession();
},
/**
* Toggles audio mute state.
*
* @param {MouseEvent} event
*/
toggleMuteAudio: function(event) {
event.preventDefault();
if (!this.localStream) {
return;
}
var msgId;
var $button = this.$(".btn-mute-audio");
var enabled = !this.localStream.hasAudio;
this.publisher.publishAudio(enabled);
if (enabled) {
msgId = "mute_local_audio_button.title";
$button.removeClass("muted");
} else {
msgId = "unmute_local_audio_button.title";
$button.addClass("muted");
}
$button.attr("title", l10n.get(msgId));
},
/**
* Toggles video mute state.
*
* @param {MouseEvent} event
*/
toggleMuteVideo: function(event) {
event.preventDefault();
if (!this.localStream) {
return;
}
var msgId;
var $button = this.$(".btn-mute-video");
var enabled = !this.localStream.hasVideo;
this.publisher.publishVideo(enabled);
if (enabled) {
$button.removeClass("muted");
msgId = "mute_local_video_button.title";
} else {
$button.addClass("muted");
msgId = "unmute_local_video_button.title";
}
$button.attr("title", l10n.get(msgId));
},
/**
* Publishes remote streams available once a session is connected.
*
@ -240,10 +271,12 @@ loop.shared.views = (function(_, OT, l10n) {
*
* @param {SessionConnectEvent} event
*/
publish: function(event) {
var outgoing = this.$(".outgoing").get(0);
startPublishing: function(event) {
var outgoing = this.getDOMNode().querySelector(".outgoing");
this.publisher = this.sdk.initPublisher(outgoing, this.publisherConfig);
// XXX move this into its StreamingVideo component?
this.publisher = this.props.sdk.initPublisher(
outgoing, this.publisherConfig);
// Suppress OT GuM custom dialog, see bug 1018875
function preventOpeningAccessDialog(event) {
@ -251,43 +284,64 @@ loop.shared.views = (function(_, OT, l10n) {
}
this.publisher.on("accessDialogOpened", preventOpeningAccessDialog);
this.publisher.on("accessDenied", preventOpeningAccessDialog);
this.publisher.on("streamCreated", function(event) {
this.localStream = event.stream;
if (this.localStream.hasAudio) {
this.$(".btn-mute-audio").addClass("streaming");
}
if (this.localStream.hasVideo) {
this.$(".btn-mute-video").addClass("streaming");
}
}.bind(this));
this.publisher.on("streamDestroyed", function() {
this.localStream = null;
this.$(".btn-mute-audio").removeClass("streaming muted");
this.$(".btn-mute-video").removeClass("streaming muted");
this.setState({
audio: {enabled: event.stream.hasAudio},
video: {enabled: event.stream.hasVideo}
});
}.bind(this));
this.model.session.publish(this.publisher);
this.publisher.on("streamDestroyed", function() {
this.setState({
audio: {enabled: false},
video: {enabled: false}
});
}.bind(this));
this.props.model.session.publish(this.publisher);
},
/**
* Toggles streaming status for a given stream type.
*
* @param {String} type Stream type ("audio" or "video").
* @param {Boolean} enabled Enabled stream flag.
*/
publishStream: function(type, enabled) {
if (type === "audio") {
this.publisher.publishAudio(enabled);
this.setState({audio: {enabled: enabled}});
} else {
this.publisher.publishVideo(enabled);
this.setState({video: {enabled: enabled}});
}
},
/**
* Unpublishes local stream.
*/
unpublish: function() {
stopPublishing: function() {
// Unregister access OT GuM custom dialog listeners, see bug 1018875
this.publisher.off("accessDialogOpened");
this.publisher.off("accessDenied");
this.model.session.unpublish(this.publisher);
this.props.model.session.unpublish(this.publisher);
},
/**
* Renders this view.
*
* @return {ConversationView}
*/
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
return (
React.DOM.div( {className:"conversation"},
ConversationToolbar( {video:this.state.video,
audio:this.state.audio,
publishStream:this.publishStream,
hangup:this.hangup} ),
React.DOM.div( {className:"media nested"},
React.DOM.div( {className:"remote"}, React.DOM.div( {className:"incoming"})),
React.DOM.div( {className:"local"}, React.DOM.div( {className:"outgoing"}))
)
)
);
}
});
@ -456,6 +510,8 @@ loop.shared.views = (function(_, OT, l10n) {
L10nView: L10nView,
BaseView: BaseView,
ConversationView: ConversationView,
ConversationToolbar: ConversationToolbar,
MediaControlButton: MediaControlButton,
NotificationListView: NotificationListView,
NotificationView: NotificationView,
UnsupportedBrowserView: UnsupportedBrowserView,

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

@ -0,0 +1,520 @@
/** @jsx React.DOM */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* jshint newcap:false */
/* global loop:true, React */
var loop = loop || {};
loop.shared = loop.shared || {};
loop.shared.views = (function(_, OT, l10n) {
"use strict";
var sharedModels = loop.shared.models;
var __ = l10n.get;
/**
* L10n view. Translates resulting view DOM fragment once rendered.
*/
var L10nView = (function() {
var L10nViewImpl = Backbone.View.extend(), // Original View constructor
originalExtend = L10nViewImpl.extend; // Original static extend fn
/**
* Patches View extend() method so we can hook and patch any declared render
* method.
*
* @return {Backbone.View} Extended view with patched render() method.
*/
L10nViewImpl.extend = function() {
var ExtendedView = originalExtend.apply(this, arguments),
originalRender = ExtendedView.prototype.render;
/**
* Wraps original render() method to translate contents once they're
* rendered.
*
* @return {Backbone.View} Extended view instance.
*/
ExtendedView.prototype.render = function() {
if (originalRender) {
originalRender.apply(this, arguments);
l10n.translate(this.el);
}
return this;
};
return ExtendedView;
};
return L10nViewImpl;
})();
/**
* Base view.
*/
var BaseView = L10nView.extend({
/**
* Hides view element.
*
* @return {BaseView}
*/
hide: function() {
this.$el.hide();
return this;
},
/**
* Shows view element.
*
* @return {BaseView}
*/
show: function() {
this.$el.show();
return this;
},
/**
* Base render implementation: renders an attached template if available.
*
* Note: You need to override this if you want to do fancier stuff, eg.
* rendering the template using model data.
*
* @return {BaseView}
*/
render: function() {
if (this.template) {
this.$el.html(this.template());
}
return this;
}
});
/**
* Media control button.
*
* Required props:
* - {String} scope Media scope, can be "local" or "remote".
* - {String} type Media type, can be "audio" or "video".
* - {Function} action Function to be executed on click.
* - {Enabled} enabled Stream activation status (default: true).
*/
var MediaControlButton = React.createClass({
propTypes: {
scope: React.PropTypes.string.isRequired,
type: React.PropTypes.string.isRequired,
action: React.PropTypes.func.isRequired,
enabled: React.PropTypes.bool.isRequired
},
getDefaultProps: function() {
return {enabled: true};
},
handleClick: function() {
this.props.action();
},
_getClasses: function() {
var cx = React.addons.classSet;
// classes
var classesObj = {
"btn": true,
"media-control": true,
"local-media": this.props.scope === "local",
"muted": !this.props.enabled
};
classesObj["btn-mute-" + this.props.type] = true;
return cx(classesObj);
},
_getTitle: function(enabled) {
var prefix = this.props.enabled ? "mute" : "unmute";
var suffix = "button_title";
var msgId = [prefix, this.props.scope, this.props.type, suffix].join("_");
return __(msgId);
},
render: function() {
return (
<button className={this._getClasses()}
title={this._getTitle()}
onClick={this.handleClick}></button>
);
}
});
/**
* Conversation controls.
*/
var ConversationToolbar = React.createClass({
getDefaultProps: function() {
return {
video: {enabled: true},
audio: {enabled: true}
};
},
propTypes: {
video: React.PropTypes.object.isRequired,
audio: React.PropTypes.object.isRequired,
hangup: React.PropTypes.func.isRequired,
publishStream: React.PropTypes.func.isRequired
},
handleClickHangup: function() {
this.props.hangup();
},
handleToggleVideo: function() {
this.props.publishStream("video", !this.props.video.enabled);
},
handleToggleAudio: function() {
this.props.publishStream("audio", !this.props.audio.enabled);
},
render: function() {
return (
<ul className="controls">
<li><button className="btn btn-hangup"
onClick={this.handleClickHangup}
title={__("hangup_button_title")}></button></li>
<li><MediaControlButton action={this.handleToggleVideo}
enabled={this.props.video.enabled}
scope="local" type="video" /></li>
<li><MediaControlButton action={this.handleToggleAudio}
enabled={this.props.audio.enabled}
scope="local" type="audio" /></li>
</ul>
);
}
});
var ConversationView = React.createClass({
mixins: [Backbone.Events],
propTypes: {
sdk: React.PropTypes.object.isRequired,
model: React.PropTypes.object.isRequired
},
// height set to "auto" to fix video layout on Google Chrome
// @see https://bugzilla.mozilla.org/show_bug.cgi?id=991122
publisherConfig: {
width: "100%",
height: "auto",
style: {
bugDisplayMode: "off",
buttonDisplayMode: "off",
nameDisplayMode: "off"
}
},
getInitialState: function() {
return {
video: {enabled: false},
audio: {enabled: false}
};
},
componentDidMount: function() {
this.props.model.startSession();
},
componentWillMount: function() {
this.listenTo(this.props.model, "session:connected",
this.startPublishing);
this.listenTo(this.props.model, "session:stream-created",
this._streamCreated);
this.listenTo(this.props.model, ["session:peer-hungup",
"session:network-disconnected",
"session:ended"].join(" "),
this.stopPublishing);
},
componentWillUnmount: function() {
this.hangup();
},
hangup: function() {
this.stopPublishing();
this.props.model.endSession();
},
/**
* Subscribes and attaches each created stream to a DOM element.
*
* XXX: for now we only support a single remote stream, hence a single DOM
* element.
*
* http://tokbox.com/opentok/libraries/client/js/reference/StreamEvent.html
*
* @param {StreamEvent} event
*/
_streamCreated: function(event) {
var incoming = this.getDOMNode().querySelector(".incoming");
event.streams.forEach(function(stream) {
if (stream.connection.connectionId !==
this.props.model.session.connection.connectionId) {
this.props.model.session.subscribe(stream, incoming,
this.publisherConfig);
}
}, this);
},
/**
* Publishes remote streams available once a session is connected.
*
* http://tokbox.com/opentok/libraries/client/js/reference/SessionConnectEvent.html
*
* @param {SessionConnectEvent} event
*/
startPublishing: function(event) {
var outgoing = this.getDOMNode().querySelector(".outgoing");
// XXX move this into its StreamingVideo component?
this.publisher = this.props.sdk.initPublisher(
outgoing, this.publisherConfig);
// Suppress OT GuM custom dialog, see bug 1018875
function preventOpeningAccessDialog(event) {
event.preventDefault();
}
this.publisher.on("accessDialogOpened", preventOpeningAccessDialog);
this.publisher.on("accessDenied", preventOpeningAccessDialog);
this.publisher.on("streamCreated", function(event) {
this.setState({
audio: {enabled: event.stream.hasAudio},
video: {enabled: event.stream.hasVideo}
});
}.bind(this));
this.publisher.on("streamDestroyed", function() {
this.setState({
audio: {enabled: false},
video: {enabled: false}
});
}.bind(this));
this.props.model.session.publish(this.publisher);
},
/**
* Toggles streaming status for a given stream type.
*
* @param {String} type Stream type ("audio" or "video").
* @param {Boolean} enabled Enabled stream flag.
*/
publishStream: function(type, enabled) {
if (type === "audio") {
this.publisher.publishAudio(enabled);
this.setState({audio: {enabled: enabled}});
} else {
this.publisher.publishVideo(enabled);
this.setState({video: {enabled: enabled}});
}
},
/**
* Unpublishes local stream.
*/
stopPublishing: function() {
// Unregister access OT GuM custom dialog listeners, see bug 1018875
this.publisher.off("accessDialogOpened");
this.publisher.off("accessDenied");
this.props.model.session.unpublish(this.publisher);
},
render: function() {
return (
<div className="conversation">
<ConversationToolbar video={this.state.video}
audio={this.state.audio}
publishStream={this.publishStream}
hangup={this.hangup} />
<div className="media nested">
<div className="remote"><div className="incoming"></div></div>
<div className="local"><div className="outgoing"></div></div>
</div>
</div>
);
}
});
/**
* Notification view.
*/
var NotificationView = BaseView.extend({
template: _.template([
'<div class="alert alert-<%- level %>">',
' <button class="close"></button>',
' <p class="message"><%- message %></p>',
'</div>'
].join("")),
events: {
"click .close": "dismiss"
},
dismiss: function(event) {
event.preventDefault();
this.$el.addClass("fade-out");
setTimeout(function() {
this.collection.remove(this.model);
this.remove();
}.bind(this), 500); // XXX make timeout value configurable
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
/**
* Notification list view.
*/
var NotificationListView = Backbone.View.extend({
/**
* Constructor.
*
* Available options:
* - {loop.shared.models.NotificationCollection} collection Notifications
* collection
*
* @param {Object} options Options object
*/
initialize: function(options) {
options = options || {};
if (!options.collection) {
this.collection = new sharedModels.NotificationCollection();
}
this.listenTo(this.collection, "reset add remove", this.render);
},
/**
* Clears the notification stack.
*/
clear: function() {
this.collection.reset();
},
/**
* Adds a new notification to the stack, triggering rendering of it.
*
* @param {Object|NotificationModel} notification Notification data.
*/
notify: function(notification) {
this.collection.add(notification);
},
/**
* Adds a new notification to the stack using an l10n message identifier,
* triggering rendering of it.
*
* @param {String} messageId L10n message id
* @param {String} level Notification level
*/
notifyL10n: function(messageId, level) {
this.notify({
message: l10n.get(messageId),
level: level
});
},
/**
* Adds a warning notification to the stack and renders it.
*
* @return {String} message
*/
warn: function(message) {
this.notify({level: "warning", message: message});
},
/**
* Adds a l10n warning notification to the stack and renders it.
*
* @param {String} messageId L10n message id
*/
warnL10n: function(messageId) {
this.warn(l10n.get(messageId));
},
/**
* Adds an error notification to the stack and renders it.
*
* @return {String} message
*/
error: function(message) {
this.notify({level: "error", message: message});
},
/**
* Adds a l10n rror notification to the stack and renders it.
*
* @param {String} messageId L10n message id
*/
errorL10n: function(messageId) {
this.error(l10n.get(messageId));
},
/**
* Renders this view.
*
* @return {loop.shared.views.NotificationListView}
*/
render: function() {
this.$el.html(this.collection.map(function(notification) {
return new NotificationView({
model: notification,
collection: this.collection
}).render().$el;
}.bind(this)));
return this;
}
});
/**
* Unsupported Browsers view.
*/
var UnsupportedBrowserView = BaseView.extend({
template: _.template([
'<div>',
' <h2 data-l10n-id="incompatible_browser"></h2>',
' <p data-l10n-id="powered_by_webrtc"></p>',
' <p data-l10n-id="use_latest_firefox" ',
' data-l10n-args=\'{"ff_url": "https://www.mozilla.org/firefox/"}\'>',
' </p>',
'</div>'
].join(""))
});
/**
* Unsupported Browsers view.
*/
var UnsupportedDeviceView = BaseView.extend({
template: _.template([
'<div>',
' <h2 data-l10n-id="incompatible_device"></h2>',
' <p data-l10n-id="sorry_device_unsupported"></p>',
' <p data-l10n-id="use_firefox_windows_mac_linux"></p>',
'</div>'
].join(""))
});
return {
L10nView: L10nView,
BaseView: BaseView,
ConversationView: ConversationView,
ConversationToolbar: ConversationToolbar,
MediaControlButton: MediaControlButton,
NotificationListView: NotificationListView,
NotificationView: NotificationView,
UnsupportedBrowserView: UnsupportedBrowserView,
UnsupportedDeviceView: UnsupportedDeviceView
};
})(_, window.OT, document.webL10n || document.mozL10n);

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

@ -25,8 +25,6 @@ browser.jar:
content/browser/loop/shared/img/icon_32.png (content/shared/img/icon_32.png)
content/browser/loop/shared/img/icon_64.png (content/shared/img/icon_64.png)
content/browser/loop/shared/img/loading-icon.gif (content/shared/img/loading-icon.gif)
content/browser/loop/shared/img/audio-highlight-14x14.png (content/shared/img/audio-highlight-14x14.png)
content/browser/loop/shared/img/audio-highlight-14x14@2x.png (content/shared/img/audio-highlight-14x14@2x.png)
content/browser/loop/shared/img/audio-inverse-14x14.png (content/shared/img/audio-inverse-14x14.png)
content/browser/loop/shared/img/audio-inverse-14x14@2x.png (content/shared/img/audio-inverse-14x14@2x.png)
content/browser/loop/shared/img/facemute-14x14.png (content/shared/img/facemute-14x14.png)
@ -35,8 +33,6 @@ browser.jar:
content/browser/loop/shared/img/hangup-inverse-14x14@2x.png (content/shared/img/hangup-inverse-14x14@2x.png)
content/browser/loop/shared/img/mute-inverse-14x14.png (content/shared/img/mute-inverse-14x14.png)
content/browser/loop/shared/img/mute-inverse-14x14@2x.png (content/shared/img/mute-inverse-14x14@2x.png)
content/browser/loop/shared/img/video-highlight-14x14.png (content/shared/img/video-highlight-14x14.png)
content/browser/loop/shared/img/video-highlight-14x14@2x.png (content/shared/img/video-highlight-14x14@2x.png)
content/browser/loop/shared/img/video-inverse-14x14.png (content/shared/img/video-inverse-14x14.png)
content/browser/loop/shared/img/video-inverse-14x14@2x.png (content/shared/img/video-inverse-14x14@2x.png)

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

@ -24,6 +24,7 @@
<!-- libs -->
<script src="https://static.opentok.com/webrtc/v2.2/js/opentok.min.js"></script>
<script type="text/javascript" src="libs/webl10n-20130617.js"></script>
<script type="text/javascript" src="shared/libs/react-0.10.0.js"></script>
<script type="text/javascript" src="shared/libs/jquery-2.1.0.js"></script>
<script type="text/javascript" src="shared/libs/lodash-2.4.1.js"></script>
<script type="text/javascript" src="shared/libs/backbone-1.1.2.js"></script>

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

@ -189,7 +189,7 @@ loop.webapp = (function($, _, OT) {
// User has loaded this url directly, actually setup the call.
return this.navigate("call/" + loopToken, {trigger: true});
}
this.loadView(new sharedViews.ConversationView({
this.loadReactComponent(sharedViews.ConversationView({
sdk: OT,
model: this._conversation
}));

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

@ -4,11 +4,11 @@ missing_conversation_info=Missing conversation information.
network_disconnected=The network connection terminated abruptly.
peer_ended_conversation=Your peer ended the conversation.
unable_retrieve_call_info=Unable to retrieve conversation information.
hangup_button.title=Hangup
mute_local_audio_button.title=Mute your audio
unmute_local_audio_button.title=Unute your audio
mute_local_video_button.title=Mute your video
unmute_local_video_button.title=Unmute your video
hangup_button_title=Hangup
mute_local_audio_button_title=Mute your audio
unmute_local_audio_button_title=Unute your audio
mute_local_video_button_title=Mute your video
unmute_local_video_button_title=Unmute your video
start_call=Start the call
welcome=Welcome to the Loop web client.
incompatible_browser=Incompatible Browser
@ -25,11 +25,11 @@ missing_conversation_info=Informations de communication manquantes.
network_disconnected=La connexion réseau semble avoir été interrompue.
peer_ended_conversation=Votre correspondant a mis fin à la communication.
unable_retrieve_call_info=Impossible de récupérer les informations liées à cet appel.
hangup_button.title=Terminer l'appel
mute_local_audio_button.title=Couper la diffusion audio
unmute_local_audio_button.title=Reprendre la diffusion audio
mute_local_video_button.title=Couper la diffusion vidéo
unmute_local_video_button.title=Reprendre la diffusion vidéo
hangup_button_title=Terminer l'appel
mute_local_audio_button_title=Couper la diffusion audio
unmute_local_audio_button_title=Reprendre la diffusion audio
mute_local_video_button_title=Couper la diffusion vidéo
unmute_local_video_button_title=Reprendre la diffusion vidéo
start_call=Démarrer l'appel
welcome=Bienvenue sur Loop.
incompatible_browser=Navigateur non supporté

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

@ -157,23 +157,28 @@ describe("loop.conversation", function() {
});
describe("#conversation", function() {
beforeEach(function() {
sandbox.stub(router, "loadReactComponent");
});
it("should load the ConversationView if session is set", function() {
sandbox.stub(loop.shared.views.ConversationView.prototype,
"initialize");
conversation.set("sessionId", "fakeSessionId");
router.conversation();
sinon.assert.calledOnce(router.loadView);
sinon.assert.calledWith(router.loadView,
sinon.match.instanceOf(loop.shared.views.ConversationView));
sinon.assert.calledOnce(router.loadReactComponent);
sinon.assert.calledWith(router.loadReactComponent,
sinon.match(function(value) {
return React.addons.TestUtils.isComponentOfType(
value, loop.shared.views.ConversationView);
}));
});
it("should not load the ConversationView if session is not set",
function() {
router.conversation();
sinon.assert.notCalled(router.loadView);
sinon.assert.notCalled(router.loadReactComponent);
});
it("should notify the user when session is not set",

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

@ -16,10 +16,11 @@
<div id="fixtures"></div>
<!-- libs -->
<script src="../../content/shared/libs/react-0.10.0.js"></script>
<script src="../../content/shared/libs/jquery-2.1.0.js"></script>
<script src="../../content/shared/libs/lodash-2.4.1.js"></script>
<script src="../../content/shared/libs/backbone-1.1.2.js"></script>
<script src="../../standalone/content/libs/webl10n-20130617.js"></script>
<script src="../../standalone/content/libs/webl10n-20130617.js"></script>
<!-- test dependencies -->
<script src="vendor/mocha-1.17.1.js"></script>

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

@ -2,16 +2,19 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global loop, sinon */
/*global loop, sinon, React */
/* jshint newcap:false */
var expect = chai.expect;
var l10n = document.webL10n || document.mozL10n;
var TestUtils = React.addons.TestUtils;
describe("loop.shared.views", function() {
"use strict";
var sharedModels = loop.shared.models,
sharedViews = loop.shared.views,
getReactElementByClass = TestUtils.findRenderedDOMComponentWithClass,
sandbox;
beforeEach(function() {
@ -40,9 +43,143 @@ describe("loop.shared.views", function() {
});
});
describe("MediaControlButton", function() {
it("should render an enabled local audio button", function() {
var comp = TestUtils.renderIntoDocument(sharedViews.MediaControlButton({
scope: "local",
type: "audio",
action: function(){},
enabled: true
}));
expect(comp.getDOMNode().classList.contains("muted")).eql(false);
});
it("should render a muted local audio button", function() {
var comp = TestUtils.renderIntoDocument(sharedViews.MediaControlButton({
scope: "local",
type: "audio",
action: function(){},
enabled: false
}));
expect(comp.getDOMNode().classList.contains("muted")).eql(true);
});
it("should render an enabled local video button", function() {
var comp = TestUtils.renderIntoDocument(sharedViews.MediaControlButton({
scope: "local",
type: "video",
action: function(){},
enabled: true
}));
expect(comp.getDOMNode().classList.contains("muted")).eql(false);
});
it("should render a muted local video button", function() {
var comp = TestUtils.renderIntoDocument(sharedViews.MediaControlButton({
scope: "local",
type: "video",
action: function(){},
enabled: false
}));
expect(comp.getDOMNode().classList.contains("muted")).eql(true);
});
});
describe("ConversationToolbar", function() {
var hangup, publishStream;
function mountTestComponent(props) {
return TestUtils.renderIntoDocument(
sharedViews.ConversationToolbar(props));
}
beforeEach(function() {
hangup = sandbox.stub();
publishStream = sandbox.stub();
});
it("should hangup when hangup button is clicked", function() {
var comp = mountTestComponent({
hangup: hangup,
publishStream: publishStream,
audio: {enabled: true}
});
TestUtils.Simulate.click(
comp.getDOMNode().querySelector(".btn-hangup"));
sinon.assert.calledOnce(hangup);
sinon.assert.calledWithExactly(hangup);
});
it("should unpublish audio when audio mute btn is clicked", function() {
var comp = mountTestComponent({
hangup: hangup,
publishStream: publishStream,
audio: {enabled: true}
});
TestUtils.Simulate.click(
comp.getDOMNode().querySelector(".btn-mute-audio"));
sinon.assert.calledOnce(publishStream);
sinon.assert.calledWithExactly(publishStream, "audio", false);
});
it("should publish audio when audio mute btn is clicked", function() {
var comp = mountTestComponent({
hangup: hangup,
publishStream: publishStream,
audio: {enabled: false}
});
TestUtils.Simulate.click(
comp.getDOMNode().querySelector(".btn-mute-audio"));
sinon.assert.calledOnce(publishStream);
sinon.assert.calledWithExactly(publishStream, "audio", true);
});
it("should unpublish video when video mute btn is clicked", function() {
var comp = mountTestComponent({
hangup: hangup,
publishStream: publishStream,
video: {enabled: true}
});
TestUtils.Simulate.click(
comp.getDOMNode().querySelector(".btn-mute-video"));
sinon.assert.calledOnce(publishStream);
sinon.assert.calledWithExactly(publishStream, "video", false);
});
it("should publish video when video mute btn is clicked", function() {
var comp = mountTestComponent({
hangup: hangup,
publishStream: publishStream,
video: {enabled: false}
});
TestUtils.Simulate.click(
comp.getDOMNode().querySelector(".btn-mute-video"));
sinon.assert.calledOnce(publishStream);
sinon.assert.calledWithExactly(publishStream, "video", true);
});
});
describe("ConversationView", function() {
var fakeSDK, fakeSessionData, fakeSession, fakePublisher, model;
function mountTestComponent(props) {
return TestUtils.renderIntoDocument(sharedViews.ConversationView(props));
}
beforeEach(function() {
fakeSessionData = {
sessionId: "sessionId",
@ -72,50 +209,46 @@ describe("loop.shared.views", function() {
});
});
describe("#initialize", function() {
it("should require a sdk object", function() {
expect(function() {
new sharedViews.ConversationView();
}).to.Throw(Error, /sdk/);
});
describe("#componentDidMount", function() {
it("should start a session", function() {
sandbox.stub(model, "startSession");
new sharedViews.ConversationView({sdk: fakeSDK, model: model});
mountTestComponent({sdk: fakeSDK, model: model});
sinon.assert.calledOnce(model.startSession);
});
});
describe("constructed", function() {
describe("#hangup", function() {
it("should disconnect the session", function() {
var view = new sharedViews.ConversationView({
sdk: fakeSDK,
model: model
});
sandbox.stub(model, "endSession");
view.publish();
var comp;
view.hangup({preventDefault: function() {}});
beforeEach(function() {
comp = mountTestComponent({sdk: fakeSDK, model: model});
});
describe("#hangup", function() {
beforeEach(function() {
comp.startPublishing();
});
it("should disconnect the session", function() {
sandbox.stub(model, "endSession");
comp.hangup();
sinon.assert.calledOnce(model.endSession);
});
it("should stop publishing local streams", function() {
comp.hangup();
sinon.assert.calledOnce(fakeSession.unpublish);
});
});
describe("#publish", function() {
var view;
beforeEach(function() {
view = new sharedViews.ConversationView({
sdk: fakeSDK,
model: model
});
});
describe("#startPublishing", function() {
it("should publish local stream", function() {
view.publish();
comp.startPublishing();
sinon.assert.calledOnce(fakeSDK.initPublisher);
sinon.assert.calledOnce(fakeSession.publish);
@ -124,7 +257,7 @@ describe("loop.shared.views", function() {
it("should start listening to OT publisher accessDialogOpened and " +
" accessDenied events",
function() {
view.publish();
comp.startPublishing();
sinon.assert.called(fakePublisher.on);
sinon.assert.calledWith(fakePublisher.on, "accessDialogOpened");
@ -132,26 +265,20 @@ describe("loop.shared.views", function() {
});
});
describe("#unpublish", function() {
var view;
describe("#stopPublishing", function() {
beforeEach(function() {
view = new sharedViews.ConversationView({
sdk: fakeSDK,
model: model
});
view.publish();
comp.startPublishing();
});
it("should unpublish local stream", function() {
view.unpublish();
it("should stop publish local stream", function() {
comp.stopPublishing();
sinon.assert.calledOnce(fakeSession.unpublish);
});
it("should unsubscribe from accessDialogOpened and accessDenied events",
function() {
view.unpublish();
comp.stopPublishing();
sinon.assert.calledTwice(fakePublisher.off);
sinon.assert.calledWith(fakePublisher.off, "accessDialogOpened");
@ -159,79 +286,48 @@ describe("loop.shared.views", function() {
});
});
describe("#toggleMuteAudio", function() {
var view;
describe("#publishStream", function() {
var comp;
beforeEach(function() {
view = new sharedViews.ConversationView({
sdk: fakeSDK,
model: model
});
view.publish();
comp = mountTestComponent({sdk: fakeSDK, model: model});
comp.startPublishing();
});
it("should unpublish local audio when enabled", function() {
view.localStream = {hasAudio: true};
it("should start streaming local audio", function() {
comp.publishStream("audio", true);
view.toggleMuteAudio({preventDefault: sandbox.spy()});
sinon.assert.calledOnce(fakePublisher.publishAudio);
sinon.assert.calledWithExactly(fakePublisher.publishAudio, true);
});
it("should stop streaming local audio", function() {
comp.publishStream("audio", false);
sinon.assert.calledOnce(fakePublisher.publishAudio);
sinon.assert.calledWithExactly(fakePublisher.publishAudio, false);
});
it("should publish local audio when disabled", function() {
view.localStream = {hasAudio: false};
view.toggleMuteAudio({preventDefault: sandbox.spy()});
sinon.assert.calledOnce(fakePublisher.publishAudio);
sinon.assert.calledWithExactly(fakePublisher.publishAudio, true);
});
});
describe("#toggleMuteVideo", function() {
var view;
beforeEach(function() {
view = new sharedViews.ConversationView({
sdk: fakeSDK,
model: model
});
view.publish();
});
it("should unpublish local video when enabled", function() {
view.localStream = {hasVideo: true};
view.toggleMuteVideo({preventDefault: sandbox.spy()});
sinon.assert.calledOnce(fakePublisher.publishVideo);
sinon.assert.calledWithExactly(fakePublisher.publishVideo, false);
});
it("should publish local video when disabled", function() {
view.localStream = {hasVideo: false};
view.toggleMuteVideo({preventDefault: sandbox.spy()});
it("should start streaming local video", function() {
comp.publishStream("video", true);
sinon.assert.calledOnce(fakePublisher.publishVideo);
sinon.assert.calledWithExactly(fakePublisher.publishVideo, true);
});
it("should stop streaming local video", function() {
comp.publishStream("video", false);
sinon.assert.calledOnce(fakePublisher.publishVideo);
sinon.assert.calledWithExactly(fakePublisher.publishVideo, false);
});
});
describe("Model events", function() {
var view;
beforeEach(function() {
sandbox.stub(sharedViews.ConversationView.prototype, "publish");
sandbox.stub(sharedViews.ConversationView.prototype, "unpublish");
view = new sharedViews.ConversationView({sdk: fakeSDK, model: model});
});
it("should publish local stream on session:connected", function() {
it("should start streaming on session:connected", function() {
model.trigger("session:connected");
sinon.assert.calledOnce(view.publish);
sinon.assert.calledOnce(fakeSDK.initPublisher);
});
it("should publish remote streams on session:stream-created",
@ -246,22 +342,28 @@ describe("loop.shared.views", function() {
});
it("should unpublish local stream on session:ended", function() {
comp.startPublishing();
model.trigger("session:ended");
sinon.assert.calledOnce(view.unpublish);
sinon.assert.calledOnce(fakeSession.unpublish);
});
it("should unpublish local stream on session:peer-hungup", function() {
comp.startPublishing();
model.trigger("session:peer-hungup");
sinon.assert.calledOnce(view.unpublish);
sinon.assert.calledOnce(fakeSession.unpublish);
});
it("should unpublish local stream on session:network-disconnected",
function() {
comp.startPublishing();
model.trigger("session:network-disconnected");
sinon.assert.calledOnce(view.unpublish);
sinon.assert.calledOnce(fakeSession.unpublish);
});
});
});

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

@ -16,6 +16,7 @@
<div id="messages"></div>
<div id="fixtures"></div>
<!-- libs -->
<script src="../../content/shared/libs/react-0.10.0.js"></script>
<script src="../../content/shared/libs/jquery-2.1.0.js"></script>
<script src="../../content/shared/libs/lodash-2.4.1.js"></script>
<script src="../../content/shared/libs/backbone-1.1.2.js"></script>

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

@ -75,6 +75,7 @@ describe("loop.webapp", function() {
notifier: notifier
});
sandbox.stub(router, "loadView");
sandbox.stub(router, "loadReactComponent");
sandbox.stub(router, "navigate");
});
@ -162,14 +163,16 @@ describe("loop.webapp", function() {
describe("#loadConversation", function() {
it("should load the ConversationView if session is set", function() {
sandbox.stub(sharedViews.ConversationView.prototype, "initialize");
conversation.set("sessionId", "fakeSessionId");
router.loadConversation();
sinon.assert.calledOnce(router.loadView);
sinon.assert.calledWith(router.loadView,
sinon.match.instanceOf(sharedViews.ConversationView));
sinon.assert.calledOnce(router.loadReactComponent);
sinon.assert.calledWith(router.loadReactComponent,
sinon.match(function(value) {
return React.addons.TestUtils.isComponentOfType(
value, loop.shared.views.ConversationView);
}));
});
it("should navigate to #call/{token} if session isn't ready",

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

@ -411,6 +411,8 @@
#endif
@BINPATH@/components/nsUpdateTimerManager.manifest
@BINPATH@/components/nsUpdateTimerManager.js
@BINPATH@/components/addoncompat.manifest
@BINPATH@/components/multiprocessShims.js
@BINPATH@/components/pluginGlue.manifest
@BINPATH@/browser/components/nsSessionStore.manifest
@BINPATH@/browser/components/nsSessionStartup.js

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

@ -18,11 +18,11 @@ incoming_call_title=Incoming Call…
incoming_call=Incoming call
accept_button=Accept
decline_button=Decline
hangup_button.title=Hangup
mute_local_audio_button.title=Mute your audio
unmute_local_audio_button.title=Unute your audio
mute_local_video_button.title=Mute your video
unmute_local_video_button.title=Unmute your video
hangup_button_title=Hangup
mute_local_audio_button_title=Mute your audio
unmute_local_audio_button_title=Unmute your audio
mute_local_video_button_title=Mute your video
unmute_local_video_button_title=Unmute your video
peer_ended_conversation=Your peer ended the conversation.
call_has_ended=Your call has ended.

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

@ -842,7 +842,7 @@ this.UITour = {
highlighter.style.width = highlightWidth + "px";
// Close a previous highlight so we can relocate the panel.
if (highlighter.parentElement.state == "open") {
if (highlighter.parentElement.state == "showing" || highlighter.parentElement.state == "open") {
highlighter.parentElement.hidePopup();
}
/* The "overlap" position anchors from the top-left but we want to centre highlights at their
@ -909,7 +909,7 @@ this.UITour = {
let tooltipIcon = document.getElementById("UITourTooltipIcon");
let tooltipButtons = document.getElementById("UITourTooltipButtons");
if (tooltip.state == "open") {
if (tooltip.state == "showing" || tooltip.state == "open") {
tooltip.hidePopup();
}

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

@ -24,9 +24,9 @@ skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
[browser_UITour_detach_tab.js]
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
[browser_UITour_annotation_size_attributes.js]
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
[browser_UITour_panel_close_annotation.js]
skip-if = e10s || os == "win" # Bug 941428 - UITour.jsm not e10s friendly. Intermittent test failures on Windows (bug 1026310 & bug 1032137)
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
[browser_UITour_registerPageID.js]
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
[browser_UITour_sync.js]

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

@ -11339,7 +11339,7 @@ public:
mDocument(do_GetWeakReference(aElement->OwnerDoc())),
mUserInputOrChromeCaller(aUserInputOrChromeCaller) {}
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSICONTENTPERMISSIONREQUEST
NS_IMETHOD Run()

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

@ -19,7 +19,7 @@ class EncodingCompleteEvent : public nsRunnable
virtual ~EncodingCompleteEvent() {}
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
EncodingCompleteEvent(nsIGlobalObject* aGlobal,
nsIThread* aEncoderThread,
@ -85,14 +85,14 @@ private:
bool mFailed;
};
NS_IMPL_ISUPPORTS(EncodingCompleteEvent, nsIRunnable);
NS_IMPL_ISUPPORTS_INHERITED0(EncodingCompleteEvent, nsRunnable);
class EncodingRunnable : public nsRunnable
{
virtual ~EncodingRunnable() {}
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
EncodingRunnable(const nsAString& aType,
const nsAString& aOptions,
@ -180,7 +180,7 @@ private:
bool mUsingCustomOptions;
};
NS_IMPL_ISUPPORTS(EncodingRunnable, nsIRunnable)
NS_IMPL_ISUPPORTS_INHERITED0(EncodingRunnable, nsRunnable);
/* static */
nsresult

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

@ -14,7 +14,7 @@
namespace {
class TimerEvent : public nsITimerCallback, public nsRunnable {
typedef mozilla::MediaDecoderStateMachineScheduler Scheduler;
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
public:
TimerEvent(Scheduler* aScheduler, int aTimerId)
: mScheduler(aScheduler), mTimerId(aTimerId) {}
@ -32,7 +32,7 @@ private:
const int mTimerId;
};
NS_IMPL_ISUPPORTS(TimerEvent, nsITimerCallback, nsIRunnable);
NS_IMPL_ISUPPORTS_INHERITED(TimerEvent, nsRunnable, nsITimerCallback);
} // anonymous namespace
static already_AddRefed<nsIEventTarget>

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

@ -129,12 +129,14 @@ SourceBufferResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCo
bool
SourceBufferResource::EvictData(uint32_t aThreshold)
{
ReentrantMonitorAutoEnter mon(mMonitor);
return mInputBuffer.Evict(mOffset, aThreshold);
}
void
SourceBufferResource::EvictBefore(uint64_t aOffset)
{
ReentrantMonitorAutoEnter mon(mMonitor);
// If aOffset is past the current playback offset we don't evict.
if (aOffset < mOffset) {
mInputBuffer.Evict(aOffset, 0);

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

@ -72,11 +72,6 @@ private:
};
class ResourceQueue : private nsDeque {
private:
// Logical offset into the resource of the first element
// in the queue.
uint64_t mOffset;
public:
ResourceQueue() :
nsDeque(new ResourceQueueDeallocator()),
@ -84,25 +79,11 @@ private:
{
}
// Clears all items from the queue
inline void Clear() {
return nsDeque::Erase();
}
// Returns the number of items in the queue
inline uint32_t GetSize() {
return nsDeque::GetSize();
}
// Returns the logical byte offset of the start of the data.
inline uint64_t GetOffset() {
return mOffset;
}
inline ResourceItem* ResourceAt(uint32_t aIndex) {
return static_cast<ResourceItem*>(nsDeque::ObjectAt(aIndex));
}
// Returns the length of all items in the queue plus the offset.
// This is the logical length of the resource.
inline uint64_t GetLength() {
@ -114,29 +95,6 @@ private:
return s;
}
// Returns the index of the resource that contains the given
// logical offset. aResourceOffset will contain the offset into
// the resource at the given index returned if it is not null. If
// no such resource exists, returns GetSize() and aOffset is
// untouched.
inline uint32_t GetAtOffset(uint64_t aOffset, uint32_t *aResourceOffset) {
MOZ_ASSERT(aOffset >= mOffset);
uint64_t offset = mOffset;
for (uint32_t i = 0; i < GetSize(); ++i) {
ResourceItem* item = ResourceAt(i);
// If the item contains the start of the offset we want to
// break out of the loop.
if (item->mData.Length() + offset > aOffset) {
if (aResourceOffset) {
*aResourceOffset = aOffset - offset;
}
return i;
}
offset += item->mData.Length();
}
return GetSize();
}
// Copies aCount bytes from aOffset in the queue into aDest.
inline void CopyData(uint64_t aOffset, uint32_t aCount, char* aDest) {
uint32_t offset = 0;
@ -158,18 +116,6 @@ private:
nsDeque::Push(aItem);
}
inline void PushFront(ResourceItem* aItem) {
nsDeque::PushFront(aItem);
}
inline ResourceItem* PopBack() {
return static_cast<ResourceItem*>(nsDeque::Pop());
}
inline ResourceItem* PopFront() {
return static_cast<ResourceItem*>(nsDeque::PopFront());
}
// Evict data in queue if the total queue size is greater than
// aThreshold past the offset. Returns true if some data was
// actually evicted.
@ -200,6 +146,47 @@ private:
return size;
}
private:
// Returns the number of items in the queue
inline uint32_t GetSize() {
return nsDeque::GetSize();
}
inline ResourceItem* ResourceAt(uint32_t aIndex) {
return static_cast<ResourceItem*>(nsDeque::ObjectAt(aIndex));
}
// Returns the index of the resource that contains the given
// logical offset. aResourceOffset will contain the offset into
// the resource at the given index returned if it is not null. If
// no such resource exists, returns GetSize() and aOffset is
// untouched.
inline uint32_t GetAtOffset(uint64_t aOffset, uint32_t *aResourceOffset) {
MOZ_ASSERT(aOffset >= mOffset);
uint64_t offset = mOffset;
for (uint32_t i = 0; i < GetSize(); ++i) {
ResourceItem* item = ResourceAt(i);
// If the item contains the start of the offset we want to
// break out of the loop.
if (item->mData.Length() + offset > aOffset) {
if (aResourceOffset) {
*aResourceOffset = aOffset - offset;
}
return i;
}
offset += item->mData.Length();
}
return GetSize();
}
inline ResourceItem* PopFront() {
return static_cast<ResourceItem*>(nsDeque::PopFront());
}
// Logical offset into the resource of the first element
// in the queue.
uint64_t mOffset;
};
public:

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

@ -346,7 +346,6 @@ public:
// on requests.
nsRefPtr<MediaResourceServer> mServer;
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISERVERSOCKETLISTENER
@ -355,6 +354,7 @@ public:
{
}
private:
virtual ~ResourceSocketListener() { }
};

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

@ -117,6 +117,8 @@ NS_IMPL_RELEASE(WMFByteStream)
// Stores data regarding an async read opreation.
class ReadRequest MOZ_FINAL : public IUnknown {
~ReadRequest() {}
public:
ReadRequest(int64_t aOffset, BYTE* aBuffer, ULONG aLength)
: mOffset(aOffset),
@ -394,17 +396,17 @@ STDMETHODIMP
WMFByteStream::Read(BYTE* aBuffer, ULONG aBufferLength, ULONG* aOutBytesRead)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
ReadRequest request(mOffset, aBuffer, aBufferLength);
if (NS_FAILED(Read(&request))) {
nsRefPtr<ReadRequest> request = new ReadRequest(mOffset, aBuffer, aBufferLength);
if (NS_FAILED(Read(request))) {
WMF_BS_LOG("[%p] WMFByteStream::Read() offset=%lld failed!", this, mOffset);
return E_FAIL;
}
if (aOutBytesRead) {
*aOutBytesRead = request.mBytesRead;
*aOutBytesRead = request->mBytesRead;
}
WMF_BS_LOG("[%p] WMFByteStream::Read() offset=%lld length=%u bytesRead=%u",
this, mOffset, aBufferLength, request.mBytesRead);
mOffset += request.mBytesRead;
this, mOffset, aBufferLength, request->mBytesRead);
mOffset += request->mBytesRead;
return S_OK;
}

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

@ -36,9 +36,10 @@ class SharedThreadPool;
class WMFByteStream MOZ_FINAL : public IMFByteStream
, public IMFAttributes
{
~WMFByteStream();
public:
WMFByteStream(MediaResource* aResource, WMFSourceReaderCallback* aCallback);
~WMFByteStream();
nsresult Init();
nsresult Shutdown();

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

@ -21,6 +21,8 @@ namespace mozilla {
// when the MediaResource is unexpectedly shutdown.
class WMFSourceReaderCallback MOZ_FINAL : public IMFSourceReaderCallback
{
~WMFSourceReaderCallback() {}
public:
WMFSourceReaderCallback();

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

@ -1213,7 +1213,7 @@ MappedAttrParser::CreateStyleRule()
return nullptr; // No mapped attributes were parsed
}
nsRefPtr<css::StyleRule> rule = new css::StyleRule(nullptr, mDecl);
nsRefPtr<css::StyleRule> rule = new css::StyleRule(nullptr, mDecl, 0, 0);
mDecl = nullptr; // We no longer own the declaration -- drop our pointer to it
return rule.forget();
}

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

@ -3399,12 +3399,20 @@ this.DOMApplicationRegistry = {
debug("Setting origin to " + uri.prePath +
" for " + aOldApp.manifestURL);
let newId = uri.prePath.substring(6); // "app://".length
if (newId in this.webapps) {
if (newId in this.webapps && this._isLaunchable(this.webapps[newId])) {
throw "DUPLICATE_ORIGIN";
}
aOldApp.origin = uri.prePath;
// Update the registry.
let oldId = aOldApp.id;
if (oldId == newId) {
// This could happen when we have an app in the registry
// that is not launchable. Since the app already has
// the correct id, we don't need to change it.
return;
}
aOldApp.id = newId;
this.webapps[newId] = aOldApp;
delete this.webapps[oldId];

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

@ -2196,33 +2196,6 @@ Navigator::HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */)
return !!pmService;
}
/* static */
bool
Navigator::HasMobileMessageSupport(JSContext* /* unused */, JSObject* aGlobal)
{
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
#ifndef MOZ_WEBSMS_BACKEND
return false;
#endif
// First of all, the general pref has to be turned on.
bool enabled = false;
Preferences::GetBool("dom.sms.enabled", &enabled);
if (!enabled) {
return false;
}
NS_ENSURE_TRUE(win, false);
NS_ENSURE_TRUE(win->GetDocShell(), false);
if (!CheckPermission(win, "sms")) {
return false;
}
return true;
}
/* static */
bool
Navigator::HasCameraSupport(JSContext* /* unused */, JSObject* aGlobal)
@ -2268,16 +2241,6 @@ Navigator::HasNFCSupport(JSContext* /* unused */, JSObject* aGlobal)
}
#endif // MOZ_NFC
#ifdef MOZ_TIME_MANAGER
/* static */
bool
Navigator::HasTimeSupport(JSContext* /* unused */, JSObject* aGlobal)
{
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
return win && CheckPermission(win, "time");
}
#endif // MOZ_TIME_MANAGER
#ifdef MOZ_MEDIA_NAVIGATOR
/* static */
bool
@ -2379,22 +2342,6 @@ Navigator::HasDataStoreSupport(JSContext* aCx, JSObject* aGlobal)
return HasDataStoreSupport(doc->NodePrincipal());
}
/* static */
bool
Navigator::HasNetworkStatsSupport(JSContext* /* unused */, JSObject* aGlobal)
{
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
return CheckPermission(win, "networkstats-manage");
}
/* static */
bool
Navigator::HasFeatureDetectionSupport(JSContext* /* unused */, JSObject* aGlobal)
{
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
return CheckPermission(win, "feature-detection");
}
#ifdef MOZ_B2G
/* static */
bool

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

@ -268,8 +268,6 @@ public:
// WebIDL helper methods
static bool HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */);
static bool HasMobileMessageSupport(JSContext* /* unused */,
JSObject* aGlobal);
static bool HasCameraSupport(JSContext* /* unused */,
JSObject* aGlobal);
static bool HasWifiManagerSupport(JSContext* /* unused */,
@ -277,9 +275,6 @@ public:
#ifdef MOZ_NFC
static bool HasNFCSupport(JSContext* /* unused */, JSObject* aGlobal);
#endif // MOZ_NFC
#ifdef MOZ_TIME_MANAGER
static bool HasTimeSupport(JSContext* /* unused */, JSObject* aGlobal);
#endif // MOZ_TIME_MANAGER
#ifdef MOZ_MEDIA_NAVIGATOR
static bool HasUserMediaSupport(JSContext* /* unused */,
JSObject* /* unused */);
@ -291,10 +286,6 @@ public:
static bool HasDataStoreSupport(JSContext* cx, JSObject* aGlobal);
static bool HasNetworkStatsSupport(JSContext* aCx, JSObject* aGlobal);
static bool HasFeatureDetectionSupport(JSContext* aCx, JSObject* aGlobal);
#ifdef MOZ_B2G
static bool HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal);
#endif

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

@ -370,10 +370,9 @@ AsyncErrorReporter::AsyncErrorReporter(JSRuntime* aRuntime,
const char16_t* m = static_cast<const char16_t*>(aErrorReport->ucmessage);
if (m) {
const char16_t* n = static_cast<const char16_t*>
(js::GetErrorTypeName(aRuntime, aErrorReport->exnType));
if (n) {
mErrorMsg.Assign(n);
JSFlatString* name = js::GetErrorTypeName(aRuntime, aErrorReport->exnType);
if (name) {
AssignJSFlatString(mErrorMsg, name);
mErrorMsg.AppendLiteral(": ");
}
mErrorMsg.Append(m);

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

@ -365,9 +365,12 @@ InterfaceObjectToString(JSContext* cx, unsigned argc, JS::Value *vp)
const JSClass* clasp = static_cast<const JSClass*>(v.toPrivate());
v = js::GetFunctionNativeReserved(callee, TOSTRING_NAME_RESERVED_SLOT);
JSString* jsname = static_cast<JSString*>(v.toString());
size_t length;
const jschar* name = JS_GetInternedStringCharsAndLength(jsname, &length);
JSString* jsname = v.toString();
nsAutoJSString name;
if (!name.init(cx, jsname)) {
return false;
}
if (js::GetObjectJSClass(&args.thisv().toObject()) != clasp) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
@ -379,7 +382,7 @@ InterfaceObjectToString(JSContext* cx, unsigned argc, JS::Value *vp)
nsString str;
str.AppendLiteral("function ");
str.Append(name, length);
str.Append(name);
str.AppendLiteral("() {");
str.Append('\n');
str.AppendLiteral(" [native code]");

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

@ -24,6 +24,7 @@
#define WEBCRYPTO_ALG_PBKDF2 "PBKDF2"
#define WEBCRYPTO_ALG_RSAES_PKCS1 "RSAES-PKCS1-v1_5"
#define WEBCRYPTO_ALG_RSASSA_PKCS1 "RSASSA-PKCS1-v1_5"
#define WEBCRYPTO_ALG_RSA_OAEP "RSA-OAEP"
// WebCrypto key formats
#define WEBCRYPTO_KEY_FORMAT_RAW "raw"
@ -146,6 +147,8 @@ MapAlgorithmNameToMechanism(const nsString& aName)
mechanism = CKM_RSA_PKCS;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
mechanism = CKM_RSA_PKCS;
} else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
mechanism = CKM_RSA_PKCS_OAEP;
}
return mechanism;

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

@ -303,7 +303,7 @@ class AesTask : public ReturnArrayBufferViewTask
{
public:
AesTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
mozilla::dom::CryptoKey& aKey, const CryptoOperationData& aData,
CryptoKey& aKey, const CryptoOperationData& aData,
bool aEncrypt)
: mSymKey(aKey.GetSymKey())
, mEncrypt(aEncrypt)
@ -480,7 +480,7 @@ class RsaesPkcs1Task : public ReturnArrayBufferViewTask
{
public:
RsaesPkcs1Task(JSContext* aCx, const ObjectOrString& aAlgorithm,
mozilla::dom::CryptoKey& aKey, const CryptoOperationData& aData,
CryptoKey& aKey, const CryptoOperationData& aData,
bool aEncrypt)
: mPrivKey(aKey.GetPrivateKey())
, mPubKey(aKey.GetPublicKey())
@ -549,11 +549,134 @@ private:
}
};
class RsaOaepTask : public ReturnArrayBufferViewTask
{
public:
RsaOaepTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
CryptoKey& aKey, const CryptoOperationData& aData,
bool aEncrypt)
: mPrivKey(aKey.GetPrivateKey())
, mPubKey(aKey.GetPublicKey())
, mEncrypt(aEncrypt)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_RSA_OAEP);
ATTEMPT_BUFFER_INIT(mData, aData);
if (mEncrypt) {
if (!mPubKey) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
return;
}
mStrength = SECKEY_PublicKeyStrength(mPubKey);
} else {
if (!mPrivKey) {
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
return;
}
mStrength = PK11_GetPrivateModulusLen(mPrivKey);
}
RootedDictionary<RsaOaepParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
if (params.mLabel.WasPassed() && !params.mLabel.Value().IsNull()) {
ATTEMPT_BUFFER_INIT(mLabel, params.mLabel.Value().Value());
}
// Otherwise mLabel remains the empty octet string, as intended
// Look up the MGF based on the KeyAlgorithm.
// static_cast is safe because we only get here if the algorithm name
// is RSA-OAEP, and that only happens if we've constructed
// an RsaHashedKeyAlgorithm.
// TODO: Add As* methods to KeyAlgorithm (Bug 1036734)
nsRefPtr<RsaHashedKeyAlgorithm> rsaAlg =
static_cast<RsaHashedKeyAlgorithm*>(aKey.Algorithm());
mHashMechanism = rsaAlg->Hash()->Mechanism();
switch (mHashMechanism) {
case CKM_SHA_1:
mMgfMechanism = CKG_MGF1_SHA1; break;
case CKM_SHA256:
mMgfMechanism = CKG_MGF1_SHA256; break;
case CKM_SHA384:
mMgfMechanism = CKG_MGF1_SHA384; break;
case CKM_SHA512:
mMgfMechanism = CKG_MGF1_SHA512; break;
default: {
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
}
}
}
private:
CK_MECHANISM_TYPE mHashMechanism;
CK_MECHANISM_TYPE mMgfMechanism;
ScopedSECKEYPrivateKey mPrivKey;
ScopedSECKEYPublicKey mPubKey;
CryptoBuffer mLabel;
CryptoBuffer mData;
uint32_t mStrength;
bool mEncrypt;
virtual nsresult DoCrypto() MOZ_OVERRIDE
{
nsresult rv;
// Ciphertext is an integer mod the modulus, so it will be
// no longer than mStrength octets
if (!mResult.SetLength(mStrength)) {
return NS_ERROR_DOM_UNKNOWN_ERR;
}
CK_RSA_PKCS_OAEP_PARAMS oaepParams;
oaepParams.source = CKZ_DATA_SPECIFIED;
oaepParams.pSourceData = mLabel.Length() ? mLabel.Elements() : nullptr;
oaepParams.ulSourceDataLen = mLabel.Length();
oaepParams.mgf = mMgfMechanism;
oaepParams.hashAlg = mHashMechanism;
SECItem param;
param.type = siBuffer;
param.data = (unsigned char*) &oaepParams;
param.len = sizeof(oaepParams);
uint32_t outLen;
if (mEncrypt) {
// PK11_PubEncrypt() checks the plaintext's length and fails if it is too
// long to encrypt, i.e. if it is longer than (k - 2hLen - 2) with 'k'
// being the length in octets of the RSA modulus n and 'hLen' being the
// output length in octets of the chosen hash function.
// <https://tools.ietf.org/html/rfc3447#section-7.1>
rv = MapSECStatus(PK11_PubEncrypt(
mPubKey.get(), CKM_RSA_PKCS_OAEP, &param,
mResult.Elements(), &outLen, mResult.Length(),
mData.Elements(), mData.Length(), nullptr));
} else {
rv = MapSECStatus(PK11_PrivDecrypt(
mPrivKey.get(), CKM_RSA_PKCS_OAEP, &param,
mResult.Elements(), &outLen, mResult.Length(),
mData.Elements(), mData.Length()));
}
mResult.SetLength(outLen);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
return NS_OK;
}
};
class HmacTask : public WebCryptoTask
{
public:
HmacTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
mozilla::dom::CryptoKey& aKey,
CryptoKey& aKey,
const CryptoOperationData& aSignature,
const CryptoOperationData& aData,
bool aSign)
@ -656,7 +779,7 @@ class RsassaPkcs1Task : public WebCryptoTask
{
public:
RsassaPkcs1Task(JSContext* aCx, const ObjectOrString& aAlgorithm,
mozilla::dom::CryptoKey& aKey,
CryptoKey& aKey,
const CryptoOperationData& aSignature,
const CryptoOperationData& aData,
bool aSign)
@ -1017,7 +1140,8 @@ public:
}
// If this is RSA with a hash, cache the hash name
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
RootedDictionary<RsaHashedImportParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
if (NS_FAILED(mEarlyRv) || !params.mHash.WasPassed()) {
@ -1088,15 +1212,14 @@ private:
{
// Construct an appropriate KeyAlgorithm
nsIGlobalObject* global = mKey->GetParentObject();
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
if ((mKey->GetKeyType() == CryptoKey::PUBLIC &&
mKey->HasUsageOtherThan(CryptoKey::ENCRYPT)) ||
(mKey->GetKeyType() == CryptoKey::PRIVATE &&
mKey->HasUsageOtherThan(CryptoKey::DECRYPT))) {
return NS_ERROR_DOM_DATA_ERR;
}
mKey->SetAlgorithm(new RsaKeyAlgorithm(global, mAlgName, mModulusLength, mPublicExponent));
} else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
if ((mKey->GetKeyType() == CryptoKey::PUBLIC &&
mKey->HasUsageOtherThan(CryptoKey::VERIFY)) ||
@ -1104,16 +1227,23 @@ private:
mKey->HasUsageOtherThan(CryptoKey::SIGN))) {
return NS_ERROR_DOM_DATA_ERR;
}
}
nsRefPtr<RsaHashedKeyAlgorithm> algorithm = new RsaHashedKeyAlgorithm(
global,
mAlgName,
mModulusLength,
mPublicExponent,
mHashName);
// Construct an appropriate KeyAlgorithm
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
mKey->SetAlgorithm(new RsaKeyAlgorithm(global, mAlgName, mModulusLength, mPublicExponent));
} else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
nsRefPtr<RsaHashedKeyAlgorithm> algorithm =
new RsaHashedKeyAlgorithm(global, mAlgName,
mModulusLength, mPublicExponent, mHashName);
if (algorithm->Mechanism() == UNKNOWN_CK_MECHANISM) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (algorithm->Hash()->Mechanism() == UNKNOWN_CK_MECHANISM) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
mKey->SetAlgorithm(algorithm);
}
@ -1345,7 +1475,8 @@ public:
// Construct an appropriate KeyAlorithm
KeyAlgorithm* algorithm;
uint32_t privateAllowedUsages = 0, publicAllowedUsages = 0;
if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
RootedDictionary<RsaHashedKeyGenParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
if (NS_FAILED(mEarlyRv) || !params.mModulusLength.WasPassed() ||
@ -1380,9 +1511,6 @@ public:
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
return;
}
privateAllowedUsages = CryptoKey::SIGN;
publicAllowedUsages = CryptoKey::VERIFY;
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
RootedDictionary<RsaKeyGenParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
@ -1411,14 +1539,21 @@ public:
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
return;
}
privateAllowedUsages = CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY;
publicAllowedUsages = CryptoKey::ENCRYPT | CryptoKey::WRAPKEY;
} else {
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
}
// Set key usages.
if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
privateAllowedUsages = CryptoKey::SIGN;
publicAllowedUsages = CryptoKey::VERIFY;
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
privateAllowedUsages = CryptoKey::DECRYPT | CryptoKey::UNWRAPKEY;
publicAllowedUsages = CryptoKey::ENCRYPT | CryptoKey::WRAPKEY;
}
mKeyPair->PrivateKey()->SetExtractable(aExtractable);
mKeyPair->PrivateKey()->SetType(CryptoKey::PRIVATE);
@ -1676,6 +1811,8 @@ WebCryptoTask::EncryptDecryptTask(JSContext* aCx,
return new AesTask(aCx, aAlgorithm, aKey, aData, aEncrypt);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
return new RsaesPkcs1Task(aCx, aAlgorithm, aKey, aData, aEncrypt);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
return new RsaOaepTask(aCx, aAlgorithm, aKey, aData, aEncrypt);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
@ -1748,7 +1885,8 @@ WebCryptoTask::ImportKeyTask(JSContext* aCx,
return new ImportSymmetricKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
return new ImportRsaKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
} else {
@ -1790,7 +1928,8 @@ WebCryptoTask::GenerateKeyTask(JSContext* aCx,
algName.EqualsASCII(WEBCRYPTO_ALG_HMAC)) {
return new GenerateSymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
} else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSAES_PKCS1) ||
algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP)) {
return new GenerateAsymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
} else {
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);

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

@ -1,6 +1,6 @@
[DEFAULT]
# Bug 1010743 - Re-enable WebCrypto tests on b2g-desktop
skip-if = (buildapp == 'b2g' && toolkit != 'gonk')
# Bug 1010743 - Re-enable WebCrypto tests on b2g
skip-if = (buildapp == 'b2g')
support-files =
test-array.js
test-vectors.js

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

@ -311,6 +311,50 @@ tv = {
),
},
// RSA test vectors, oaep-vect.txt, Example 1.1: A 1024-bit RSA Key Pair
// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
rsaoaep: {
pkcs8: util.hex2abv(
"30820276020100300d06092a864886f70d0101010500048202603082025c0201" +
"0002818100a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae" +
"4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630" +
"f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fa" +
"b9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de" +
"88d39f16fb020301000102818053339cfdb79fc8466a655c7316aca85c55fd8f" +
"6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a55" +
"3d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c4831" +
"16ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0c" +
"f539e9cfcdd3de653729ead5d1024100d32737e7267ffe1341b2d5c0d150a81b" +
"586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1" +
"c11c520c2f26a471dcad212eac7ca39d024100cc8853d1d54da630fac004f471" +
"f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0d" +
"d852be2419b2af72bfe9a030e860b0288b5d7702400e12bf1718e9cef5599ba1" +
"c3882fe8046a90874eefce8f2ccc20e4f2741fb0a33a3848aec9c9305fbecbd2" +
"d76819967d4671acc6431e4037968db37878e695c102410095297b0f95a2fa67" +
"d00707d609dfd4fc05c89dafc2ef6d6ea55bec771ea333734d9251e79082ecda" +
"866efef13c459e1a631386b7e354c899f5f112ca85d7158302404f456c502493" +
"bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbe" +
"fd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1"
),
spki: util.hex2abv(
"30819f300d06092a864886f70d010101050003818d0030818902818100a8b3b2" +
"84af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0" +
"b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae8" +
"33c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef739" +
"2dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb020301" +
"0001"
),
data: util.hex2abv(
"6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34"
),
result: util.hex2abv(
"354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad468fb" +
"21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618c21a535f" +
"a9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e657a05a266426" +
"d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5210035d47ac72e8a"
),
},
// RFC 6070 <http://tools.ietf.org/html/rfc6070>
pbkdf2_sha1: {
password: new TextEncoder("utf-8").encode("passwordPASSWORDpassword"),

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

@ -154,7 +154,7 @@ TestArray.addTest(
"Import / export round-trip with 'pkcs8'",
function() {
var that = this;
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA1" };
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" };
function doExport(x) {
if (!hasKeyFields(x)) {
@ -186,7 +186,7 @@ TestArray.addTest(
"Import failure with format 'pkcs8'",
function() {
var that = this;
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA1" };
var alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" };
crypto.subtle.importKey("pkcs8", tv.negative_pkcs8, alg, true, ["encrypt"])
.then(error(that), complete(that));
@ -1150,3 +1150,127 @@ TestArray.addTest(
.then( memcmp_complete(that, tv.pbkdf2_sha256.derived), fail );
}
);*/
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-OAEP encrypt/decrypt round-trip",
function () {
var that = this;
var privKey, pubKey;
var alg = {name: "RSA-OAEP", hash: "SHA-1"};
var privKey, pubKey;
function setPriv(x) { privKey = x; }
function setPub(x) { pubKey = x; }
function doEncrypt() {
return crypto.subtle.encrypt(alg, pubKey, tv.rsaoaep.data);
}
function doDecrypt(x) {
return crypto.subtle.decrypt(alg, privKey, x);
}
Promise.all([
crypto.subtle.importKey("pkcs8", tv.rsaoaep.pkcs8, alg, false, ['decrypt'])
.then(setPriv, error(that)),
crypto.subtle.importKey("spki", tv.rsaoaep.spki, alg, false, ['encrypt'])
.then(setPub, error(that))
]).then(doEncrypt, error(that))
.then(doDecrypt, error(that))
.then(
memcmp_complete(that, tv.rsaoaep.data),
error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-OAEP key generation and encrypt/decrypt round-trip (SHA-256)",
function () {
var that = this;
var alg = {
name: "RSA-OAEP",
hash: "SHA-256",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
var privKey, pubKey, data = crypto.getRandomValues(new Uint8Array(128));
function setKey(x) { pubKey = x.publicKey; privKey = x.privateKey; }
function doEncrypt() {
return crypto.subtle.encrypt(alg, pubKey, data);
}
function doDecrypt(x) {
return crypto.subtle.decrypt(alg, privKey, x);
}
crypto.subtle.generateKey(alg, false, ['encrypt', 'decrypt'])
.then(setKey, error(that))
.then(doEncrypt, error(that))
.then(doDecrypt, error(that))
.then(
memcmp_complete(that, data),
error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-OAEP decryption known answer",
function () {
var that = this;
var alg = {name: "RSA-OAEP", hash: "SHA-1"};
function doDecrypt(x) {
return crypto.subtle.decrypt(alg, x, tv.rsaoaep.result);
}
function fail() { error(that); }
crypto.subtle.importKey("pkcs8", tv.rsaoaep.pkcs8, alg, false, ['decrypt'])
.then( doDecrypt, fail )
.then( memcmp_complete(that, tv.rsaoaep.data), fail );
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-OAEP input data length checks (2048-bit key)",
function () {
var that = this;
var privKey, pubKey;
var alg = {
name: "RSA-OAEP",
hash: "SHA-1",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
var privKey, pubKey;
function setKey(x) { pubKey = x.publicKey; privKey = x.privateKey; }
function doEncrypt(n) {
return function () {
return crypto.subtle.encrypt(alg, pubKey, new Uint8Array(n));
}
}
crypto.subtle.generateKey(alg, false, ['encrypt'])
.then(setKey, error(that))
.then(doEncrypt(214), error(that))
.then(doEncrypt(215), error(that))
.then(error(that), complete(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"RSA-OAEP key import with invalid hash",
function () {
var that = this;
var alg = {name: "RSA-OAEP", hash: "SHA-123"};
crypto.subtle.importKey("pkcs8", tv.rsaoaep.pkcs8, alg, false, ['decrypt'])
.then(error(that), complete(that));
}
);

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

@ -5,6 +5,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
if CONFIG["MOZ_B2G"]:
TEST_DIRS += ['tests']
TEST_DIRS += ['tests']
PARALLEL_DIRS += ['src']

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

@ -17,7 +17,7 @@ class FocusEvent : public UIEvent,
public nsIDOMFocusEvent
{
public:
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMFOCUSEVENT
// Forward to base class

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

@ -5,7 +5,7 @@
#include "nsIDOMCSSRule.idl"
[scriptable, uuid(19fe78cc-65ff-4b1d-a5d7-9ea89692cec6)]
[scriptable, uuid(756c326c-eb38-4342-95e5-5eabea809174)]
interface nsIDOMCSSCharsetRule : nsIDOMCSSRule
{
attribute DOMString encoding;

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

@ -9,7 +9,7 @@
* Interface in the CSS OM for at-rules that conditionally apply their
* child rules.
*/
[scriptable, uuid(942754f2-2c0e-461b-9c10-c0e929504fe1)]
[scriptable, uuid(44da41b2-5660-415d-8692-eae805776103)]
interface nsIDOMCSSConditionRule : nsIDOMCSSGroupingRule
{
attribute DOMString conditionText;

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

@ -6,7 +6,7 @@
#include "nsIDOMCSSRule.idl"
[scriptable, uuid(5f9f2068-743b-42e3-becb-10ffa994d1e3)]
[scriptable, uuid(9b5e48ce-d84c-4e31-aff5-34e9f4141313)]
interface nsIDOMCSSCounterStyleRule : nsIDOMCSSRule
{
attribute DOMString name;

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

@ -5,7 +5,7 @@
#include "nsIDOMCSSRule.idl"
[scriptable, uuid(a6cf90bb-15b3-11d2-932e-00805f8add32)]
[scriptable, uuid(db971017-fe0c-4529-972c-8217f2fee217)]
interface nsIDOMCSSFontFaceRule : nsIDOMCSSRule
{
readonly attribute nsIDOMCSSStyleDeclaration style;

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

@ -5,7 +5,7 @@
#include "nsIDOMCSSRule.idl"
[scriptable, uuid(f4cb1776-389d-4f52-a4d8-68bea5bd00c1)]
[scriptable, uuid(a343d27f-1da6-4fc3-9355-d4ca434f958e)]
interface nsIDOMCSSFontFeatureValuesRule : nsIDOMCSSRule
{
attribute DOMString fontFamily;

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

@ -8,7 +8,7 @@
/**
* Interface for at-rules that have child rules in the CSS OM.
*/
[scriptable, uuid(ab013eed-fa21-4c6a-bba3-79e8780f583e)]
[scriptable, uuid(a0e3324a-f911-4baf-9591-5322c76cbb0d)]
interface nsIDOMCSSGroupingRule : nsIDOMCSSRule
{
readonly attribute nsIDOMCSSRuleList cssRules;

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

@ -5,7 +5,7 @@
#include "nsIDOMCSSRule.idl"
[scriptable, uuid(a6cf90cf-15b3-11d2-932e-00805f8add32)]
[scriptable, uuid(d3b2b914-01ef-4663-beda-a6475a26f491)]
interface nsIDOMCSSImportRule : nsIDOMCSSRule
{
readonly attribute DOMString href;

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

@ -8,7 +8,7 @@
/**
* Interface for @media rules in the CSS OM.
*/
[scriptable, uuid(1f491b05-932b-4aa1-a1f1-466505d70898)]
[scriptable, uuid(6cf9c5b2-fa0f-43c0-aa50-ef85b4756e3a)]
interface nsIDOMCSSMediaRule : nsIDOMCSSConditionRule
{
readonly attribute nsIDOMMediaList media;

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

@ -8,7 +8,7 @@
/**
* Interface for @-moz-document rules in the CSS OM.
*/
[scriptable, uuid(f118a5a8-ac36-464f-b993-18cf6fe76fda)]
[scriptable, uuid(2d0cef9d-c1b2-4c6c-9003-fa83040626d1)]
interface nsIDOMCSSMozDocumentRule : nsIDOMCSSConditionRule
{
// XXX Add access to the URL list.

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

@ -5,7 +5,7 @@
#include "nsIDOMCSSRule.idl"
[scriptable, uuid(6126024d-d716-4ad8-bc53-24dd6d5846b1)]
[scriptable, uuid(c119072b-7d2f-4aeb-a90d-e2d6b606c32a)]
interface nsIDOMCSSPageRule : nsIDOMCSSRule
{
//attribute DOMString selectorText;

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

@ -5,6 +5,16 @@
#include "domstubs.idl"
%{C++
namespace mozilla {
namespace css {
class Rule;
}
}
%}
[ptr] native Rule(mozilla::css::Rule);
/**
* The nsIDOMCSSRule interface is a datatype for a CSS style rule in
* the Document Object Model.
@ -13,7 +23,7 @@
* http://www.w3.org/TR/DOM-Level-2-Style
*/
[scriptable, uuid(2938307a-9d70-4b63-8afc-0197e82318ad)]
[scriptable, uuid(4d6b3bad-f53c-4585-82f6-62982e27ede8)]
interface nsIDOMCSSRule : nsISupports
{
// RuleType
@ -41,4 +51,6 @@ interface nsIDOMCSSRule : nsISupports
readonly attribute nsIDOMCSSStyleSheet parentStyleSheet;
readonly attribute nsIDOMCSSRule parentRule;
[noscript, nostdcall, notxpcom] Rule getCSSRule();
};

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

@ -5,7 +5,7 @@
#include "nsIDOMCSSRule.idl"
[scriptable, uuid(a6cf90bf-15b3-11d2-932e-00805f8add32)]
[scriptable, uuid(b5e9af48-a7c2-4f88-aae3-58307af4b5a5)]
interface nsIDOMCSSStyleRule : nsIDOMCSSRule
{
attribute DOMString selectorText;

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

@ -8,7 +8,7 @@
/**
* Interface for @supports rules in the CSS OM.
*/
[scriptable, uuid(5f409a4d-92f9-4a62-8e8a-cc1c02c32918)]
[scriptable, uuid(0b9e63a1-1bd7-4caf-850e-148b762b14d2)]
interface nsIDOMCSSSupportsRule : nsIDOMCSSConditionRule
{
};

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

@ -5,7 +5,7 @@
#include "nsIDOMCSSRule.idl"
[scriptable, uuid(a6cf90d0-15b3-11d2-932e-00805f8add32)]
[scriptable, uuid(98f4c27b-fb35-4355-8fd9-546c4697d71a)]
interface nsIDOMCSSUnknownRule : nsIDOMCSSRule
{
};

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

@ -5,7 +5,7 @@
#include "nsIDOMCSSRule.idl"
[scriptable, uuid(38a19612-dc58-414a-954c-233183808484)]
[scriptable, uuid(a281a8b4-eaa2-49a8-8b97-acc2814a57c9)]
interface nsIDOMMozCSSKeyframeRule : nsIDOMCSSRule
{
attribute DOMString keyText;

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

@ -5,7 +5,7 @@
#include "nsIDOMCSSRule.idl"
[scriptable, uuid(aa4ea11f-791b-4671-b192-b931e6539669)]
[scriptable, uuid(400f4b70-ad0a-4047-aba4-ee8019f6b907)]
interface nsIDOMMozCSSKeyframesRule : nsIDOMCSSRule
{
attribute DOMString name;

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

@ -59,6 +59,7 @@
#include "nsIMutable.h"
#include "nsIObserverService.h"
#include "nsIScriptSecurityManager.h"
#include "nsScreenManagerProxy.h"
#include "nsMemoryInfoDumper.h"
#include "nsServiceManagerUtils.h"
#include "nsStyleSheetService.h"
@ -169,6 +170,7 @@ using namespace mozilla::jsipc;
#if defined(MOZ_WIDGET_GONK)
using namespace mozilla::system;
#endif
using namespace mozilla::widget;
#ifdef MOZ_NUWA_PROCESS
static bool sNuwaForking = false;
@ -1200,6 +1202,28 @@ ContentChild::DeallocPNeckoChild(PNeckoChild* necko)
return true;
}
PScreenManagerChild*
ContentChild::AllocPScreenManagerChild(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
// The ContentParent should never attempt to allocate the
// nsScreenManagerProxy. Instead, the nsScreenManagerProxy
// service is requested and instantiated via XPCOM, and the
// constructor of nsScreenManagerProxy sets up the IPC connection.
NS_NOTREACHED("Should never get here!");
return nullptr;
}
bool
ContentChild::DeallocPScreenManagerChild(PScreenManagerChild* aService)
{
// nsScreenManagerProxy is AddRef'd in its constructor.
nsScreenManagerProxy *child = static_cast<nsScreenManagerProxy*>(aService);
child->Release();
return true;
}
PExternalHelperAppChild*
ContentChild::AllocPExternalHelperAppChild(const OptionalURIParams& uri,
const nsCString& aMimeContentType,

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

@ -193,6 +193,12 @@ public:
virtual PNeckoChild* AllocPNeckoChild() MOZ_OVERRIDE;
virtual bool DeallocPNeckoChild(PNeckoChild*) MOZ_OVERRIDE;
virtual PScreenManagerChild*
AllocPScreenManagerChild(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool DeallocPScreenManagerChild(PScreenManagerChild*) MOZ_OVERRIDE;
virtual PExternalHelperAppChild *AllocPExternalHelperAppChild(
const OptionalURIParams& uri,
const nsCString& aMimeContentType,

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

@ -113,6 +113,7 @@
#include "PreallocatedProcessManager.h"
#include "ProcessPriorityManager.h"
#include "SandboxHal.h"
#include "ScreenManagerParent.h"
#include "StructuredCloneUtils.h"
#include "TabParent.h"
#include "URIUtils.h"
@ -189,6 +190,7 @@ using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::net;
using namespace mozilla::jsipc;
using namespace mozilla::widget;
#ifdef ENABLE_TESTS
@ -2903,6 +2905,21 @@ ContentParent::DeallocPNeckoParent(PNeckoParent* necko)
return true;
}
PScreenManagerParent*
ContentParent::AllocPScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
return new ScreenManagerParent(aNumberOfScreens, aSystemDefaultScale, aSuccess);
}
bool
ContentParent::DeallocPScreenManagerParent(PScreenManagerParent* aActor)
{
delete aActor;
return true;
}
PExternalHelperAppParent*
ContentParent::AllocPExternalHelperAppParent(const OptionalURIParams& uri,
const nsCString& aMimeContentType,

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

@ -230,6 +230,12 @@ public:
return PContentParent::RecvPNeckoConstructor(aActor);
}
virtual PScreenManagerParent*
AllocPScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool DeallocPScreenManagerParent(PScreenManagerParent* aActor) MOZ_OVERRIDE;
virtual PHalParent* AllocPHalParent() MOZ_OVERRIDE;
virtual bool RecvPHalConstructor(PHalParent* aActor) MOZ_OVERRIDE {
return PContentParent::RecvPHalConstructor(aActor);

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

@ -23,6 +23,7 @@ include protocol PImageBridge;
include protocol PIndexedDB;
include protocol PMemoryReportRequest;
include protocol PNecko;
include protocol PScreenManager;
include protocol PSharedBufferManager;
include protocol PSms;
include protocol PSpeechSynthesis;
@ -303,6 +304,7 @@ intr protocol PContent
manages PIndexedDB;
manages PMemoryReportRequest;
manages PNecko;
manages PScreenManager;
manages PSms;
manages PSpeechSynthesis;
manages PStorage;
@ -479,6 +481,11 @@ parent:
PNecko();
sync PScreenManager()
returns (uint32_t numberOfScreens,
float systemDefaultScale,
bool success);
PSms();
PSpeechSynthesis();

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

@ -0,0 +1,57 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBrowser;
include protocol PContent;
using struct nsIntRect from "nsRect.h";
namespace mozilla {
namespace dom {
struct ScreenDetails {
uint32_t id;
nsIntRect rect;
nsIntRect availRect;
int32_t pixelDepth;
int32_t colorDepth;
double contentsScaleFactor;
};
sync protocol PScreenManager
{
manager PContent;
parent:
sync Refresh()
returns (uint32_t numberOfScreens,
float systemDefaultScale,
bool success);
sync ScreenRefresh(uint32_t aId)
returns (ScreenDetails screen,
bool success);
sync GetPrimaryScreen()
returns (ScreenDetails screen,
bool success);
sync ScreenForRect(int32_t aLeft,
int32_t aTop,
int32_t aWidth,
int32_t aHeight)
returns (ScreenDetails screen,
bool success);
sync ScreenForBrowser(PBrowser aBrowser)
returns (ScreenDetails screen,
bool success);
child:
__delete__();
};
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,195 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/TabParent.h"
#include "mozilla/unused.h"
#include "nsIWidget.h"
#include "nsServiceManagerUtils.h"
#include "ScreenManagerParent.h"
namespace mozilla {
namespace dom {
static const char *sScreenManagerContractID = "@mozilla.org/gfx/screenmanager;1";
ScreenManagerParent::ScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
mScreenMgr = do_GetService(sScreenManagerContractID);
if (!mScreenMgr) {
MOZ_CRASH("Couldn't get nsIScreenManager from ScreenManagerParent.");
}
unused << RecvRefresh(aNumberOfScreens, aSystemDefaultScale, aSuccess);
}
bool
ScreenManagerParent::RecvRefresh(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
*aSuccess = false;
nsresult rv = mScreenMgr->GetNumberOfScreens(aNumberOfScreens);
if (NS_FAILED(rv)) {
return true;
}
rv = mScreenMgr->GetSystemDefaultScale(aSystemDefaultScale);
if (NS_FAILED(rv)) {
return true;
}
*aSuccess = true;
return true;
}
bool
ScreenManagerParent::RecvScreenRefresh(const uint32_t& aId,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
nsCOMPtr<nsIScreen> screen;
nsresult rv = mScreenMgr->ScreenForId(aId, getter_AddRefs(screen));
if (NS_FAILED(rv)) {
return true;
}
ScreenDetails details;
unused << ExtractScreenDetails(screen, details);
*aRetVal = details;
*aSuccess = true;
return true;
}
bool
ScreenManagerParent::RecvGetPrimaryScreen(ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
nsCOMPtr<nsIScreen> screen;
nsresult rv = mScreenMgr->GetPrimaryScreen(getter_AddRefs(screen));
NS_ENSURE_SUCCESS(rv, true);
ScreenDetails details;
if (!ExtractScreenDetails(screen, details)) {
return true;
}
*aRetVal = details;
*aSuccess = true;
return true;
}
bool
ScreenManagerParent::RecvScreenForRect(const int32_t& aLeft,
const int32_t& aTop,
const int32_t& aWidth,
const int32_t& aHeight,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
nsCOMPtr<nsIScreen> screen;
nsresult rv = mScreenMgr->ScreenForRect(aLeft, aTop, aWidth, aHeight, getter_AddRefs(screen));
NS_ENSURE_SUCCESS(rv, true);
ScreenDetails details;
if (!ExtractScreenDetails(screen, details)) {
return true;
}
*aRetVal = details;
*aSuccess = true;
return true;
}
bool
ScreenManagerParent::RecvScreenForBrowser(PBrowserParent* aBrowser,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
// Find the mWidget associated with the tabparent, and then return
// the nsIScreen it's on.
TabParent* tabParent = static_cast<TabParent*>(aBrowser);
nsCOMPtr<nsIWidget> widget = tabParent->GetWidget();
if (!widget) {
return true;
}
nsCOMPtr<nsIScreen> screen;
if (widget->GetNativeData(NS_NATIVE_WINDOW)) {
mScreenMgr->ScreenForNativeWidget(widget->GetNativeData(NS_NATIVE_WINDOW),
getter_AddRefs(screen));
}
NS_ENSURE_TRUE(screen, true);
ScreenDetails details;
if (!ExtractScreenDetails(screen, details)) {
return true;
}
*aRetVal = details;
*aSuccess = true;
return true;
}
bool
ScreenManagerParent::ExtractScreenDetails(nsIScreen* aScreen, ScreenDetails &aDetails)
{
uint32_t id;
nsresult rv = aScreen->GetId(&id);
NS_ENSURE_SUCCESS(rv, false);
aDetails.id() = id;
nsIntRect rect;
rv = aScreen->GetRect(&rect.x, &rect.y, &rect.width, &rect.height);
NS_ENSURE_SUCCESS(rv, false);
aDetails.rect() = rect;
nsIntRect availRect;
rv = aScreen->GetAvailRect(&availRect.x, &availRect.y, &availRect.width,
&availRect.height);
NS_ENSURE_SUCCESS(rv, false);
aDetails.availRect() = availRect;
int32_t pixelDepth = 0;
rv = aScreen->GetPixelDepth(&pixelDepth);
NS_ENSURE_SUCCESS(rv, false);
aDetails.pixelDepth() = pixelDepth;
int32_t colorDepth = 0;
rv = aScreen->GetColorDepth(&colorDepth);
NS_ENSURE_SUCCESS(rv, false);
aDetails.colorDepth() = colorDepth;
double contentsScaleFactor = 1.0;
rv = aScreen->GetContentsScaleFactor(&contentsScaleFactor);
NS_ENSURE_SUCCESS(rv, false);
aDetails.contentsScaleFactor() = contentsScaleFactor;
return true;
}
void
ScreenManagerParent::ActorDestroy(ActorDestroyReason why)
{
}
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_ScreenManagerParent_h
#define mozilla_dom_ScreenManagerParent_h
#include "mozilla/dom/PScreenManagerParent.h"
#include "nsIScreenManager.h"
namespace mozilla {
namespace dom {
class ScreenManagerParent : public PScreenManagerParent
{
public:
ScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess);
~ScreenManagerParent() {};
virtual bool RecvRefresh(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool RecvScreenRefresh(const uint32_t& aId,
ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool RecvGetPrimaryScreen(ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool RecvScreenForRect(const int32_t& aLeft,
const int32_t& aTop,
const int32_t& aWidth,
const int32_t& aHeight,
ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool RecvScreenForBrowser(PBrowserParent* aBrowser,
ScreenDetails* aRetVal,
bool* aSuccess);
private:
bool ExtractScreenDetails(nsIScreen* aScreen, ScreenDetails &aDetails);
nsCOMPtr<nsIScreenManager> mScreenMgr;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ScreenManagerParent_h

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

@ -309,6 +309,8 @@ public:
*/
bool IsDestroyed() const { return mIsDestroyed; }
already_AddRefed<nsIWidget> GetWidget() const;
protected:
bool ReceiveMessage(const nsString& aMessage,
bool aSync,
@ -380,7 +382,6 @@ protected:
private:
already_AddRefed<nsFrameLoader> GetFrameLoader() const;
already_AddRefed<nsIWidget> GetWidget() const;
layout::RenderFrameParent* GetRenderFrame();
nsRefPtr<nsIContentParent> mManager;
void TryCacheDPIAndScale();

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

@ -59,6 +59,7 @@ UNIFIED_SOURCES += [
'PermissionMessageUtils.cpp',
'PreallocatedProcessManager.cpp',
'ProcessPriorityManager.cpp',
'ScreenManagerParent.cpp',
'StructuredCloneUtils.cpp',
'TabChild.cpp',
'TabContext.cpp',
@ -92,6 +93,7 @@ IPDL_SOURCES += [
'PFileDescriptorSet.ipdl',
'PFilePicker.ipdl',
'PMemoryReportRequest.ipdl',
'PScreenManager.ipdl',
'PTabContext.ipdlh',
]

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

@ -5,6 +5,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
if CONFIG ['MOZ_WEBRTC']:
MOCHITEST_MANIFESTS += ['mochitest.ini']
WEBRTC_SIGNALLING_TEST_MANIFESTS += ['steeplechase.ini']
MOCHITEST_MANIFESTS += ['mochitest.ini']
WEBRTC_SIGNALLING_TEST_MANIFESTS += ['steeplechase.ini']

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

@ -34,7 +34,7 @@ class DesktopNotificationRequest : public nsIContentPermissionRequest,
}
public:
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSICONTENTPERMISSIONREQUEST
DesktopNotificationRequest(DesktopNotification* notification)
@ -309,9 +309,8 @@ DesktopNotificationCenter::WrapObject(JSContext* aCx)
/* DesktopNotificationRequest */
/* ------------------------------------------------------------------------ */
NS_IMPL_ISUPPORTS(DesktopNotificationRequest,
nsIContentPermissionRequest,
nsIRunnable)
NS_IMPL_ISUPPORTS_INHERITED(DesktopNotificationRequest, nsRunnable,
nsIContentPermissionRequest)
NS_IMETHODIMP
DesktopNotificationRequest::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)

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

@ -26,8 +26,8 @@ dictionary NetworkStatsAlarmOptions
[JSImplementation="@mozilla.org/networkstats;1",
ChromeOnly,
Pref="dom.mozNetworkStats.enabled",
Func="Navigator::HasNetworkStatsSupport"]
CheckPermissions="networkstats-manage",
Pref="dom.mozNetworkStats.enabled"]
interface MozNetworkStats {
/**
* App manifest URL of an application for specifying the per-app stats of the

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

@ -4,8 +4,8 @@
[JSImplementation="@mozilla.org/networkstatsalarm;1",
ChromeOnly,
Pref="dom.mozNetworkStats.enabled",
Func="Navigator::HasNetworkStatsSupport"]
CheckPermissions="networkstats-manage",
Pref="dom.mozNetworkStats.enabled"]
interface MozNetworkStatsAlarm {
readonly attribute unsigned long alarmId;
readonly attribute MozNetworkStatsInterface network;

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

@ -4,8 +4,8 @@
[JSImplementation="@mozilla.org/networkStatsdata;1",
ChromeOnly,
Pref="dom.mozNetworkStats.enabled",
Func="Navigator::HasNetworkStatsSupport"]
CheckPermissions="networkstats-manage",
Pref="dom.mozNetworkStats.enabled"]
interface MozNetworkStatsData {
readonly attribute unsigned long rxBytes; // Received bytes.
readonly attribute unsigned long txBytes; // Sent bytes.

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

@ -12,8 +12,8 @@ dictionary NetworkInterface {
*/
[Constructor(optional NetworkInterface networkinterface),
JSImplementation="@mozilla.org/networkstatsinterface;1",
Pref="dom.mozNetworkStats.enabled",
Func="Navigator::HasNetworkStatsSupport"]
CheckPermissions="networkstats-manage",
Pref="dom.mozNetworkStats.enabled"]
interface MozNetworkStatsInterface {
readonly attribute long type;

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

@ -83,7 +83,7 @@ interface NavigatorStorageUtils {
[NoInterfaceObject]
interface NavigatorFeatures {
[Func="Navigator::HasFeatureDetectionSupport"]
[CheckPermissions="feature-detection"]
Promise getFeature(DOMString name);
};
@ -252,10 +252,12 @@ partial interface Navigator {
boolean mozIsLocallyAvailable(DOMString uri, boolean whenOffline);
};
#ifdef MOZ_WEBSMS_BACKEND
partial interface Navigator {
[Func="Navigator::HasMobileMessageSupport"]
[CheckPermissions="sms", Pref="dom.sms.enabled"]
readonly attribute MozMobileMessageManager? mozMobileMessage;
};
#endif
// NetworkInformation
partial interface Navigator {
@ -331,7 +333,7 @@ partial interface Navigator {
#ifdef MOZ_TIME_MANAGER
// nsIDOMMozNavigatorTime
partial interface Navigator {
[Throws, Func="Navigator::HasTimeSupport"]
[Throws, CheckPermissions="time"]
readonly attribute MozTimeManager mozTime;
};
#endif // MOZ_TIME_MANAGER

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

@ -95,6 +95,10 @@ dictionary RsaHashedKeyGenParams : RsaKeyGenParams {
AlgorithmIdentifier hash;
};
dictionary RsaOaepParams : Algorithm {
CryptoOperationData? label;
};
dictionary DhKeyGenParams : Algorithm {
BigInteger prime;
BigInteger generator;

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

@ -204,7 +204,7 @@ struct TextureFactoryIdentifier
TextureFactoryIdentifier(LayersBackend aLayersBackend = LayersBackend::LAYERS_NONE,
GeckoProcessType aParentProcessId = GeckoProcessType_Default,
int32_t aMaxTextureSize = 0,
int32_t aMaxTextureSize = 4096,
bool aSupportsTextureBlitting = false,
bool aSupportsPartialUploads = false)
: mParentBackend(aLayersBackend)

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

@ -1410,6 +1410,8 @@ public:
mManager->Mutated(this);
}
virtual int32_t GetMaxLayerSize() { return Manager()->GetMaxTextureSize(); }
protected:
Layer(LayerManager* aManager, void* aImplData);

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

@ -412,34 +412,13 @@ GetFrameTime() {
return sFrameTime;
}
// This is a base class for animations that can deal with
// overscroll states. In particular, it ensures that overscroll
// states are cleared when the animation is cancelled.
class OverscrollableAnimation: public AsyncPanZoomAnimation {
public:
OverscrollableAnimation(AsyncPanZoomController& aApzc,
const TimeDuration& aRepaintInterval = TimeDuration::Forever())
: AsyncPanZoomAnimation(aRepaintInterval)
, mApzc(aApzc)
{
}
virtual void Cancel() MOZ_OVERRIDE
{
mApzc.mX.ClearOverscroll();
mApzc.mY.ClearOverscroll();
}
protected:
AsyncPanZoomController& mApzc;
};
class FlingAnimation: public OverscrollableAnimation {
class FlingAnimation: public AsyncPanZoomAnimation {
public:
FlingAnimation(AsyncPanZoomController& aApzc,
bool aApplyAcceleration,
bool aAllowOverscroll)
: OverscrollableAnimation(aApzc, TimeDuration::FromMilliseconds(gfxPrefs::APZFlingRepaintInterval()))
: AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gfxPrefs::APZFlingRepaintInterval()))
, mApzc(aApzc)
, mAllowOverscroll(aAllowOverscroll)
{
TimeStamp now = GetFrameTime();
@ -594,6 +573,7 @@ private:
+ (aSupplemental * gfxPrefs::APZFlingAccelSupplementalMultiplier());
}
AsyncPanZoomController& mApzc;
bool mAllowOverscroll;
};
@ -656,10 +636,10 @@ private:
CSSToScreenScale mEndZoom;
};
class OverscrollSnapBackAnimation: public OverscrollableAnimation {
class OverscrollSnapBackAnimation: public AsyncPanZoomAnimation {
public:
OverscrollSnapBackAnimation(AsyncPanZoomController& aApzc)
: OverscrollableAnimation(aApzc)
: mApzc(aApzc)
{
}
@ -671,6 +651,8 @@ public:
bool continueY = mApzc.mY.SampleSnapBack(aDelta);
return continueX || continueY;
}
private:
AsyncPanZoomController& mApzc;
};
void
@ -1771,10 +1753,13 @@ void AsyncPanZoomController::CancelAnimation() {
ReentrantMonitorAutoEnter lock(mMonitor);
APZC_LOG("%p running CancelAnimation in state %d\n", this, mState);
SetState(NOTHING);
if (mAnimation) {
mAnimation->Cancel();
mAnimation = nullptr;
// mAnimation->Cancel() may have done something that requires a repaint.
mAnimation = nullptr;
// Setting the state to nothing and cancelling the animation can
// preempt normal mechanisms for relieving overscroll, so we need to clear
// overscroll here.
if (mX.IsOverscrolled() || mY.IsOverscrolled()) {
mX.ClearOverscroll();
mY.ClearOverscroll();
RequestContentRepaint();
ScheduleComposite();
UpdateSharedCompositorFrameMetrics();

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

@ -800,7 +800,6 @@ public:
bool TakeOverFling(ScreenPoint aVelocity);
private:
friend class OverscrollableAnimation;
friend class FlingAnimation;
friend class OverscrollSnapBackAnimation;
// The initial velocity of the most recent fling.
@ -1039,9 +1038,6 @@ public:
virtual bool Sample(FrameMetrics& aFrameMetrics,
const TimeDuration& aDelta) = 0;
// Called if the animation is cancelled before it ends.
virtual void Cancel() {}
/**
* Get the deferred tasks in |mDeferredTasks|. See |mDeferredTasks|
* for more information.

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

@ -86,6 +86,12 @@ public:
void* aCallbackData,
ReadbackProcessor* aReadback) MOZ_OVERRIDE;
/**
* We don't really have a hard restriction for max layer size, but we pick
* 4096 to avoid excessive memory usage.
*/
virtual int32_t GetMaxLayerSize() MOZ_OVERRIDE { return 4096; }
protected:
BasicLayerManager* BasicManager()
{

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

@ -631,11 +631,17 @@ nsDeviceContext::ComputeFullAreaUsingScreen(nsRect* outRect)
void
nsDeviceContext::FindScreen(nsIScreen** outScreen)
{
if (mWidget && mWidget->GetNativeData(NS_NATIVE_WINDOW))
if (mWidget && mWidget->GetOwningTabChild()) {
mScreenManager->ScreenForNativeWidget((void *)mWidget->GetOwningTabChild(),
outScreen);
}
else if (mWidget && mWidget->GetNativeData(NS_NATIVE_WINDOW)) {
mScreenManager->ScreenForNativeWidget(mWidget->GetNativeData(NS_NATIVE_WINDOW),
outScreen);
else
}
else {
mScreenManager->GetPrimaryScreen(outScreen);
}
}
void

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -29,7 +29,7 @@ FontInfoData::Load()
class FontInfoLoadCompleteEvent : public nsRunnable {
virtual ~FontInfoLoadCompleteEvent() {}
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
FontInfoLoadCompleteEvent(FontInfoData *aFontInfo) :
mFontInfo(aFontInfo)
@ -43,7 +43,7 @@ class FontInfoLoadCompleteEvent : public nsRunnable {
class AsyncFontInfoLoader : public nsRunnable {
virtual ~AsyncFontInfoLoader() {}
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
AsyncFontInfoLoader(FontInfoData *aFontInfo) :
mFontInfo(aFontInfo)
@ -70,7 +70,7 @@ FontInfoLoadCompleteEvent::Run()
return NS_OK;
}
NS_IMPL_ISUPPORTS(FontInfoLoadCompleteEvent, nsIRunnable);
NS_IMPL_ISUPPORTS_INHERITED0(FontInfoLoadCompleteEvent, nsRunnable);
// runs on separate thread
nsresult
@ -86,7 +86,7 @@ AsyncFontInfoLoader::Run()
return NS_OK;
}
NS_IMPL_ISUPPORTS(AsyncFontInfoLoader, nsIRunnable);
NS_IMPL_ISUPPORTS_INHERITED0(AsyncFontInfoLoader, nsRunnable);
NS_IMPL_ISUPPORTS(gfxFontInfoLoader::ShutdownObserver, nsIObserver)

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

@ -115,6 +115,8 @@ NS_IMPL_ISUPPORTS(GfxD2DSurfaceReporter, nsIMemoryReporter)
class GfxD2DVramReporter MOZ_FINAL : public nsIMemoryReporter
{
~GfxD2DVramReporter() {}
public:
NS_DECL_ISUPPORTS

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

@ -281,11 +281,6 @@ public:
}
}
virtual ~Observer()
{
Stop();
}
void SetDeviceChangeTimer()
{
// Set stable timer, since we will get multiple devices-changed
@ -297,6 +292,11 @@ public:
}
private:
virtual ~Observer()
{
Stop();
}
// Gamepad service owns us, we just hold a reference back to it.
WindowsGamepadService& mSvc;
nsCOMPtr<nsITimer> mTimer;

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

@ -156,7 +156,7 @@ ClippedImage::ShouldClip()
return mShouldClip.ref();
}
NS_IMPL_ISUPPORTS(ClippedImage, imgIContainer)
NS_IMPL_ISUPPORTS_INHERITED0(ClippedImage, ImageWrapper)
nsIntRect
ClippedImage::FrameRect(uint32_t aWhichFrame)

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

@ -29,7 +29,7 @@ class ClippedImage : public ImageWrapper
typedef mozilla::gfx::SourceSurface SourceSurface;
public:
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE;

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

@ -10,7 +10,7 @@ using namespace mozilla::gfx;
namespace mozilla {
namespace image {
NS_IMPL_ISUPPORTS(FrozenImage, imgIContainer)
NS_IMPL_ISUPPORTS_INHERITED0(FrozenImage, ImageWrapper)
nsIntRect
FrozenImage::FrameRect(uint32_t /* aWhichFrame - ignored */)

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

@ -29,7 +29,7 @@ class FrozenImage : public ImageWrapper
typedef mozilla::gfx::SourceSurface SourceSurface;
public:
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE;
virtual void IncrementAnimationConsumers() MOZ_OVERRIDE;

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

@ -20,7 +20,7 @@ using mozilla::layers::ImageContainer;
namespace mozilla {
namespace image {
NS_IMPL_ISUPPORTS(OrientedImage, imgIContainer)
NS_IMPL_ISUPPORTS_INHERITED0(OrientedImage, ImageWrapper)
nsIntRect
OrientedImage::FrameRect(uint32_t aWhichFrame)

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

@ -26,7 +26,7 @@ class OrientedImage : public ImageWrapper
typedef mozilla::gfx::SourceSurface SourceSurface;
public:
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE;

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

@ -5,7 +5,7 @@
#include "nsSemanticUnitScanner.h"
NS_IMPL_ISUPPORTS(nsSemanticUnitScanner, nsISemanticUnitScanner)
NS_IMPL_ISUPPORTS_INHERITED(nsSemanticUnitScanner, nsSampleWordBreaker, nsISemanticUnitScanner)
nsSemanticUnitScanner::nsSemanticUnitScanner() : nsSampleWordBreaker()
{

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

@ -14,7 +14,7 @@ class nsSemanticUnitScanner : public nsISemanticUnitScanner
, public nsSampleWordBreaker
{
public:
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSISEMANTICUNITSCANNER
nsSemanticUnitScanner();

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

@ -1018,12 +1018,12 @@ template <typename T> class MaybeRooted<T, NoGC>
typedef FakeRooted<T> RootType;
typedef FakeMutableHandle<T> MutableHandleType;
static inline JS::Handle<T> toHandle(HandleType v) {
MOZ_ASSUME_UNREACHABLE("Bad conversion");
static JS::Handle<T> toHandle(HandleType v) {
MOZ_CRASH("Bad conversion");
}
static inline JS::MutableHandle<T> toMutableHandle(MutableHandleType v) {
MOZ_ASSUME_UNREACHABLE("Bad conversion");
static JS::MutableHandle<T> toMutableHandle(MutableHandleType v) {
MOZ_CRASH("Bad conversion");
}
};

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