mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-22 10:27:03 +00:00
Merge m-c to b2g-inbound. a=merge
This commit is contained in:
commit
c54b721795
@ -627,7 +627,9 @@ pref("app.update.socket.maxErrors", 20);
|
||||
pref("app.update.log", true);
|
||||
|
||||
// SystemUpdate API
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
pref("dom.system_update.active", "@mozilla.org/updates/update-prompt;1");
|
||||
#endif
|
||||
#else
|
||||
// Explicitly disable the shutdown watchdog. It's enabled by default.
|
||||
// When the updater is disabled, we want to know about shutdown hangs.
|
||||
|
@ -724,6 +724,10 @@ input[type=button] {
|
||||
color: #4A90E2;
|
||||
}
|
||||
|
||||
#newtab-intro-footer > ul > li > a:hover {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
#newtab-intro-body {
|
||||
position: relative;
|
||||
display: block;
|
||||
|
@ -55,7 +55,6 @@ skip-if = !crashreporter
|
||||
[browser_CTP_data_urls.js]
|
||||
[browser_CTP_drag_drop.js]
|
||||
[browser_CTP_hide_overlay.js]
|
||||
skip-if = true # Bug 1160788
|
||||
[browser_CTP_iframe.js]
|
||||
skip-if = os == 'linux' || os == 'mac' # Bug 984821
|
||||
[browser_CTP_multi_allow.js]
|
||||
|
@ -21,7 +21,6 @@
|
||||
<script type="text/javascript" src="loop/js/otconfig.js"></script>
|
||||
<script type="text/javascript" src="loop/libs/sdk.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/react-0.12.2.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/jquery-2.1.4.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/lodash-3.9.3.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/backbone-1.2.1.js"></script>
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var loop = loop || {};
|
||||
loop.Client = (function($) {
|
||||
loop.Client = (function() {
|
||||
"use strict";
|
||||
|
||||
// THe expected properties to be returned from the POST /calls request.
|
||||
@ -116,4 +116,4 @@ loop.Client = (function($) {
|
||||
};
|
||||
|
||||
return Client;
|
||||
})(jQuery);
|
||||
})();
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
<script type="text/javascript" src="loop/shared/libs/react-0.12.2.js"></script>
|
||||
<script type="text/javascript" src="loop/libs/l10n.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/jquery-2.1.4.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/lodash-3.9.3.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/backbone-1.2.1.js"></script>
|
||||
|
||||
|
@ -549,6 +549,9 @@ html[dir="rtl"] .context-wrapper > .context-preview {
|
||||
flex: 0 1 auto;
|
||||
display: block;
|
||||
color: black;
|
||||
/* 16px for the preview, plus its .8em margin */
|
||||
max-width: calc(100% - 16px - .8em);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.context-wrapper > .context-description > .context-url {
|
||||
|
@ -143,5 +143,11 @@ loop.store.StoreMixin = (function() {
|
||||
StoreMixin.register = function(stores) {
|
||||
_.extend(_stores, stores);
|
||||
};
|
||||
/**
|
||||
* Used for test purposes, to clear the list of registered stores.
|
||||
*/
|
||||
StoreMixin.clearRegisteredStores = function() {
|
||||
_stores = {};
|
||||
};
|
||||
return StoreMixin;
|
||||
})();
|
||||
|
@ -944,6 +944,81 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
}
|
||||
});
|
||||
|
||||
var MediaLayoutView = React.createClass({displayName: "MediaLayoutView",
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
displayScreenShare: React.PropTypes.bool.isRequired,
|
||||
isLocalLoading: React.PropTypes.bool.isRequired,
|
||||
isRemoteLoading: React.PropTypes.bool.isRequired,
|
||||
isScreenShareLoading: React.PropTypes.bool.isRequired,
|
||||
// The poster URLs are for UI-showcase testing and development.
|
||||
localPosterUrl: React.PropTypes.string,
|
||||
localSrcVideoObject: React.PropTypes.object,
|
||||
localVideoMuted: React.PropTypes.bool.isRequired,
|
||||
remotePosterUrl: React.PropTypes.string,
|
||||
remoteSrcVideoObject: React.PropTypes.object,
|
||||
renderRemoteVideo: React.PropTypes.bool.isRequired,
|
||||
screenSharePosterUrl: React.PropTypes.string,
|
||||
screenShareVideoObject: React.PropTypes.object,
|
||||
showContextRoomName: React.PropTypes.bool.isRequired,
|
||||
useDesktopPaths: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var remoteStreamClasses = React.addons.classSet({
|
||||
"remote": true,
|
||||
"focus-stream": !this.props.displayScreenShare
|
||||
});
|
||||
|
||||
var screenShareStreamClasses = React.addons.classSet({
|
||||
"screen": true,
|
||||
"focus-stream": this.props.displayScreenShare
|
||||
});
|
||||
|
||||
var mediaWrapperClasses = React.addons.classSet({
|
||||
"media-wrapper": true,
|
||||
"receiving-screen-share": this.props.displayScreenShare,
|
||||
"showing-local-streams": this.props.localSrcVideoObject ||
|
||||
this.props.localPosterUrl
|
||||
});
|
||||
|
||||
return (
|
||||
React.createElement("div", {className: "media-layout"},
|
||||
React.createElement("div", {className: mediaWrapperClasses},
|
||||
React.createElement("span", {className: "self-view-hidden-message"},
|
||||
mozL10n.get("self_view_hidden_message")
|
||||
),
|
||||
React.createElement("div", {className: remoteStreamClasses},
|
||||
React.createElement(MediaView, {displayAvatar: !this.props.renderRemoteVideo,
|
||||
isLoading: this.props.isRemoteLoading,
|
||||
mediaType: "remote",
|
||||
posterUrl: this.props.remotePosterUrl,
|
||||
srcVideoObject: this.props.remoteSrcVideoObject})
|
||||
),
|
||||
React.createElement("div", {className: screenShareStreamClasses},
|
||||
React.createElement(MediaView, {displayAvatar: false,
|
||||
isLoading: this.props.isScreenShareLoading,
|
||||
mediaType: "screen-share",
|
||||
posterUrl: this.props.screenSharePosterUrl,
|
||||
srcVideoObject: this.props.screenShareVideoObject})
|
||||
),
|
||||
React.createElement(loop.shared.views.chat.TextChatView, {
|
||||
dispatcher: this.props.dispatcher,
|
||||
showRoomName: this.props.showContextRoomName,
|
||||
useDesktopPaths: false}),
|
||||
React.createElement("div", {className: "local"},
|
||||
React.createElement(MediaView, {displayAvatar: this.props.localVideoMuted,
|
||||
isLoading: this.props.isLocalLoading,
|
||||
mediaType: "local",
|
||||
posterUrl: this.props.localPosterUrl,
|
||||
srcVideoObject: this.props.localSrcVideoObject})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
AvatarView: AvatarView,
|
||||
Button: Button,
|
||||
@ -953,6 +1028,7 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
ConversationView: ConversationView,
|
||||
ConversationToolbar: ConversationToolbar,
|
||||
MediaControlButton: MediaControlButton,
|
||||
MediaLayoutView: MediaLayoutView,
|
||||
MediaView: MediaView,
|
||||
LoadingView: LoadingView,
|
||||
ScreenShareControlButton: ScreenShareControlButton,
|
||||
|
@ -944,6 +944,81 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
}
|
||||
});
|
||||
|
||||
var MediaLayoutView = React.createClass({
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
displayScreenShare: React.PropTypes.bool.isRequired,
|
||||
isLocalLoading: React.PropTypes.bool.isRequired,
|
||||
isRemoteLoading: React.PropTypes.bool.isRequired,
|
||||
isScreenShareLoading: React.PropTypes.bool.isRequired,
|
||||
// The poster URLs are for UI-showcase testing and development.
|
||||
localPosterUrl: React.PropTypes.string,
|
||||
localSrcVideoObject: React.PropTypes.object,
|
||||
localVideoMuted: React.PropTypes.bool.isRequired,
|
||||
remotePosterUrl: React.PropTypes.string,
|
||||
remoteSrcVideoObject: React.PropTypes.object,
|
||||
renderRemoteVideo: React.PropTypes.bool.isRequired,
|
||||
screenSharePosterUrl: React.PropTypes.string,
|
||||
screenShareVideoObject: React.PropTypes.object,
|
||||
showContextRoomName: React.PropTypes.bool.isRequired,
|
||||
useDesktopPaths: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var remoteStreamClasses = React.addons.classSet({
|
||||
"remote": true,
|
||||
"focus-stream": !this.props.displayScreenShare
|
||||
});
|
||||
|
||||
var screenShareStreamClasses = React.addons.classSet({
|
||||
"screen": true,
|
||||
"focus-stream": this.props.displayScreenShare
|
||||
});
|
||||
|
||||
var mediaWrapperClasses = React.addons.classSet({
|
||||
"media-wrapper": true,
|
||||
"receiving-screen-share": this.props.displayScreenShare,
|
||||
"showing-local-streams": this.props.localSrcVideoObject ||
|
||||
this.props.localPosterUrl
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="media-layout">
|
||||
<div className={mediaWrapperClasses}>
|
||||
<span className="self-view-hidden-message">
|
||||
{mozL10n.get("self_view_hidden_message")}
|
||||
</span>
|
||||
<div className={remoteStreamClasses}>
|
||||
<MediaView displayAvatar={!this.props.renderRemoteVideo}
|
||||
isLoading={this.props.isRemoteLoading}
|
||||
mediaType="remote"
|
||||
posterUrl={this.props.remotePosterUrl}
|
||||
srcVideoObject={this.props.remoteSrcVideoObject} />
|
||||
</div>
|
||||
<div className={screenShareStreamClasses}>
|
||||
<MediaView displayAvatar={false}
|
||||
isLoading={this.props.isScreenShareLoading}
|
||||
mediaType="screen-share"
|
||||
posterUrl={this.props.screenSharePosterUrl}
|
||||
srcVideoObject={this.props.screenShareVideoObject} />
|
||||
</div>
|
||||
<loop.shared.views.chat.TextChatView
|
||||
dispatcher={this.props.dispatcher}
|
||||
showRoomName={this.props.showContextRoomName}
|
||||
useDesktopPaths={false} />
|
||||
<div className="local">
|
||||
<MediaView displayAvatar={this.props.localVideoMuted}
|
||||
isLoading={this.props.isLocalLoading}
|
||||
mediaType="local"
|
||||
posterUrl={this.props.localPosterUrl}
|
||||
srcVideoObject={this.props.localSrcVideoObject} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
AvatarView: AvatarView,
|
||||
Button: Button,
|
||||
@ -953,6 +1028,7 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
ConversationView: ConversationView,
|
||||
ConversationToolbar: ConversationToolbar,
|
||||
MediaControlButton: MediaControlButton,
|
||||
MediaLayoutView: MediaLayoutView,
|
||||
MediaView: MediaView,
|
||||
LoadingView: LoadingView,
|
||||
ScreenShareControlButton: ScreenShareControlButton,
|
||||
|
@ -99,7 +99,6 @@ browser.jar:
|
||||
content/browser/loop/shared/libs/react-0.12.2.js (content/shared/libs/react-0.12.2-prod.js)
|
||||
#endif
|
||||
content/browser/loop/shared/libs/lodash-3.9.3.js (content/shared/libs/lodash-3.9.3.js)
|
||||
content/browser/loop/shared/libs/jquery-2.1.4.js (content/shared/libs/jquery-2.1.4.js)
|
||||
content/browser/loop/shared/libs/backbone-1.2.1.js (content/shared/libs/backbone-1.2.1.js)
|
||||
|
||||
# Shared sounds
|
||||
|
@ -401,7 +401,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
_shouldRenderLocalLoading: function () {
|
||||
_isLocalLoading: function () {
|
||||
return this.state.roomState === ROOM_STATES.MEDIA_WAIT &&
|
||||
!this.state.localSrcVideoObject;
|
||||
},
|
||||
@ -413,7 +413,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
_shouldRenderRemoteLoading: function() {
|
||||
_isRemoteLoading: function() {
|
||||
return !!(this.state.roomState === ROOM_STATES.HAS_PARTICIPANTS &&
|
||||
!this.state.remoteSrcVideoObject &&
|
||||
!this.state.mediaConnected);
|
||||
@ -426,31 +426,14 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
_shouldRenderScreenShareLoading: function() {
|
||||
_isScreenShareLoading: function() {
|
||||
return this.state.receivingScreenShare &&
|
||||
!this.state.screenShareVideoObject;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var displayScreenShare = this.state.receivingScreenShare ||
|
||||
this.props.screenSharePosterUrl;
|
||||
|
||||
var remoteStreamClasses = React.addons.classSet({
|
||||
"remote": true,
|
||||
"focus-stream": !displayScreenShare
|
||||
});
|
||||
|
||||
var screenShareStreamClasses = React.addons.classSet({
|
||||
"screen": true,
|
||||
"focus-stream": displayScreenShare
|
||||
});
|
||||
|
||||
var mediaWrapperClasses = React.addons.classSet({
|
||||
"media-wrapper": true,
|
||||
"receiving-screen-share": displayScreenShare,
|
||||
"showing-local-streams": this.state.localSrcVideoObject ||
|
||||
this.props.localPosterUrl
|
||||
});
|
||||
var displayScreenShare = !!(this.state.receivingScreenShare ||
|
||||
this.props.screenSharePosterUrl);
|
||||
|
||||
return (
|
||||
React.createElement("div", {className: "room-conversation-wrapper standalone-room-wrapper"},
|
||||
@ -463,38 +446,22 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
joinRoom: this.joinRoom,
|
||||
roomState: this.state.roomState,
|
||||
roomUsed: this.state.used}),
|
||||
React.createElement("div", {className: "media-layout"},
|
||||
React.createElement("div", {className: mediaWrapperClasses},
|
||||
React.createElement("span", {className: "self-view-hidden-message"},
|
||||
mozL10n.get("self_view_hidden_message")
|
||||
),
|
||||
React.createElement("div", {className: remoteStreamClasses},
|
||||
React.createElement(sharedViews.MediaView, {displayAvatar: !this.shouldRenderRemoteVideo(),
|
||||
isLoading: this._shouldRenderRemoteLoading(),
|
||||
mediaType: "remote",
|
||||
posterUrl: this.props.remotePosterUrl,
|
||||
srcVideoObject: this.state.remoteSrcVideoObject})
|
||||
),
|
||||
React.createElement("div", {className: screenShareStreamClasses},
|
||||
React.createElement(sharedViews.MediaView, {displayAvatar: false,
|
||||
isLoading: this._shouldRenderScreenShareLoading(),
|
||||
mediaType: "screen-share",
|
||||
posterUrl: this.props.screenSharePosterUrl,
|
||||
srcVideoObject: this.state.screenShareVideoObject})
|
||||
),
|
||||
React.createElement(sharedViews.chat.TextChatView, {
|
||||
dispatcher: this.props.dispatcher,
|
||||
showRoomName: true,
|
||||
useDesktopPaths: false}),
|
||||
React.createElement("div", {className: "local"},
|
||||
React.createElement(sharedViews.MediaView, {displayAvatar: this.state.videoMuted,
|
||||
isLoading: this._shouldRenderLocalLoading(),
|
||||
mediaType: "local",
|
||||
posterUrl: this.props.localPosterUrl,
|
||||
srcVideoObject: this.state.localSrcVideoObject})
|
||||
)
|
||||
)
|
||||
),
|
||||
React.createElement(sharedViews.MediaLayoutView, {
|
||||
dispatcher: this.props.dispatcher,
|
||||
displayScreenShare: displayScreenShare,
|
||||
isLocalLoading: this._isLocalLoading(),
|
||||
isRemoteLoading: this._isRemoteLoading(),
|
||||
isScreenShareLoading: this._isScreenShareLoading(),
|
||||
localPosterUrl: this.props.localPosterUrl,
|
||||
localSrcVideoObject: this.state.localSrcVideoObject,
|
||||
localVideoMuted: this.state.videoMuted,
|
||||
remotePosterUrl: this.props.remotePosterUrl,
|
||||
remoteSrcVideoObject: this.state.remoteSrcVideoObject,
|
||||
renderRemoteVideo: this.shouldRenderRemoteVideo(),
|
||||
screenSharePosterUrl: this.props.screenSharePosterUrl,
|
||||
screenShareVideoObject: this.state.screenShareVideoObject,
|
||||
showContextRoomName: true,
|
||||
useDesktopPaths: false}),
|
||||
React.createElement(sharedViews.ConversationToolbar, {
|
||||
audio: {enabled: !this.state.audioMuted,
|
||||
visible: this._roomIsActive()},
|
||||
|
@ -401,7 +401,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
_shouldRenderLocalLoading: function () {
|
||||
_isLocalLoading: function () {
|
||||
return this.state.roomState === ROOM_STATES.MEDIA_WAIT &&
|
||||
!this.state.localSrcVideoObject;
|
||||
},
|
||||
@ -413,7 +413,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
_shouldRenderRemoteLoading: function() {
|
||||
_isRemoteLoading: function() {
|
||||
return !!(this.state.roomState === ROOM_STATES.HAS_PARTICIPANTS &&
|
||||
!this.state.remoteSrcVideoObject &&
|
||||
!this.state.mediaConnected);
|
||||
@ -426,31 +426,14 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
_shouldRenderScreenShareLoading: function() {
|
||||
_isScreenShareLoading: function() {
|
||||
return this.state.receivingScreenShare &&
|
||||
!this.state.screenShareVideoObject;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var displayScreenShare = this.state.receivingScreenShare ||
|
||||
this.props.screenSharePosterUrl;
|
||||
|
||||
var remoteStreamClasses = React.addons.classSet({
|
||||
"remote": true,
|
||||
"focus-stream": !displayScreenShare
|
||||
});
|
||||
|
||||
var screenShareStreamClasses = React.addons.classSet({
|
||||
"screen": true,
|
||||
"focus-stream": displayScreenShare
|
||||
});
|
||||
|
||||
var mediaWrapperClasses = React.addons.classSet({
|
||||
"media-wrapper": true,
|
||||
"receiving-screen-share": displayScreenShare,
|
||||
"showing-local-streams": this.state.localSrcVideoObject ||
|
||||
this.props.localPosterUrl
|
||||
});
|
||||
var displayScreenShare = !!(this.state.receivingScreenShare ||
|
||||
this.props.screenSharePosterUrl);
|
||||
|
||||
return (
|
||||
<div className="room-conversation-wrapper standalone-room-wrapper">
|
||||
@ -463,38 +446,22 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
joinRoom={this.joinRoom}
|
||||
roomState={this.state.roomState}
|
||||
roomUsed={this.state.used} />
|
||||
<div className="media-layout">
|
||||
<div className={mediaWrapperClasses}>
|
||||
<span className="self-view-hidden-message">
|
||||
{mozL10n.get("self_view_hidden_message")}
|
||||
</span>
|
||||
<div className={remoteStreamClasses}>
|
||||
<sharedViews.MediaView displayAvatar={!this.shouldRenderRemoteVideo()}
|
||||
isLoading={this._shouldRenderRemoteLoading()}
|
||||
mediaType="remote"
|
||||
posterUrl={this.props.remotePosterUrl}
|
||||
srcVideoObject={this.state.remoteSrcVideoObject} />
|
||||
</div>
|
||||
<div className={screenShareStreamClasses}>
|
||||
<sharedViews.MediaView displayAvatar={false}
|
||||
isLoading={this._shouldRenderScreenShareLoading()}
|
||||
mediaType="screen-share"
|
||||
posterUrl={this.props.screenSharePosterUrl}
|
||||
srcVideoObject={this.state.screenShareVideoObject} />
|
||||
</div>
|
||||
<sharedViews.chat.TextChatView
|
||||
dispatcher={this.props.dispatcher}
|
||||
showRoomName={true}
|
||||
useDesktopPaths={false} />
|
||||
<div className="local">
|
||||
<sharedViews.MediaView displayAvatar={this.state.videoMuted}
|
||||
isLoading={this._shouldRenderLocalLoading()}
|
||||
mediaType="local"
|
||||
posterUrl={this.props.localPosterUrl}
|
||||
srcVideoObject={this.state.localSrcVideoObject} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<sharedViews.MediaLayoutView
|
||||
dispatcher={this.props.dispatcher}
|
||||
displayScreenShare={displayScreenShare}
|
||||
isLocalLoading={this._isLocalLoading()}
|
||||
isRemoteLoading={this._isRemoteLoading()}
|
||||
isScreenShareLoading={this._isScreenShareLoading()}
|
||||
localPosterUrl={this.props.localPosterUrl}
|
||||
localSrcVideoObject={this.state.localSrcVideoObject}
|
||||
localVideoMuted={this.state.videoMuted}
|
||||
remotePosterUrl={this.props.remotePosterUrl}
|
||||
remoteSrcVideoObject={this.state.remoteSrcVideoObject}
|
||||
renderRemoteVideo={this.shouldRenderRemoteVideo()}
|
||||
screenSharePosterUrl={this.props.screenSharePosterUrl}
|
||||
screenShareVideoObject={this.state.screenShareVideoObject}
|
||||
showContextRoomName={true}
|
||||
useDesktopPaths={false} />
|
||||
<sharedViews.ConversationToolbar
|
||||
audio={{enabled: !this.state.audioMuted,
|
||||
visible: this._roomIsActive()}}
|
||||
|
@ -31,7 +31,6 @@
|
||||
<!-- libs -->
|
||||
<script src="../../content/libs/l10n.js"></script>
|
||||
<script src="../../content/shared/libs/react-0.12.2.js"></script>
|
||||
<script src="../../content/shared/libs/jquery-2.1.4.js"></script>
|
||||
<script src="../../content/shared/libs/lodash-3.9.3.js"></script>
|
||||
<script src="../../content/shared/libs/backbone-1.2.1.js"></script>
|
||||
|
||||
@ -101,7 +100,10 @@
|
||||
});
|
||||
|
||||
mocha.run(function () {
|
||||
$("#mocha").append("<p id='complete'>Complete.</p>");
|
||||
var completeNode = document.createElement("p");
|
||||
completeNode.setAttribute("id", "complete");
|
||||
completeNode.appendChild(document.createTextNode("Complete"));
|
||||
document.getElementById("mocha").appendChild(completeNode);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
@ -30,7 +30,6 @@
|
||||
|
||||
<!-- libs -->
|
||||
<script src="../../content/shared/libs/react-0.12.2.js"></script>
|
||||
<script src="../../content/shared/libs/jquery-2.1.4.js"></script>
|
||||
<script src="../../content/shared/libs/lodash-3.9.3.js"></script>
|
||||
<script src="../../content/shared/libs/backbone-1.2.1.js"></script>
|
||||
<script src="../../standalone/content/libs/l10n-gaia-02ca67948fe8.js"></script>
|
||||
@ -95,7 +94,10 @@
|
||||
});
|
||||
|
||||
mocha.run(function () {
|
||||
$("#mocha").append("<p id='complete'>Complete.</p>");
|
||||
var completeNode = document.createElement("p");
|
||||
completeNode.setAttribute("id", "complete");
|
||||
completeNode.appendChild(document.createTextNode("Complete"));
|
||||
document.getElementById("mocha").appendChild(completeNode);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
@ -50,7 +50,7 @@ describe("loop.shared.views", function() {
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
$("#fixtures").empty();
|
||||
loop.store.StoreMixin.clearRegisteredStores();
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
@ -1045,4 +1045,104 @@ describe("loop.shared.views", function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("MediaLayoutView", function() {
|
||||
var textChatStore, view;
|
||||
|
||||
function mountTestComponent(extraProps) {
|
||||
var defaultProps = {
|
||||
dispatcher: dispatcher,
|
||||
displayScreenShare: false,
|
||||
isLocalLoading: false,
|
||||
isRemoteLoading: false,
|
||||
isScreenShareLoading: false,
|
||||
localVideoMuted: false,
|
||||
renderRemoteVideo: false,
|
||||
showContextRoomName: false,
|
||||
useDesktopPaths: false
|
||||
};
|
||||
|
||||
return TestUtils.renderIntoDocument(
|
||||
React.createElement(sharedViews.MediaLayoutView,
|
||||
_.extend(defaultProps, extraProps)));
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
textChatStore = new loop.store.TextChatStore(dispatcher, {
|
||||
sdkDriver: {}
|
||||
});
|
||||
|
||||
loop.store.StoreMixin.register({textChatStore: textChatStore});
|
||||
});
|
||||
|
||||
it("should mark the remote stream as the focus stream when not displaying screen share", function() {
|
||||
view = mountTestComponent({
|
||||
displayScreenShare: false
|
||||
});
|
||||
|
||||
var node = view.getDOMNode();
|
||||
|
||||
expect(node.querySelector(".remote").classList.contains("focus-stream")).eql(true);
|
||||
expect(node.querySelector(".screen").classList.contains("focus-stream")).eql(false);
|
||||
});
|
||||
|
||||
it("should mark the screen share stream as the focus stream when displaying screen share", function() {
|
||||
view = mountTestComponent({
|
||||
displayScreenShare: true
|
||||
});
|
||||
|
||||
var node = view.getDOMNode();
|
||||
|
||||
expect(node.querySelector(".remote").classList.contains("focus-stream")).eql(false);
|
||||
expect(node.querySelector(".screen").classList.contains("focus-stream")).eql(true);
|
||||
});
|
||||
|
||||
it("should not mark the wrapper as receiving screen share when not displaying a screen share", function() {
|
||||
view = mountTestComponent({
|
||||
displayScreenShare: false
|
||||
});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".media-wrapper")
|
||||
.classList.contains("receiving-screen-share")).eql(false);
|
||||
});
|
||||
|
||||
it("should mark the wrapper as receiving screen share when displaying a screen share", function() {
|
||||
view = mountTestComponent({
|
||||
displayScreenShare: true
|
||||
});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".media-wrapper")
|
||||
.classList.contains("receiving-screen-share")).eql(true);
|
||||
});
|
||||
|
||||
it("should not mark the wrapper as showing local streams when not displaying a stream", function() {
|
||||
view = mountTestComponent({
|
||||
localSrcVideoObject: null,
|
||||
localPosterUrl: null
|
||||
});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".media-wrapper")
|
||||
.classList.contains("showing-local-streams")).eql(false);
|
||||
});
|
||||
|
||||
it("should mark the wrapper as showing local streams when displaying a stream", function() {
|
||||
view = mountTestComponent({
|
||||
localSrcVideoObject: {},
|
||||
localPosterUrl: null
|
||||
});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".media-wrapper")
|
||||
.classList.contains("showing-local-streams")).eql(true);
|
||||
});
|
||||
|
||||
it("should mark the wrapper as showing local streams when displaying a poster url", function() {
|
||||
view = mountTestComponent({
|
||||
localSrcVideoObject: {},
|
||||
localPosterUrl: "fake/url"
|
||||
});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".media-wrapper")
|
||||
.classList.contains("showing-local-streams")).eql(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -85,12 +85,15 @@
|
||||
|
||||
describe("Unexpected Warnings Check", function() {
|
||||
it("should long only the warnings we expect", function() {
|
||||
chai.expect(caughtWarnings.length).to.eql(11);
|
||||
chai.expect(caughtWarnings.length).to.eql(10);
|
||||
});
|
||||
});
|
||||
|
||||
mocha.run(function () {
|
||||
$("#mocha").append("<p id='complete'>Complete.</p>");
|
||||
var completeNode = document.createElement("p");
|
||||
completeNode.setAttribute("id", "complete");
|
||||
completeNode.appendChild(document.createTextNode("Complete"));
|
||||
document.getElementById("mocha").appendChild(completeNode);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
@ -431,7 +431,7 @@ describe("loop.standaloneRoomViews", function() {
|
||||
"remoteSrcVideoObject is false, mediaConnected is true", function() {
|
||||
activeRoomStore.setStoreState({
|
||||
roomState: ROOM_STATES.HAS_PARTICIPANTS,
|
||||
remoteSrcVideoObject: false,
|
||||
remoteSrcVideoObject: null,
|
||||
remoteVideoEnabled: false,
|
||||
mediaConnected: true
|
||||
});
|
||||
|
@ -18,6 +18,11 @@ var gContentPane = {
|
||||
if (Services.prefs.getBoolPref(prefName)) {
|
||||
let row = document.getElementById("translationBox");
|
||||
row.removeAttribute("hidden");
|
||||
// Showing attribution only for Bing Translator.
|
||||
Components.utils.import("resource:///modules/translation/Translation.jsm");
|
||||
if (Translation.translationEngine == "bing") {
|
||||
document.getElementById("bingAttribution").removeAttribute("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
let drmInfoURL =
|
||||
|
@ -163,11 +163,13 @@
|
||||
label="&translateWebPages.label;." accesskey="&translateWebPages.accesskey;"
|
||||
onsyncfrompreference="return gContentPane.updateButtons('translateButton',
|
||||
'browser.translation.detectLanguage');"/>
|
||||
<label>&translation.options.attribution.beforeLogo;</label>
|
||||
<image id="translationAttributionImage" aria-label="Microsoft Translator"
|
||||
onclick="gContentPane.openTranslationProviderAttribution()"
|
||||
src="chrome://browser/content/microsoft-translator-attribution.png"/>
|
||||
<label>&translation.options.attribution.afterLogo;</label>
|
||||
<hbox id="bingAttribution" hidden="true">
|
||||
<label>&translation.options.attribution.beforeLogo;</label>
|
||||
<image id="translationAttributionImage" aria-label="Microsoft Translator"
|
||||
onclick="gContentPane.openTranslationProviderAttribution()"
|
||||
src="chrome://browser/content/microsoft-translator-attribution.png"/>
|
||||
<label>&translation.options.attribution.afterLogo;</label>
|
||||
</hbox>
|
||||
</hbox>
|
||||
<button id="translateButton" label="&translateExceptions.label;"
|
||||
oncommand="gContentPane.showTranslationExceptions();"
|
||||
|
@ -23,6 +23,11 @@ var gContentPane = {
|
||||
if (Services.prefs.getBoolPref(prefName)) {
|
||||
let row = document.getElementById("translationBox");
|
||||
row.removeAttribute("hidden");
|
||||
// Showing attribution only for Bing Translator.
|
||||
Components.utils.import("resource:///modules/translation/Translation.jsm");
|
||||
if (Translation.translationEngine == "bing") {
|
||||
document.getElementById("bingAttribution").removeAttribute("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
setEventListener("font.language.group", "change",
|
||||
|
@ -160,12 +160,14 @@
|
||||
label="&translateWebPages.label;." accesskey="&translateWebPages.accesskey;"
|
||||
onsyncfrompreference="return gContentPane.updateButtons('translateButton',
|
||||
'browser.translation.detectLanguage');"/>
|
||||
<label>&translation.options.attribution.beforeLogo;</label>
|
||||
<separator orient="vertical" class="thin"/>
|
||||
<image id="translationAttributionImage" aria-label="Microsoft Translator"
|
||||
src="chrome://browser/content/microsoft-translator-attribution.png"/>
|
||||
<separator orient="vertical" class="thin"/>
|
||||
<label>&translation.options.attribution.afterLogo;</label>
|
||||
<hbox id="bingAttribution" hidden="true">
|
||||
<label>&translation.options.attribution.beforeLogo;</label>
|
||||
<separator orient="vertical" class="thin"/>
|
||||
<image id="translationAttributionImage" aria-label="Microsoft Translator"
|
||||
src="chrome://browser/content/microsoft-translator-attribution.png"/>
|
||||
<separator orient="vertical" class="thin"/>
|
||||
<label>&translation.options.attribution.afterLogo;</label>
|
||||
</hbox>
|
||||
</hbox>
|
||||
<button id="translateButton" label="&translateExceptions.label;"
|
||||
accesskey="&translateExceptions.accesskey;"/>
|
||||
|
@ -23,7 +23,6 @@ support-files =
|
||||
[browser_privatebrowsing_certexceptionsui.js]
|
||||
[browser_privatebrowsing_concurrent.js]
|
||||
[browser_privatebrowsing_cookieacceptdialog.js]
|
||||
skip-if = e10s # Bug 1139953 - Accept cookie dialog shown in private window when e10s enabled
|
||||
[browser_privatebrowsing_crh.js]
|
||||
[browser_privatebrowsing_downloadLastDir.js]
|
||||
[browser_privatebrowsing_downloadLastDir_c.js]
|
||||
|
@ -40,33 +40,29 @@ add_task(function* () {
|
||||
// Now we'll set a new unique value on 1 of the tabs
|
||||
let newUniq = r();
|
||||
ss.setTabValue(gBrowser.tabs[1], "uniq", newUniq);
|
||||
yield promiseRemoveTab(gBrowser.tabs[1]);
|
||||
let closedTabData = (JSON.parse(ss.getClosedTabData(window)))[0];
|
||||
is(closedTabData.state.extData.uniq, newUniq,
|
||||
let tabState = JSON.parse(ss.getTabState(gBrowser.tabs[1]));
|
||||
is(tabState.extData.uniq, newUniq,
|
||||
"(overwriting) new data is stored in extData");
|
||||
|
||||
// hide the next tab before closing it
|
||||
gBrowser.hideTab(gBrowser.tabs[1]);
|
||||
yield promiseRemoveTab(gBrowser.tabs[1]);
|
||||
closedTabData = (JSON.parse(ss.getClosedTabData(window)))[0];
|
||||
ok(closedTabData.state.hidden, "(hiding) tab data has hidden == true");
|
||||
gBrowser.hideTab(gBrowser.tabs[2]);
|
||||
tabState = JSON.parse(ss.getTabState(gBrowser.tabs[2]));
|
||||
ok(tabState.hidden, "(hiding) tab data has hidden == true");
|
||||
|
||||
// set data that's not in a conflicting key
|
||||
let stillUniq = r();
|
||||
ss.setTabValue(gBrowser.tabs[1], "stillUniq", stillUniq);
|
||||
yield promiseRemoveTab(gBrowser.tabs[1]);
|
||||
closedTabData = (JSON.parse(ss.getClosedTabData(window)))[0];
|
||||
is(closedTabData.state.extData.stillUniq, stillUniq,
|
||||
ss.setTabValue(gBrowser.tabs[3], "stillUniq", stillUniq);
|
||||
tabState = JSON.parse(ss.getTabState(gBrowser.tabs[3]));
|
||||
is(tabState.extData.stillUniq, stillUniq,
|
||||
"(adding) new data is stored in extData");
|
||||
|
||||
// remove the uniq value and make sure it's not there in the closed data
|
||||
ss.deleteTabValue(gBrowser.tabs[1], "uniq");
|
||||
yield promiseRemoveTab(gBrowser.tabs[1]);
|
||||
closedTabData = (JSON.parse(ss.getClosedTabData(window)))[0];
|
||||
ss.deleteTabValue(gBrowser.tabs[4], "uniq");
|
||||
tabState = JSON.parse(ss.getTabState(gBrowser.tabs[4]));
|
||||
// Since Panorama might have put data in, first check if there is extData.
|
||||
// If there is explicitly check that "uniq" isn't in it. Otherwise, we're ok
|
||||
if ("extData" in closedTabData.state) {
|
||||
ok(!("uniq" in closedTabData.state.extData),
|
||||
if ("extData" in tabState) {
|
||||
ok(!("uniq" in tabState.extData),
|
||||
"(deleting) uniq not in existing extData");
|
||||
}
|
||||
else {
|
||||
@ -75,11 +71,14 @@ add_task(function* () {
|
||||
|
||||
// set unique data on the tab that never had any set, make sure that's saved
|
||||
let newUniq2 = r();
|
||||
ss.setTabValue(gBrowser.tabs[1], "uniq", newUniq2);
|
||||
yield promiseRemoveTab(gBrowser.tabs[1]);
|
||||
closedTabData = (JSON.parse(ss.getClosedTabData(window)))[0];
|
||||
is(closedTabData.state.extData.uniq, newUniq2,
|
||||
ss.setTabValue(gBrowser.tabs[5], "uniq", newUniq2);
|
||||
tabState = JSON.parse(ss.getTabState(gBrowser.tabs[5]));
|
||||
is(tabState.extData.uniq, newUniq2,
|
||||
"(creating) new data is stored in extData where there was none");
|
||||
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
yield promiseRemoveTab(gBrowser.tabs[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the test state.
|
||||
|
@ -3,6 +3,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsWindowsShellService.h"
|
||||
|
||||
#include "imgIContainer.h"
|
||||
#include "imgIRequest.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
@ -17,7 +19,6 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsShellService.h"
|
||||
#include "nsWindowsShellService.h"
|
||||
#include "nsIProcess.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsBrowserCompsCID.h"
|
||||
@ -85,6 +86,38 @@ OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetPrefString(const nsCString& aPrefName, nsAString& aValue)
|
||||
{
|
||||
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
if (!prefs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString prefCStr;
|
||||
nsresult rv = prefs->GetCharPref(aPrefName.get(),
|
||||
getter_Copies(prefCStr));
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
CopyUTF8toUTF16(prefCStr, aValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SetPrefString(const nsCString& aPrefName, const nsString& aValue)
|
||||
{
|
||||
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
if (!prefs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult rv = prefs->SetCharPref(aPrefName.get(),
|
||||
NS_ConvertUTF16toUTF8(aValue).get());
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Default Browser Registry Settings
|
||||
//
|
||||
@ -322,38 +355,219 @@ nsWindowsShellService::ShortcutMaintenance()
|
||||
}
|
||||
|
||||
static bool
|
||||
IsAARDefaultHTTP(IApplicationAssociationRegistration* pAAR,
|
||||
bool* aIsDefaultBrowser)
|
||||
IsAARDefault(const nsRefPtr<IApplicationAssociationRegistration>& pAAR,
|
||||
LPCWSTR aClassName)
|
||||
{
|
||||
// Make sure the Prog ID matches what we have
|
||||
LPWSTR registeredApp;
|
||||
HRESULT hr = pAAR->QueryCurrentDefault(L"http", AT_URLPROTOCOL, AL_EFFECTIVE,
|
||||
bool isProtocol = *aClassName != L'.';
|
||||
ASSOCIATIONTYPE queryType = isProtocol ? AT_URLPROTOCOL : AT_FILEEXTENSION;
|
||||
HRESULT hr = pAAR->QueryCurrentDefault(aClassName, queryType, AL_EFFECTIVE,
|
||||
®isteredApp);
|
||||
if (SUCCEEDED(hr)) {
|
||||
LPCWSTR firefoxHTTPProgID = L"FirefoxURL";
|
||||
*aIsDefaultBrowser = !wcsicmp(registeredApp, firefoxHTTPProgID);
|
||||
CoTaskMemFree(registeredApp);
|
||||
} else {
|
||||
*aIsDefaultBrowser = false;
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
|
||||
LPCWSTR progID = isProtocol ? L"FirefoxURL" : L"FirefoxHTML";
|
||||
bool isDefault = !wcsicmp(registeredApp, progID);
|
||||
CoTaskMemFree(registeredApp);
|
||||
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
static void
|
||||
GetUserChoiceKeyName(LPCWSTR aClassName, bool aIsProtocol,
|
||||
nsAString& aKeyName)
|
||||
{
|
||||
aKeyName.AssignLiteral(aIsProtocol
|
||||
? "Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\"
|
||||
: "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\");
|
||||
aKeyName.Append(aClassName);
|
||||
aKeyName.AppendLiteral("\\UserChoice");
|
||||
}
|
||||
|
||||
static void
|
||||
GetHashPrefName(LPCWSTR aClassName, nsACString& aPrefName)
|
||||
{
|
||||
aPrefName.AssignLiteral("browser.shell.associationHash.");
|
||||
aPrefName.Append(NS_ConvertUTF16toUTF8(*aClassName == L'.' ? aClassName + 1
|
||||
: aClassName));
|
||||
}
|
||||
|
||||
static bool
|
||||
IsAARDefaultHTML(IApplicationAssociationRegistration* pAAR,
|
||||
bool* aIsDefaultBrowser)
|
||||
SaveWin8RegistryHash(const nsRefPtr<IApplicationAssociationRegistration>& pAAR,
|
||||
LPCWSTR aClassName)
|
||||
{
|
||||
LPWSTR registeredApp;
|
||||
HRESULT hr = pAAR->QueryCurrentDefault(L".html", AT_FILEEXTENSION, AL_EFFECTIVE,
|
||||
®isteredApp);
|
||||
if (SUCCEEDED(hr)) {
|
||||
LPCWSTR firefoxHTMLProgID = L"FirefoxHTML";
|
||||
*aIsDefaultBrowser = !wcsicmp(registeredApp, firefoxHTMLProgID);
|
||||
CoTaskMemFree(registeredApp);
|
||||
} else {
|
||||
*aIsDefaultBrowser = false;
|
||||
bool isProtocol = *aClassName != L'.';
|
||||
bool isDefault = IsAARDefault(pAAR, aClassName);
|
||||
// We can save the value only if Firefox is the default.
|
||||
if (!isDefault) {
|
||||
return isDefault;
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
|
||||
nsAutoString keyName;
|
||||
GetUserChoiceKeyName(aClassName, isProtocol, keyName);
|
||||
|
||||
nsCOMPtr<nsIWindowsRegKey> regKey =
|
||||
do_CreateInstance("@mozilla.org/windows-registry-key;1");
|
||||
if (!regKey) {
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
keyName, nsIWindowsRegKey::ACCESS_READ);
|
||||
if (NS_FAILED(rv)) {
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
nsAutoString hash;
|
||||
rv = regKey->ReadStringValue(NS_LITERAL_STRING("Hash"), hash);
|
||||
if (NS_FAILED(rv)) {
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
nsAutoCString prefName;
|
||||
GetHashPrefName(aClassName, prefName);
|
||||
SetPrefString(prefName, hash);
|
||||
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
static bool
|
||||
RestoreWin8RegistryHash(const nsRefPtr<IApplicationAssociationRegistration>& pAAR,
|
||||
LPCWSTR aClassName)
|
||||
{
|
||||
nsAutoCString prefName;
|
||||
GetHashPrefName(aClassName, prefName);
|
||||
nsAutoString hash;
|
||||
if (!GetPrefString(prefName, hash)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isProtocol = *aClassName != L'.';
|
||||
nsString progId = isProtocol ? NS_LITERAL_STRING("FirefoxURL")
|
||||
: NS_LITERAL_STRING("FirefoxHTML");
|
||||
|
||||
nsAutoString keyName;
|
||||
GetUserChoiceKeyName(aClassName, isProtocol, keyName);
|
||||
|
||||
nsCOMPtr<nsIWindowsRegKey> regKey =
|
||||
do_CreateInstance("@mozilla.org/windows-registry-key;1");
|
||||
if (!regKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
keyName, nsIWindowsRegKey::ACCESS_READ);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsAutoString currValue;
|
||||
if (NS_SUCCEEDED(regKey->ReadStringValue(NS_LITERAL_STRING("Hash"),
|
||||
currValue)) &&
|
||||
currValue.Equals(hash) &&
|
||||
NS_SUCCEEDED(regKey->ReadStringValue(NS_LITERAL_STRING("ProgId"),
|
||||
currValue)) &&
|
||||
currValue.Equals(progId)) {
|
||||
// The value is already set.
|
||||
return true;
|
||||
}
|
||||
// We need to close this explicitly because nsIWindowsRegKey::SetKey
|
||||
// does not close the old key.
|
||||
regKey->Close();
|
||||
}
|
||||
|
||||
// We have to use the registry function directly because
|
||||
// nsIWindowsRegKey::Create will only return NS_ERROR_FAILURE
|
||||
// on failure.
|
||||
HKEY theKey;
|
||||
DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0,
|
||||
KEY_READ | KEY_SET_VALUE, &theKey);
|
||||
if (REG_FAILED(res)) {
|
||||
if (res != ERROR_ACCESS_DENIED && res != ERROR_FILE_NOT_FOUND) {
|
||||
return false;
|
||||
}
|
||||
if (res == ERROR_ACCESS_DENIED) {
|
||||
res = ::RegDeleteKeyW(HKEY_CURRENT_USER, keyName.get());
|
||||
if (REG_FAILED(res)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
res = ::RegCreateKeyExW(HKEY_CURRENT_USER, keyName.get(), 0,
|
||||
nullptr, 0, KEY_READ | KEY_SET_VALUE,
|
||||
nullptr, &theKey, nullptr);
|
||||
if (REG_FAILED(res)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
regKey->SetKey(theKey);
|
||||
|
||||
rv = regKey->WriteStringValue(NS_LITERAL_STRING("Hash"), hash);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rv = regKey->WriteStringValue(NS_LITERAL_STRING("ProgId"), progId);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsAARDefault(pAAR, aClassName);
|
||||
}
|
||||
|
||||
static void
|
||||
SaveWin8RegistryHashes(bool aCheckAllTypes, bool* aIsDefaultBrowser)
|
||||
{
|
||||
nsRefPtr<IApplicationAssociationRegistration> pAAR;
|
||||
HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
|
||||
nullptr,
|
||||
CLSCTX_INPROC,
|
||||
IID_IApplicationAssociationRegistration,
|
||||
getter_AddRefs(pAAR));
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool res = SaveWin8RegistryHash(pAAR, L"http");
|
||||
if (*aIsDefaultBrowser) {
|
||||
*aIsDefaultBrowser = res;
|
||||
}
|
||||
SaveWin8RegistryHash(pAAR, L"https");
|
||||
SaveWin8RegistryHash(pAAR, L"ftp");
|
||||
res = SaveWin8RegistryHash(pAAR, L".html");
|
||||
if (*aIsDefaultBrowser && aCheckAllTypes) {
|
||||
*aIsDefaultBrowser = res;
|
||||
}
|
||||
SaveWin8RegistryHash(pAAR, L".htm");
|
||||
SaveWin8RegistryHash(pAAR, L".shtml");
|
||||
SaveWin8RegistryHash(pAAR, L".xhtml");
|
||||
SaveWin8RegistryHash(pAAR, L".xht");
|
||||
}
|
||||
|
||||
static bool
|
||||
RestoreWin8RegistryHashes(bool aClaimAllTypes)
|
||||
{
|
||||
nsRefPtr<IApplicationAssociationRegistration> pAAR;
|
||||
HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
|
||||
nullptr,
|
||||
CLSCTX_INPROC,
|
||||
IID_IApplicationAssociationRegistration,
|
||||
getter_AddRefs(pAAR));
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool res = RestoreWin8RegistryHash(pAAR, L"http");
|
||||
res = RestoreWin8RegistryHash(pAAR, L"https") && res;
|
||||
RestoreWin8RegistryHash(pAAR, L"ftp");
|
||||
bool res2 = RestoreWin8RegistryHash(pAAR, L".html");
|
||||
res2 = RestoreWin8RegistryHash(pAAR, L".htm") && res2;
|
||||
if (aClaimAllTypes) {
|
||||
res = res && res2;
|
||||
}
|
||||
RestoreWin8RegistryHash(pAAR, L".shtml");
|
||||
RestoreWin8RegistryHash(pAAR, L".xhtml");
|
||||
RestoreWin8RegistryHash(pAAR, L".xht");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -366,37 +580,27 @@ bool
|
||||
nsWindowsShellService::IsDefaultBrowserVista(bool aCheckAllTypes,
|
||||
bool* aIsDefaultBrowser)
|
||||
{
|
||||
IApplicationAssociationRegistration* pAAR;
|
||||
nsRefPtr<IApplicationAssociationRegistration> pAAR;
|
||||
HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
|
||||
nullptr,
|
||||
CLSCTX_INPROC,
|
||||
IID_IApplicationAssociationRegistration,
|
||||
(void**)&pAAR);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (aCheckAllTypes) {
|
||||
BOOL res;
|
||||
hr = pAAR->QueryAppIsDefaultAll(AL_EFFECTIVE,
|
||||
APP_REG_NAME,
|
||||
&res);
|
||||
*aIsDefaultBrowser = res;
|
||||
|
||||
// If we have all defaults, let's make sure that our ProgID
|
||||
// is explicitly returned as well. Needed only for Windows 8.
|
||||
if (*aIsDefaultBrowser && IsWin8OrLater()) {
|
||||
IsAARDefaultHTTP(pAAR, aIsDefaultBrowser);
|
||||
if (*aIsDefaultBrowser) {
|
||||
IsAARDefaultHTML(pAAR, aIsDefaultBrowser);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
IsAARDefaultHTTP(pAAR, aIsDefaultBrowser);
|
||||
}
|
||||
|
||||
pAAR->Release();
|
||||
return true;
|
||||
getter_AddRefs(pAAR));
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
if (aCheckAllTypes) {
|
||||
BOOL res;
|
||||
hr = pAAR->QueryAppIsDefaultAll(AL_EFFECTIVE,
|
||||
APP_REG_NAME,
|
||||
&res);
|
||||
*aIsDefaultBrowser = res;
|
||||
} else if (!IsWin8OrLater()) {
|
||||
*aIsDefaultBrowser = IsAARDefault(pAAR, L"http");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -496,6 +700,9 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck,
|
||||
// previous checks show that Firefox is the default browser.
|
||||
if (*aIsDefaultBrowser) {
|
||||
IsDefaultBrowserVista(aForAllTypes, aIsDefaultBrowser);
|
||||
if (IsWin8OrLater()) {
|
||||
SaveWin8RegistryHashes(aForAllTypes, aIsDefaultBrowser);
|
||||
}
|
||||
}
|
||||
|
||||
// To handle the case where DDE isn't disabled due for a user because there
|
||||
@ -730,7 +937,8 @@ nsWindowsShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers)
|
||||
}
|
||||
|
||||
nsresult rv = LaunchHelper(appHelperPath);
|
||||
if (NS_SUCCEEDED(rv) && IsWin8OrLater()) {
|
||||
if (NS_SUCCEEDED(rv) && IsWin8OrLater() &&
|
||||
!RestoreWin8RegistryHashes(aClaimAllTypes)) {
|
||||
if (aClaimAllTypes) {
|
||||
if (IsWin10OrLater()) {
|
||||
rv = LaunchModernSettingsDialogDefaultApps();
|
||||
@ -760,6 +968,8 @@ nsWindowsShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers)
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = LaunchControlPanelDefaultsSelectionUI();
|
||||
}
|
||||
bool isDefault;
|
||||
SaveWin8RegistryHashes(aClaimAllTypes, &isDefault);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,10 +84,34 @@ this.Translation = {
|
||||
},
|
||||
|
||||
openProviderAttribution: function() {
|
||||
let attribution = this.supportedEngines[this.translationEngine];
|
||||
Cu.import("resource:///modules/RecentWindow.jsm");
|
||||
RecentWindow.getMostRecentBrowserWindow().openUILinkIn(
|
||||
"http://aka.ms/MicrosoftTranslatorAttribution", "tab");
|
||||
}
|
||||
RecentWindow.getMostRecentBrowserWindow().openUILinkIn(attribution, "tab");
|
||||
},
|
||||
|
||||
/**
|
||||
* The list of translation engines and their attributions.
|
||||
*/
|
||||
supportedEngines: {
|
||||
"bing" : "http://aka.ms/MicrosoftTranslatorAttribution",
|
||||
"yandex" : "http://translate.yandex.com/"
|
||||
},
|
||||
|
||||
/**
|
||||
* Fallback engine (currently Bing Translator) if the preferences seem
|
||||
* confusing.
|
||||
*/
|
||||
get defaultEngine() {
|
||||
return this.supportedEngines.keys[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the name of the preferred translation engine.
|
||||
*/
|
||||
get translationEngine() {
|
||||
let engine = Services.prefs.getCharPref("browser.translation.engine");
|
||||
return Object.keys(this.supportedEngines).includes(engine) ? engine : this.defaultEngine;
|
||||
},
|
||||
};
|
||||
|
||||
/* TranslationUI objects keep the information related to translation for
|
||||
|
@ -8,18 +8,22 @@
|
||||
|
||||
const kEnginePref = "browser.translation.engine";
|
||||
const kApiKeyPref = "browser.translation.yandex.apiKeyOverride";
|
||||
const kShowUIPref = "browser.translation.ui.show";
|
||||
|
||||
const {YandexTranslator} = Cu.import("resource:///modules/translation/YandexTranslator.jsm", {});
|
||||
const {TranslationDocument} = Cu.import("resource:///modules/translation/TranslationDocument.jsm", {});
|
||||
const {Promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
const {Translation} = Cu.import("resource:///modules/translation/Translation.jsm", {});
|
||||
|
||||
add_task(function* setup() {
|
||||
Services.prefs.setCharPref(kEnginePref, "yandex");
|
||||
Services.prefs.setCharPref(kApiKeyPref, "yandexValidKey");
|
||||
Services.prefs.setBoolPref(kShowUIPref, true);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref(kEnginePref);
|
||||
Services.prefs.clearUserPref(kApiKeyPref);
|
||||
Services.prefs.clearUserPref(kShowUIPref);
|
||||
});
|
||||
});
|
||||
|
||||
@ -45,6 +49,38 @@ add_task(function* test_yandex_translation() {
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
/**
|
||||
* Ensure that Yandex.Translate is propertly attributed.
|
||||
*/
|
||||
add_task(function* test_yandex_attribution() {
|
||||
// Loading the fixture page.
|
||||
let url = constructFixtureURL("bug1022725-fr.html");
|
||||
let tab = yield promiseTestPageLoad(url);
|
||||
|
||||
info("Show an info bar saying the current page is in French");
|
||||
let notif = showTranslationUI(tab, "fr");
|
||||
let attribution = notif._getAnonElt("translationEngine").selectedIndex;
|
||||
Assert.equal(attribution, 1, "Yandex attribution should be shown.");
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
|
||||
add_task(function* test_preference_attribution() {
|
||||
|
||||
let prefUrl = "about:preferences#content";
|
||||
let tab = yield promiseTestPageLoad(prefUrl);
|
||||
|
||||
let browser = gBrowser.getBrowserForTab(tab);
|
||||
let win = browser.contentWindow;
|
||||
let bingAttribution = win.document.getElementById("bingAttribution");
|
||||
ok(bingAttribution, "Bing attribution should exist.");
|
||||
ok(bingAttribution.hidden, "Bing attribution should be hidden.");
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* A helper function for constructing a URL to a page stored in the
|
||||
* local fixture folder.
|
||||
@ -79,3 +115,12 @@ function promiseTestPageLoad(url) {
|
||||
}, true);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function showTranslationUI(tab, aDetectedLanguage) {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
Translation.documentStateReceived(browser, {state: Translation.STATE_OFFER,
|
||||
originalShown: true,
|
||||
detectedLanguage: aDetectedLanguage});
|
||||
let ui = browser.translationUI;
|
||||
return ui.notificationBox.getNotificationWithValue("translation");
|
||||
}
|
||||
|
@ -127,12 +127,17 @@
|
||||
<xul:menuitem oncommand="openPreferences('paneContent');"
|
||||
label="&translation.options.preferences.label;"
|
||||
accesskey="&translation.options.preferences.accesskey;"/>
|
||||
<xul:menuitem class="translation-attribution subviewbutton panel-subview-footer"
|
||||
<xul:menuitem class="subviewbutton panel-subview-footer"
|
||||
oncommand="document.getBindingParent(this).openProviderAttribution();">
|
||||
<xul:label>&translation.options.attribution.beforeLogo;</xul:label>
|
||||
<xul:image src="chrome://browser/content/microsoft-translator-attribution.png"
|
||||
aria-label="Microsoft Translator"/>
|
||||
<xul:label>&translation.options.attribution.afterLogo;</xul:label>
|
||||
<xul:deck anonid="translationEngine" selectedIndex="0">
|
||||
<xul:hbox class="translation-attribution">
|
||||
<xul:label>&translation.options.attribution.beforeLogo;</xul:label>
|
||||
<xul:image src="chrome://browser/content/microsoft-translator-attribution.png"
|
||||
aria-label="Microsoft Translator"/>
|
||||
<xul:label>&translation.options.attribution.afterLogo;</xul:label>
|
||||
</xul:hbox>
|
||||
<xul:label class="translation-attribution">&translation.options.attribution.yandexTranslate;</xul:label>
|
||||
</xul:deck>
|
||||
</xul:menuitem>
|
||||
</xul:menupopup>
|
||||
</xul:button>
|
||||
@ -215,6 +220,13 @@
|
||||
if (aTranslation.state)
|
||||
this.state = aTranslation.state;
|
||||
|
||||
// Show attribution for the preferred translator.
|
||||
let engineIndex = Object.keys(Translation.supportedEngines)
|
||||
.indexOf(Translation.translationEngine);
|
||||
if (engineIndex != -1) {
|
||||
this._getAnonElt('translationEngine').selectedIndex = engineIndex;
|
||||
}
|
||||
|
||||
const kWelcomePref = "browser.translation.ui.welcomeMessageShown";
|
||||
if (Services.prefs.prefHasUserValue(kWelcomePref) ||
|
||||
this.translation.browser != gBrowser.selectedBrowser)
|
||||
|
@ -1176,13 +1176,25 @@ InspectorPanel.prototype = {
|
||||
|
||||
/**
|
||||
* This method is here for the benefit of the node-menu-link-follow menu item
|
||||
* in the inspector contextual-menu. It's behavior depends on which node was
|
||||
* right-clicked when the menu was opened.
|
||||
* in the inspector contextual-menu.
|
||||
*/
|
||||
followAttributeLink: function(e) {
|
||||
onFollowLink: function() {
|
||||
let type = this.panelDoc.popupNode.dataset.type;
|
||||
let link = this.panelDoc.popupNode.dataset.link;
|
||||
|
||||
this.followAttributeLink(type, link);
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a type and link found in a node's attribute in the markup-view,
|
||||
* attempt to follow that link (which may result in opening a new tab, the
|
||||
* style editor or debugger).
|
||||
*/
|
||||
followAttributeLink: function(type, link) {
|
||||
if (!type || !link) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === "uri" || type === "cssresource" || type === "jsresource") {
|
||||
// Open link in a new tab.
|
||||
// When the inspector menu was setup on click (see _setupNodeLinkMenu), we
|
||||
@ -1213,11 +1225,18 @@ InspectorPanel.prototype = {
|
||||
|
||||
/**
|
||||
* This method is here for the benefit of the node-menu-link-copy menu item
|
||||
* in the inspector contextual-menu. It's behavior depends on which node was
|
||||
* right-clicked when the menu was opened.
|
||||
* in the inspector contextual-menu.
|
||||
*/
|
||||
copyAttributeLink: function(e) {
|
||||
onCopyLink: function() {
|
||||
let link = this.panelDoc.popupNode.dataset.link;
|
||||
|
||||
this.copyAttributeLink(link);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method is here for the benefit of copying links.
|
||||
*/
|
||||
copyAttributeLink: function(link) {
|
||||
// When the inspector menu was setup on click (see _setupNodeLinkMenu), we
|
||||
// already checked that resolveRelativeURL existed.
|
||||
this.inspector.resolveRelativeURL(link, this.selection.nodeFront).then(url => {
|
||||
|
@ -106,9 +106,9 @@
|
||||
oncommand="inspector.deleteNode()"/>
|
||||
<menuseparator id="node-menu-link-separator"/>
|
||||
<menuitem id="node-menu-link-follow"
|
||||
oncommand="inspector.followAttributeLink()"/>
|
||||
oncommand="inspector.onFollowLink()"/>
|
||||
<menuitem id="node-menu-link-copy"
|
||||
oncommand="inspector.copyAttributeLink()"/>
|
||||
oncommand="inspector.onCopyLink()"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="node-menu-pseudo-hover"
|
||||
label=":hover" type="checkbox"
|
||||
|
@ -1933,6 +1933,15 @@ MarkupContainer.prototype = {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
let isMiddleClick = event.button === 1;
|
||||
let isMetaClick = event.button === 0 && (event.metaKey || event.ctrlKey);
|
||||
|
||||
if (isMiddleClick || isMetaClick) {
|
||||
let link = target.dataset.link;
|
||||
let type = target.dataset.type;
|
||||
this.markup._inspector.followAttributeLink(type, link);
|
||||
}
|
||||
|
||||
// Start dragging the container after a delay.
|
||||
this.markup._dragStartEl = target;
|
||||
setTimeout(() => {
|
||||
|
@ -79,6 +79,7 @@ skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
|
||||
[browser_markupview_links_04.js]
|
||||
[browser_markupview_links_05.js]
|
||||
[browser_markupview_links_06.js]
|
||||
[browser_markupview_links_07.js]
|
||||
[browser_markupview_load_01.js]
|
||||
[browser_markupview_html_edit_01.js]
|
||||
[browser_markupview_html_edit_02.js]
|
||||
|
@ -22,7 +22,7 @@ add_task(function*() {
|
||||
|
||||
info("Follow the link and wait for the new tab to open");
|
||||
let onTabOpened = once(gBrowser.tabContainer, "TabOpen");
|
||||
inspector.followAttributeLink();
|
||||
inspector.onFollowLink();
|
||||
let {target: tab} = yield onTabOpened;
|
||||
yield waitForTabLoad(tab);
|
||||
|
||||
@ -41,7 +41,7 @@ add_task(function*() {
|
||||
|
||||
info("Follow the link and wait for the new node to be selected");
|
||||
let onSelection = inspector.selection.once("new-node-front");
|
||||
inspector.followAttributeLink();
|
||||
inspector.onFollowLink();
|
||||
yield onSelection;
|
||||
|
||||
ok(true, "A new node was selected");
|
||||
@ -57,7 +57,7 @@ add_task(function*() {
|
||||
|
||||
info("Try to follow the link and check that no new node were selected");
|
||||
let onFailed = inspector.once("idref-attribute-link-failed");
|
||||
inspector.followAttributeLink();
|
||||
inspector.onFollowLink();
|
||||
yield onFailed;
|
||||
|
||||
ok(true, "The node selection failed");
|
||||
|
@ -22,7 +22,7 @@ add_task(function*() {
|
||||
|
||||
info("Follow the link and wait for the style-editor to open");
|
||||
let onStyleEditorReady = toolbox.once("styleeditor-ready");
|
||||
inspector.followAttributeLink();
|
||||
inspector.onFollowLink();
|
||||
yield onStyleEditorReady;
|
||||
|
||||
// No real need to test that the editor opened on the right file here as this
|
||||
@ -42,7 +42,7 @@ add_task(function*() {
|
||||
|
||||
info("Follow the link and wait for the debugger to open");
|
||||
let onDebuggerReady = toolbox.once("jsdebugger-ready");
|
||||
inspector.followAttributeLink();
|
||||
inspector.onFollowLink();
|
||||
yield onDebuggerReady;
|
||||
|
||||
// No real need to test that the debugger opened on the right file here as
|
||||
|
118
browser/devtools/markupview/test/browser_markupview_links_07.js
Normal file
118
browser/devtools/markupview/test/browser_markupview_links_07.js
Normal file
@ -0,0 +1,118 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that a middle-click or meta/ctrl-click on links in attributes actually
|
||||
// do follows the link.
|
||||
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_links.html";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
|
||||
info("Select a node with a URI attribute");
|
||||
yield selectNode("video", inspector);
|
||||
|
||||
info("Find the link element from the markup-view");
|
||||
let {editor} = yield getContainerForSelector("video", inspector);
|
||||
let linkEl = editor.attrElements.get("poster").querySelector(".link");
|
||||
|
||||
info("Follow the link with middle-click and wait for the new tab to open");
|
||||
yield followLinkWaitForTab(linkEl, false,
|
||||
TEST_URL_ROOT + "doc_markup_tooltip.png");
|
||||
|
||||
info("Follow the link with meta/ctrl-click and wait for the new tab to open");
|
||||
yield followLinkWaitForTab(linkEl, true,
|
||||
TEST_URL_ROOT + "doc_markup_tooltip.png");
|
||||
|
||||
info("Select a node with a IDREF attribute");
|
||||
yield selectNode("label", inspector);
|
||||
|
||||
info("Find the link element from the markup-view that contains the ref");
|
||||
({editor} = yield getContainerForSelector("label", inspector));
|
||||
linkEl = editor.attrElements.get("for").querySelector(".link");
|
||||
|
||||
info("Follow link with middle-click, wait for new node to be selected.");
|
||||
yield followLinkWaitForNewNode(linkEl, false, inspector);
|
||||
|
||||
info("Follow link with ctrl/meta-click, wait for new node to be selected.");
|
||||
yield followLinkWaitForNewNode(linkEl, true, inspector);
|
||||
|
||||
info("Select a node with an invalid IDREF attribute");
|
||||
yield selectNode("output", inspector);
|
||||
|
||||
info("Find the link element from the markup-view that contains the ref");
|
||||
({editor} = yield getContainerForSelector("output", inspector));
|
||||
linkEl = editor.attrElements.get("for").querySelectorAll(".link")[2];
|
||||
|
||||
info("Try to follow link wiith middle-click, check no new node selected");
|
||||
yield followLinkNoNewNode(linkEl, false, inspector);
|
||||
|
||||
info("Try to follow link wiith meta/ctrl-click, check no new node selected");
|
||||
yield followLinkNoNewNode(linkEl, true, inspector);
|
||||
});
|
||||
|
||||
function waitForTabLoad(tab) {
|
||||
let def = promise.defer();
|
||||
tab.addEventListener("load", function onLoad() {
|
||||
// Skip load event for about:blank
|
||||
if (tab.linkedBrowser.currentURI.spec === "about:blank") {
|
||||
return;
|
||||
}
|
||||
tab.removeEventListener("load", onLoad);
|
||||
def.resolve();
|
||||
});
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
function performMouseDown(linkEl, metactrl) {
|
||||
let evt = linkEl.ownerDocument.createEvent("MouseEvents");
|
||||
|
||||
let button = -1;
|
||||
|
||||
if (metactrl) {
|
||||
info("Performing Meta/Ctrl+Left Click");
|
||||
button = 0;
|
||||
} else {
|
||||
info("Performing Middle Click");
|
||||
button = 1;
|
||||
}
|
||||
|
||||
evt.initMouseEvent("mousedown", true, true,
|
||||
linkEl.ownerDocument.defaultView, 1, 0, 0, 0, 0, metactrl,
|
||||
false, false, metactrl, button, null);
|
||||
|
||||
linkEl.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
function* followLinkWaitForTab(linkEl, isMetaClick, expectedTabURI) {
|
||||
let onTabOpened = once(gBrowser.tabContainer, "TabOpen");
|
||||
performMouseDown(linkEl, isMetaClick);
|
||||
let {target} = yield onTabOpened;
|
||||
yield waitForTabLoad(target);
|
||||
ok(true, "A new tab opened");
|
||||
is(target.linkedBrowser.currentURI.spec, expectedTabURI,
|
||||
"The URL for the new tab is correct");
|
||||
gBrowser.removeTab(target);
|
||||
}
|
||||
|
||||
function* followLinkWaitForNewNode(linkEl, isMetaClick, inspector) {
|
||||
let onSelection = inspector.selection.once("new-node-front");
|
||||
performMouseDown(linkEl, isMetaClick);
|
||||
yield onSelection;
|
||||
|
||||
ok(true, "A new node was selected");
|
||||
is(inspector.selection.nodeFront.id, "name", "The right node was selected");
|
||||
}
|
||||
|
||||
function* followLinkNoNewNode(linkEl, isMetaClick, inspector) {
|
||||
let onFailed = inspector.once("idref-attribute-link-failed");
|
||||
performMouseDown(linkEl, isMetaClick);
|
||||
yield onFailed;
|
||||
|
||||
ok(true, "The node selection failed");
|
||||
is(inspector.selection.nodeFront.tagName.toLowerCase(), "output",
|
||||
"The <output> node is still selected");
|
||||
}
|
@ -35,7 +35,6 @@ label,
|
||||
text-transform: uppercase;
|
||||
line-height: 200%;
|
||||
margin: 5px 5px 0 5px;
|
||||
font-size: 10%;
|
||||
font-weight: 700;
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -64,3 +64,12 @@
|
||||
-->
|
||||
<!ENTITY translation.options.attribution.beforeLogo "Translations by">
|
||||
<!ENTITY translation.options.attribution.afterLogo "">
|
||||
|
||||
<!-- LOCALIZATION NOTE (translation.options.attribution.poweredByYandex,
|
||||
translation.options.attribution.beforeLogo,
|
||||
- translation.options.attribution.afterLogo):
|
||||
- translation.options.attribution.poweredByYandex is displayed instead of
|
||||
- the other two strings when yandex translation engine is preferred by the
|
||||
- user.
|
||||
-->
|
||||
<!ENTITY translation.options.attribution.yandexTranslate "Powered by Yandex.Translate">
|
||||
|
@ -19,6 +19,8 @@
|
||||
%define conditionalForwardWithUrlbarWidth 30
|
||||
|
||||
:root {
|
||||
--backbutton-urlbar-overlap: 5px;
|
||||
|
||||
--toolbarbutton-hover-background: hsla(0,0%,100%,.3) linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.2));
|
||||
--toolbarbutton-hover-boxshadow: 0 1px 0 hsla(0,0%,100%,.3) inset, 0 0 0 1px hsla(0,0%,100%,.2) inset, 0 1px 0 hsla(0,0%,0%,.03);
|
||||
--toolbarbutton-hover-bordercolor: rgb(154,154,154);
|
||||
@ -846,7 +848,7 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
#urlbar,
|
||||
.searchbar-textbox {
|
||||
-moz-appearance: none;
|
||||
padding: 1px;
|
||||
padding: 0;
|
||||
border: 1px solid ThreeDShadow;
|
||||
border-radius: 2px;
|
||||
margin: 0 3px;
|
||||
@ -895,7 +897,7 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
|
||||
@conditionalForwardWithUrlbar@ {
|
||||
clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path");
|
||||
-moz-margin-start: -5px;
|
||||
margin-inline-start: calc(-1 * var(--backbutton-urlbar-overlap));
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:-moz-locale-dir(rtl),
|
||||
@ -973,14 +975,6 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
|
||||
/* identity box */
|
||||
|
||||
#identity-box {
|
||||
margin: -1px;
|
||||
-moz-margin-end: 4px;
|
||||
padding: 2px;
|
||||
-moz-padding-end: 1px;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
#identity-box:-moz-locale-dir(ltr) {
|
||||
border-top-left-radius: 1.5px;
|
||||
border-bottom-left-radius: 1.5px;
|
||||
@ -991,42 +985,6 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
border-bottom-right-radius: 1.5px;
|
||||
}
|
||||
|
||||
#notification-popup-box:not([hidden]) + #identity-box {
|
||||
-moz-padding-start: 10px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #urlbar > #identity-box {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar > #identity-box {
|
||||
transition: padding-left, padding-right;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box {
|
||||
/* forward button hiding is delayed when hovered */
|
||||
transition-delay: 100s;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
|
||||
/* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */
|
||||
padding-left: 5.01px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
|
||||
/* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */
|
||||
padding-right: 5.01px;
|
||||
}
|
||||
|
||||
#identity-box.verifiedIdentity:not(:-moz-lwtheme):not(:hover):not([open=true]) {
|
||||
background-color: var(--verified-identity-box-backgroundcolor);
|
||||
}
|
||||
@ -1036,20 +994,8 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
#identity-icon-labels {
|
||||
-moz-padding-start: 2px;
|
||||
-moz-padding-end: 5px;
|
||||
}
|
||||
|
||||
%include ../shared/identity-block/identity-block.inc.css
|
||||
|
||||
#page-proxy-favicon {
|
||||
margin-top: 1px;
|
||||
margin-bottom: 1px;
|
||||
-moz-margin-start: 3px;
|
||||
-moz-margin-end: 1px;
|
||||
}
|
||||
|
||||
%include ../shared/notification-icons.inc.css
|
||||
|
||||
.popup-notification-body[popupid="addon-progress"],
|
||||
@ -1065,8 +1011,6 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
/* Notification icon box */
|
||||
#notification-popup-box {
|
||||
border-radius: 2.5px 0 0 2.5px;
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.notification-anchor-icon:-moz-focusring {
|
||||
|
@ -7,11 +7,6 @@
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.searchbar-textbox {
|
||||
min-height: 22px;
|
||||
background-color: -moz-field;
|
||||
}
|
||||
|
||||
.autocomplete-textbox-container {
|
||||
-moz-box-align: stretch;
|
||||
}
|
||||
@ -81,6 +76,8 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
|
||||
.searchbar-search-button {
|
||||
list-style-image: url("chrome://browser/skin/search-indicator.png");
|
||||
-moz-image-region: rect(0, 20px, 20px, 0);
|
||||
margin-top: 1px;
|
||||
margin-bottom: 1px;
|
||||
-moz-margin-start: 2px;
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,10 @@
|
||||
|
||||
:root {
|
||||
--space-above-tabbar: 9px;
|
||||
|
||||
--tabs-toolbar-color: #333;
|
||||
|
||||
--backbutton-urlbar-overlap: 6px;
|
||||
|
||||
--toolbarbutton-hover-background: hsla(0,0%,100%,.1) linear-gradient(hsla(0,0%,100%,.3), hsla(0,0%,100%,.1)) padding-box;
|
||||
--toolbarbutton-hover-bordercolor: hsla(0,0%,0%,.2);
|
||||
--toolbarbutton-hover-boxshadow: 0 1px 0 hsla(0,0%,100%,.5),
|
||||
@ -1633,7 +1635,7 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
|
||||
@conditionalForwardWithUrlbar@ {
|
||||
clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path");
|
||||
-moz-margin-start: -6px;
|
||||
margin-inline-start: calc(-1 * var(--backbutton-urlbar-overlap));
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:-moz-locale-dir(rtl),
|
||||
@ -1646,24 +1648,19 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
-moz-box-direction: reverse;
|
||||
}
|
||||
|
||||
#identity-box {
|
||||
margin: 0;
|
||||
-moz-margin-end: 3px;
|
||||
padding: 1px 4px;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
#urlbar:not([focused="true"]) > #identity-box {
|
||||
margin: -1px 0;
|
||||
-moz-margin-end: 3px;
|
||||
padding: 2px 4px;
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
@media (-moz-mac-yosemite-theme) {
|
||||
#urlbar:not([focused="true"]):not(:-moz-window-inactive) > #identity-box {
|
||||
margin: -2px 0;
|
||||
-moz-margin-end: 3px;
|
||||
padding: 3px 4px;
|
||||
margin-top: -2px;
|
||||
margin-bottom: -2px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
#identity-box {
|
||||
--identity-box-selected-background-color: rgb(240,237,237);
|
||||
@ -1680,40 +1677,6 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
|
||||
#notification-popup-box:not([hidden]) + #identity-box {
|
||||
-moz-padding-start: 10px !important;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #urlbar > #identity-box {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar > #identity-box {
|
||||
transition: padding-left, padding-right;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box {
|
||||
/* forward button hiding is delayed when hovered */
|
||||
transition-delay: 100s;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
|
||||
padding-left: 10.01px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
|
||||
padding-right: 10.01px;
|
||||
}
|
||||
|
||||
#identity-box:-moz-focusring {
|
||||
box-shadow: 0 0 2px 1px -moz-mac-focusring inset,
|
||||
0 0 2px 2px -moz-mac-focusring;
|
||||
@ -1721,10 +1684,6 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
-moz-padding-end: 5px;
|
||||
}
|
||||
|
||||
#identity-icon-labels {
|
||||
-moz-margin-start: 4px;
|
||||
}
|
||||
|
||||
.urlbar-input-box {
|
||||
-moz-margin-start: 0;
|
||||
padding: 3px 0 2px;
|
||||
@ -1807,11 +1766,6 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
|
||||
%include ../shared/identity-block/identity-block.inc.css
|
||||
|
||||
#page-proxy-favicon {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#wrapper-urlbar-container[place="palette"] {
|
||||
max-width: 20em;
|
||||
}
|
||||
|
@ -140,9 +140,10 @@
|
||||
|
||||
.identity-popup-expander[panel-multiview-anchor] {
|
||||
transition: background-color 250ms ease-in;
|
||||
background-color: #0069d9;
|
||||
background-color: Highlight;
|
||||
background-image: url("chrome://browser/skin/customizableui/subView-arrow-back-inverted.png"),
|
||||
linear-gradient(rgba(255,255,255,0.3), transparent);
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
|
@ -48,6 +48,9 @@
|
||||
background-size: 1px;
|
||||
background-repeat: no-repeat;
|
||||
background-image: var(--identity-box-background-image);
|
||||
font-size: .9em;
|
||||
padding: 2px 5px;
|
||||
margin-inline-end: 4px;
|
||||
}
|
||||
|
||||
#identity-box:-moz-locale-dir(rtl) {
|
||||
@ -69,11 +72,52 @@
|
||||
background-image: var(--identity-box-chrome-background-image);
|
||||
}
|
||||
|
||||
#identity-icon-labels {
|
||||
padding-inline-start: 2px;
|
||||
}
|
||||
|
||||
#notification-popup-box:not([hidden]) + #identity-box {
|
||||
-moz-padding-start: 10px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #urlbar > #identity-box {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar > #identity-box {
|
||||
transition: padding-left, padding-right;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
|
||||
padding-left: calc(var(--backbutton-urlbar-overlap) + 4px);
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
|
||||
padding-right: calc(var(--backbutton-urlbar-overlap) + 4px);
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box {
|
||||
/* forward button hiding is delayed when hovered */
|
||||
transition-delay: 100s;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
|
||||
/* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */
|
||||
padding-left: calc(var(--backbutton-urlbar-overlap) + 4.01px);
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
|
||||
/* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */
|
||||
padding-right: calc(var(--backbutton-urlbar-overlap) + 4.01px);
|
||||
}
|
||||
|
||||
/* TRACKING PROTECTION ICON */
|
||||
|
||||
#tracking-protection-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-inline-end: 2px;
|
||||
list-style-image: url(chrome://browser/skin/tracking-protection-16.svg);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
:root {
|
||||
--space-above-tabbar: 15px;
|
||||
|
||||
--backbutton-urlbar-overlap: 5px;
|
||||
|
||||
--toolbarbutton-vertical-inner-padding: 2px;
|
||||
--toolbarbutton-vertical-outer-padding: 8px;
|
||||
|
||||
@ -1238,7 +1240,6 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
#urlbar:not(:-moz-lwtheme):hover,
|
||||
.searchbar-textbox:not(:-moz-lwtheme):hover {
|
||||
border-color: hsl(0,0%,80%);
|
||||
box-shadow: 0 0 0 1px hsl(0,0%,80%) inset;
|
||||
}
|
||||
|
||||
#urlbar:not(:-moz-lwtheme)[focused],
|
||||
@ -1304,13 +1305,16 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
|
||||
@conditionalForwardWithUrlbar@ {
|
||||
clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path");
|
||||
-moz-margin-start: -5px;
|
||||
margin-inline-start: calc(-1 * var(--backbutton-urlbar-overlap));
|
||||
}
|
||||
|
||||
@media (-moz-os-version: windows-win10) {
|
||||
@conditionalForwardWithUrlbar@ {
|
||||
clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path-win10");
|
||||
-moz-margin-start: -8px;
|
||||
}
|
||||
|
||||
:root {
|
||||
--backbutton-urlbar-overlap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1420,12 +1424,6 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
||||
|
||||
/* identity box */
|
||||
|
||||
#identity-box {
|
||||
padding: 2px;
|
||||
font-size: .9em;
|
||||
-moz-margin-end: 4px;
|
||||
}
|
||||
|
||||
#identity-box:-moz-locale-dir(ltr) {
|
||||
border-top-left-radius: 1.5px;
|
||||
border-bottom-left-radius: 1.5px;
|
||||
@ -1436,42 +1434,6 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
||||
border-bottom-right-radius: 1.5px;
|
||||
}
|
||||
|
||||
#notification-popup-box:not([hidden]) + #identity-box {
|
||||
-moz-padding-start: 10px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #urlbar > #identity-box {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar > #identity-box {
|
||||
transition: padding-left, padding-right;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box {
|
||||
/* forward button hiding is delayed when hovered */
|
||||
transition-delay: 100s;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
|
||||
/* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */
|
||||
padding-left: 5.01px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
|
||||
/* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */
|
||||
padding-right: 5.01px;
|
||||
}
|
||||
|
||||
#identity-box.verifiedIdentity:not(:-moz-lwtheme):not(:hover):not([open=true]) {
|
||||
background-color: var(--verified-identity-box-backgroundcolor);
|
||||
}
|
||||
@ -1481,11 +1443,6 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
#identity-icon-labels {
|
||||
-moz-padding-start: 2px;
|
||||
-moz-padding-end: 5px;
|
||||
}
|
||||
|
||||
/* Location bar dropmarker */
|
||||
|
||||
.urlbar-history-dropmarker {
|
||||
@ -1533,19 +1490,6 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
||||
|
||||
%include ../shared/identity-block/identity-block.inc.css
|
||||
|
||||
#page-proxy-favicon {
|
||||
margin-top: 1px;
|
||||
margin-bottom: 1px;
|
||||
-moz-margin-start: 3px;
|
||||
-moz-margin-end: 1px;
|
||||
}
|
||||
|
||||
@media (-moz-os-version: windows-win10) {
|
||||
#page-proxy-favicon {
|
||||
-moz-margin-start: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
/* autocomplete */
|
||||
|
||||
#treecolAutoCompleteImage {
|
||||
|
@ -106,13 +106,13 @@
|
||||
|
||||
/* Tab styling - make sure to use an inverted icon for the selected tab
|
||||
(brighttext only covers the unselected tabs) */
|
||||
.tab-close-button[visuallyselected=true]:not(:hover) {
|
||||
-moz-image-region: rect(0, 64px, 16px, 48px);
|
||||
.tab-close-button[visuallyselected=true] {
|
||||
list-style-image: url("chrome://global/skin/icons/close-inverted.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.tab-close-button[visuallyselected=true]:not(:hover) {
|
||||
-moz-image-region: rect(0, 128px, 32px, 96px);
|
||||
.tab-close-button[visuallyselected=true] {
|
||||
list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7212,8 +7212,12 @@ HTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
|
||||
filterBundle->GetStringFromName(MOZ_UTF16("videoFilter"),
|
||||
getter_Copies(extensionListStr));
|
||||
} else if (token.First() == '.') {
|
||||
if (token.FindChar(';') >= 0 || token.FindChar('*') >= 0) {
|
||||
// Ignore this filter as it contains reserved characters
|
||||
continue;
|
||||
}
|
||||
extensionListStr = NS_LITERAL_STRING("*") + token;
|
||||
filterName = extensionListStr + NS_LITERAL_STRING("; ");
|
||||
filterName = extensionListStr;
|
||||
atLeastOneFileExtensionFilter = true;
|
||||
} else {
|
||||
//... if no image/audio/video filter is found, check mime types filters
|
||||
@ -7291,7 +7295,14 @@ HTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
|
||||
if (i == j) {
|
||||
continue;
|
||||
}
|
||||
if (FindInReadable(filterToCheck.mFilter, filtersCopy[j].mFilter)) {
|
||||
// Check if this filter's extension list is a substring of the other one.
|
||||
// e.g. if filters are "*.jpeg" and "*.jpeg; *.jpg" the first one should
|
||||
// be removed.
|
||||
// Add an extra "; " to be sure the check will work and avoid cases like
|
||||
// "*.xls" being a subtring of "*.xslx" while those are two differents
|
||||
// filters and none should be removed.
|
||||
if (FindInReadable(filterToCheck.mFilter + NS_LITERAL_STRING(";"),
|
||||
filtersCopy[j].mFilter + NS_LITERAL_STRING(";"))) {
|
||||
// We already have a similar, less restrictive filter (i.e.
|
||||
// filterToCheck extensionList is just a subset of another filter
|
||||
// extension list): remove this one
|
||||
|
@ -31,7 +31,16 @@
|
||||
<input id='o' type="file" accept=".test">
|
||||
<input id='p' type="file" accept="image/gif,.csv">
|
||||
<input id='q' type="file" accept="image/gif,.gif">
|
||||
<input id='r' type="file" accept=".prefix,.prefixPlusSomething">
|
||||
<input id='s' type="file" accept=".xls,.xlsx">
|
||||
<input id='t' type="file" accept=".mp3,.wav,.flac">
|
||||
<input id='u' type="file" accept=".xls, .xlsx">
|
||||
<input id='v' type="file" accept=".xlsx, .xls">
|
||||
<input id='w' type="file" accept=".xlsx; .xls">
|
||||
<input id='x' type="file" accept=".xls, .xlsx">
|
||||
<input id='y' type="file" accept=".xlsx, .xls">
|
||||
<input id='z' type='file' accept="i/am,a,pathological,;,,,,test/case">
|
||||
<input id='A' type="file" accept=".xlsx, .xls*">
|
||||
<input id='mix-ref' type="file" accept="image/jpeg">
|
||||
<input id='mix' type="file" accept="image/jpeg,.jpg">
|
||||
<input id='hidden' hidden type='file'>
|
||||
@ -91,7 +100,16 @@ var testData = [["a", 1, MockFilePicker.filterImages, 1],
|
||||
["o", 1, "*.test", 1],
|
||||
["p", 3, "*.gif; *.csv", 1],
|
||||
["q", 1, "*.gif", 1],
|
||||
["r", 3, "*.prefix; *.prefixPlusSomething", 1],
|
||||
["s", 3, "*.xls; *.xlsx", 1],
|
||||
["t", 4, "*.mp3; *.wav; *.flac", 1],
|
||||
["u", 3, "*.xls; *.xlsx", 1],
|
||||
["v", 3, "*.xlsx; *.xls", 1],
|
||||
["w", 0, undefined, 0],
|
||||
["x", 3, "*.xls; *.xlsx", 1],
|
||||
["y", 3, "*.xlsx; *.xls", 1],
|
||||
["z", 0, undefined, 0],
|
||||
["A", 1, "*.xlsx", 1],
|
||||
// Note: mix and mix-ref tests extension lists are checked differently: see SimpleTest.executeSoon below
|
||||
["mix-ref", undefined, undefined, undefined],
|
||||
["mix", 1, undefined, 1],
|
||||
|
@ -86,7 +86,7 @@ AudioSink::HasUnplayedFrames()
|
||||
}
|
||||
|
||||
void
|
||||
AudioSink::PrepareToShutdown()
|
||||
AudioSink::Shutdown()
|
||||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
mStopAudioThread = true;
|
||||
@ -94,11 +94,8 @@ AudioSink::PrepareToShutdown()
|
||||
mAudioStream->Cancel();
|
||||
}
|
||||
GetReentrantMonitor().NotifyAll();
|
||||
}
|
||||
|
||||
void
|
||||
AudioSink::Shutdown()
|
||||
{
|
||||
ReentrantMonitorAutoExit exit(GetReentrantMonitor());
|
||||
mThread->Shutdown();
|
||||
mThread = nullptr;
|
||||
if (mAudioStream) {
|
||||
|
@ -37,12 +37,8 @@ public:
|
||||
// played.
|
||||
bool HasUnplayedFrames();
|
||||
|
||||
// Tell the AudioSink to stop processing and initiate shutdown. Must be
|
||||
// called with the decoder monitor held.
|
||||
void PrepareToShutdown();
|
||||
|
||||
// Shut down the AudioSink's resources. The decoder monitor must not be
|
||||
// held during this call, as it may block processing thread event queues.
|
||||
// Shut down the AudioSink's resources.
|
||||
// Must be called with the decoder monitor held.
|
||||
void Shutdown();
|
||||
|
||||
void SetVolume(double aVolume);
|
||||
|
@ -655,25 +655,6 @@ void MediaDecoder::QueueMetadata(int64_t aPublishTime,
|
||||
mDecoderStateMachine->QueueMetadata(aPublishTime, aInfo, aTags);
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoder::IsExpectingMoreData()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
||||
// If there's no resource, we're probably just getting set up.
|
||||
if (!mResource) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we've downloaded anything, we're not waiting for anything.
|
||||
if (mResource->IsDataCachedToEndOfResource(mDecoderPosition)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, we should be getting data unless the stream is suspended.
|
||||
return !mResource->IsSuspended();
|
||||
}
|
||||
|
||||
void MediaDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
nsAutoPtr<MetadataTags> aTags,
|
||||
MediaDecoderEventVisibility aEventVisibility)
|
||||
|
@ -622,13 +622,6 @@ public:
|
||||
// the track list. Call on the main thread only.
|
||||
virtual void RemoveMediaTracks() override;
|
||||
|
||||
// Returns true if the this decoder is expecting any more data to arrive
|
||||
// sometime in the not-too-distant future, either from the network or from
|
||||
// an appendBuffer call on a MediaSource element.
|
||||
//
|
||||
// Acquires the monitor. Call from any thread.
|
||||
virtual bool IsExpectingMoreData();
|
||||
|
||||
// Called when the video has completed playing.
|
||||
// Call on the main thread only.
|
||||
void PlaybackEnded();
|
||||
|
@ -1282,9 +1282,6 @@ void MediaDecoderStateMachine::Shutdown()
|
||||
// threads can start exiting cleanly during the Shutdown call.
|
||||
ScheduleStateMachine();
|
||||
SetState(DECODER_STATE_SHUTDOWN);
|
||||
if (mAudioSink) {
|
||||
mAudioSink->PrepareToShutdown();
|
||||
}
|
||||
|
||||
mQueuedSeek.RejectIfExists(__func__);
|
||||
mPendingSeek.RejectIfExists(__func__);
|
||||
@ -1473,11 +1470,7 @@ void MediaDecoderStateMachine::StopAudioThread()
|
||||
|
||||
if (mAudioSink) {
|
||||
DECODER_LOG("Shutdown audio thread");
|
||||
mAudioSink->PrepareToShutdown();
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
mAudioSink->Shutdown();
|
||||
}
|
||||
mAudioSink->Shutdown();
|
||||
mAudioSink = nullptr;
|
||||
}
|
||||
mAudioSinkPromise.DisconnectIfExists();
|
||||
@ -2374,7 +2367,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
||||
elapsed < TimeDuration::FromSeconds(mBufferingWait * mPlaybackRate) &&
|
||||
(mQuickBuffering ? HasLowDecodedData(mQuickBufferingLowDataThresholdUsecs)
|
||||
: HasLowUndecodedData(mBufferingWait * USECS_PER_S)) &&
|
||||
mDecoder->IsExpectingMoreData())
|
||||
mResource->IsExpectingMoreData())
|
||||
{
|
||||
DECODER_LOG("Buffering: wait %ds, timeout in %.3lfs %s",
|
||||
mBufferingWait, mBufferingWait - elapsed.ToSeconds(),
|
||||
@ -2734,7 +2727,7 @@ void MediaDecoderStateMachine::UpdateRenderedVideoFrames()
|
||||
// If we don't, switch to buffering mode.
|
||||
if (mState == DECODER_STATE_DECODING &&
|
||||
mPlayState == MediaDecoder::PLAY_STATE_PLAYING &&
|
||||
mDecoder->IsExpectingMoreData()) {
|
||||
mResource->IsExpectingMoreData()) {
|
||||
bool shouldBuffer;
|
||||
if (mReader->UseBufferingHeuristics()) {
|
||||
shouldBuffer = HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
|
||||
|
@ -402,6 +402,15 @@ public:
|
||||
// Returns true if all the data from aOffset to the end of the stream
|
||||
// is in cache. If the end of the stream is not known, we return false.
|
||||
virtual bool IsDataCachedToEndOfResource(int64_t aOffset) = 0;
|
||||
// Returns true if we are expecting any more data to arrive
|
||||
// sometime in the not-too-distant future, either from the network or from
|
||||
// an appendBuffer call on a MediaSource element.
|
||||
virtual bool IsExpectingMoreData()
|
||||
{
|
||||
// MediaDecoder::mDecoderPosition is roughly the same as Tell() which
|
||||
// returns a position updated by latest Read() or ReadAt().
|
||||
return !IsDataCachedToEndOfResource(Tell()) && !IsSuspended();
|
||||
}
|
||||
// Returns true if this stream is suspended by the cache because the
|
||||
// cache is full. If true then the decoder should try to start consuming
|
||||
// data, otherwise we may not be able to make progress.
|
||||
|
@ -49,7 +49,7 @@ static BOOL CALLBACK EnumDisplayMonitorsCallback(HMONITOR hMonitor, HDC hdc,
|
||||
&numVideoOutputs,
|
||||
&opmVideoOutputArray);
|
||||
if (S_OK != hr) {
|
||||
if (0x8007001f != hr && 0x80070032 != hr) {
|
||||
if (0x8007001f != hr && 0x80070032 != hr && 0xc02625e5 != hr) {
|
||||
char msg[100];
|
||||
sprintf(msg, "FAIL OPMGetVideoOutputsFromHMONITOR call failed: HRESULT=0x%08x", hr);
|
||||
failureMsgs->push_back(msg);
|
||||
|
@ -215,12 +215,6 @@ MediaSourceDecoder::Ended(bool aEnded)
|
||||
mon.NotifyAll();
|
||||
}
|
||||
|
||||
bool
|
||||
MediaSourceDecoder::IsExpectingMoreData()
|
||||
{
|
||||
return !mEnded;
|
||||
}
|
||||
|
||||
void
|
||||
MediaSourceDecoder::SetInitialDuration(int64_t aDuration)
|
||||
{
|
||||
|
@ -65,7 +65,6 @@ public:
|
||||
void OnTrackBufferConfigured(TrackBuffer* aTrackBuffer, const MediaInfo& aInfo);
|
||||
|
||||
void Ended(bool aEnded);
|
||||
bool IsExpectingMoreData() override;
|
||||
|
||||
// Return the duration of the video in seconds.
|
||||
virtual double GetDuration() override;
|
||||
|
@ -77,6 +77,12 @@ public:
|
||||
mEnded = aEnded;
|
||||
}
|
||||
|
||||
virtual bool IsExpectingMoreData() override
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
return !mEnded;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
|
||||
{
|
||||
|
@ -54,8 +54,12 @@ const kAllSettingsWritePermission = "settings" + kSettingsWriteSuffix;
|
||||
// will be allowed depends on the exact permissions the app has.
|
||||
const kSomeSettingsReadPermission = "settings-api" + kSettingsReadSuffix;
|
||||
const kSomeSettingsWritePermission = "settings-api" + kSettingsWriteSuffix;
|
||||
|
||||
// Time, in seconds, to consider the API is starting to jam
|
||||
const kSoftLockupDelta = 30;
|
||||
let kSoftLockupDelta = 30;
|
||||
try {
|
||||
kSoftLockupDelta = Services.prefs.getIntPref("dom.mozSettings.softLockupDelta");
|
||||
} catch (ex) { }
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "mrm",
|
||||
"@mozilla.org/memory-reporter-manager;1",
|
||||
|
@ -472,34 +472,18 @@ DOMStorageManager::GetLocalStorageForPrincipal(nsIPrincipal* aPrincipal,
|
||||
return CreateStorage(nullptr, aPrincipal, aDocumentURI, aPrivate, aRetval);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ClearCacheEnumeratorData
|
||||
void
|
||||
DOMStorageManager::ClearCaches(uint32_t aUnloadFlags,
|
||||
const nsACString& aKeyPrefix)
|
||||
{
|
||||
public:
|
||||
explicit ClearCacheEnumeratorData(uint32_t aFlags)
|
||||
: mUnloadFlags(aFlags)
|
||||
{}
|
||||
for (auto iter = mCaches.Iter(); !iter.Done(); iter.Next()) {
|
||||
DOMStorageCache* cache = iter.Get()->cache();
|
||||
nsCString& key = const_cast<nsCString&>(cache->Scope());
|
||||
|
||||
uint32_t mUnloadFlags;
|
||||
nsCString mKeyPrefix;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
PLDHashOperator
|
||||
DOMStorageManager::ClearCacheEnumerator(DOMStorageCacheHashKey* aEntry, void* aClosure)
|
||||
{
|
||||
DOMStorageCache* cache = aEntry->cache();
|
||||
nsCString& key = const_cast<nsCString&>(cache->Scope());
|
||||
|
||||
ClearCacheEnumeratorData* data = static_cast<ClearCacheEnumeratorData*>(aClosure);
|
||||
|
||||
if (data->mKeyPrefix.IsEmpty() || StringBeginsWith(key, data->mKeyPrefix)) {
|
||||
cache->UnloadItems(data->mUnloadFlags);
|
||||
if (aKeyPrefix.IsEmpty() || StringBeginsWith(key, aKeyPrefix)) {
|
||||
cache->UnloadItems(aUnloadFlags);
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -507,37 +491,27 @@ DOMStorageManager::Observe(const char* aTopic, const nsACString& aScopePrefix)
|
||||
{
|
||||
// Clear everything, caches + database
|
||||
if (!strcmp(aTopic, "cookie-cleared")) {
|
||||
ClearCacheEnumeratorData data(DOMStorageCache::kUnloadComplete);
|
||||
mCaches.EnumerateEntries(ClearCacheEnumerator, &data);
|
||||
|
||||
ClearCaches(DOMStorageCache::kUnloadComplete, EmptyCString());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Clear from caches everything that has been stored
|
||||
// while in session-only mode
|
||||
if (!strcmp(aTopic, "session-only-cleared")) {
|
||||
ClearCacheEnumeratorData data(DOMStorageCache::kUnloadSession);
|
||||
data.mKeyPrefix = aScopePrefix;
|
||||
mCaches.EnumerateEntries(ClearCacheEnumerator, &data);
|
||||
|
||||
ClearCaches(DOMStorageCache::kUnloadSession, aScopePrefix);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Clear everything (including so and pb data) from caches and database
|
||||
// for the gived domain and subdomains.
|
||||
if (!strcmp(aTopic, "domain-data-cleared")) {
|
||||
ClearCacheEnumeratorData data(DOMStorageCache::kUnloadComplete);
|
||||
data.mKeyPrefix = aScopePrefix;
|
||||
mCaches.EnumerateEntries(ClearCacheEnumerator, &data);
|
||||
|
||||
ClearCaches(DOMStorageCache::kUnloadComplete, aScopePrefix);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Clear all private-browsing caches
|
||||
if (!strcmp(aTopic, "private-browsing-data-cleared")) {
|
||||
ClearCacheEnumeratorData data(DOMStorageCache::kUnloadPrivate);
|
||||
mCaches.EnumerateEntries(ClearCacheEnumerator, &data);
|
||||
|
||||
ClearCaches(DOMStorageCache::kUnloadPrivate, EmptyCString());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -549,18 +523,13 @@ DOMStorageManager::Observe(const char* aTopic, const nsACString& aScopePrefix)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ClearCacheEnumeratorData data(DOMStorageCache::kUnloadComplete);
|
||||
data.mKeyPrefix = aScopePrefix;
|
||||
mCaches.EnumerateEntries(ClearCacheEnumerator, &data);
|
||||
|
||||
ClearCaches(DOMStorageCache::kUnloadComplete, aScopePrefix);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "profile-change")) {
|
||||
// For case caches are still referenced - clear them completely
|
||||
ClearCacheEnumeratorData data(DOMStorageCache::kUnloadComplete);
|
||||
mCaches.EnumerateEntries(ClearCacheEnumerator, &data);
|
||||
|
||||
ClearCaches(DOMStorageCache::kUnloadComplete, EmptyCString());
|
||||
mCaches.Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
@ -588,8 +557,7 @@ DOMStorageManager::Observe(const char* aTopic, const nsACString& aScopePrefix)
|
||||
}
|
||||
|
||||
// This immediately completely reloads all caches from the database.
|
||||
ClearCacheEnumeratorData data(DOMStorageCache::kTestReload);
|
||||
mCaches.EnumerateEntries(ClearCacheEnumerator, &data);
|
||||
ClearCaches(DOMStorageCache::kTestReload, EmptyCString());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -99,8 +99,7 @@ private:
|
||||
bool mLowDiskSpace;
|
||||
bool IsLowDiskSpace() const { return mLowDiskSpace; };
|
||||
|
||||
static PLDHashOperator ClearCacheEnumerator(DOMStorageCacheHashKey* aCache,
|
||||
void* aClosure);
|
||||
void ClearCaches(uint32_t aUnloadFlags, const nsACString& aKeyPrefix);
|
||||
|
||||
protected:
|
||||
// Keeps usage cache objects for eTLD+1 scopes we have touched.
|
||||
|
@ -296,6 +296,7 @@ TiledLayerBufferComposite::UseTiles(const SurfaceDescriptorTiles& aTiles,
|
||||
}
|
||||
|
||||
tile.mTextureHost = TextureHost::AsTextureHost(texturedDesc.textureParent());
|
||||
tile.mTextureHost->SetCompositor(aCompositor);
|
||||
|
||||
if (texturedDesc.textureOnWhite().type() == MaybeTexture::TPTextureParent) {
|
||||
tile.mTextureHostOnWhite =
|
||||
|
@ -8497,7 +8497,7 @@ CheckComparison(FunctionBuilder& f, ParseNode* comp, Type* type)
|
||||
}
|
||||
|
||||
I32 stmt;
|
||||
if (lhsType.isSigned()) {
|
||||
if (lhsType.isSigned() && rhsType.isSigned()) {
|
||||
switch (comp->getOp()) {
|
||||
case JSOP_EQ: stmt = I32::EqI32; break;
|
||||
case JSOP_NE: stmt = I32::NeI32; break;
|
||||
@ -8507,7 +8507,7 @@ CheckComparison(FunctionBuilder& f, ParseNode* comp, Type* type)
|
||||
case JSOP_GE: stmt = I32::SGeI32; break;
|
||||
default: MOZ_CRASH("unexpected comparison op");
|
||||
}
|
||||
} else if (lhsType.isUnsigned()) {
|
||||
} else if (lhsType.isUnsigned() && rhsType.isUnsigned()) {
|
||||
switch (comp->getOp()) {
|
||||
case JSOP_EQ: stmt = I32::EqI32; break;
|
||||
case JSOP_NE: stmt = I32::NeI32; break;
|
||||
|
@ -2651,6 +2651,32 @@ SetGCCallback(JSContext* cx, unsigned argc, Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SetARMHwCapFlags(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (args.length() != 1) {
|
||||
JS_ReportError(cx, "Wrong number of arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedString flagsListString(cx, JS::ToString(cx, args.get(0)));
|
||||
if (!flagsListString)
|
||||
return false;
|
||||
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
JSAutoByteString flagsList(cx, flagsListString);
|
||||
if (!flagsList)
|
||||
return false;
|
||||
|
||||
jit::ParseARMHwCapFlags(flagsList.ptr());
|
||||
#endif
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static const JSFunctionSpecWithHelp TestingFunctions[] = {
|
||||
JS_FN_HELP("gc", ::GC, 0, 0,
|
||||
"gc([obj] | 'compartment' [, 'shrinking'])",
|
||||
@ -3081,6 +3107,11 @@ gc::ZealModeHelpText),
|
||||
" 'minorGC' - run a nursery collection\n"
|
||||
" 'majorGC' - run a major collection, nesting up to a given 'depth'\n"),
|
||||
|
||||
JS_FN_HELP("setARMHwCapFlags", SetARMHwCapFlags, 1, 0,
|
||||
"setARMHwCapFlags(\"flag1,flag2 flag3\")",
|
||||
" On non-ARM, no-op. On ARM, set the hardware capabilities. The list of \n"
|
||||
" flags is available by calling this function with \"help\" as the flag's name"),
|
||||
|
||||
JS_FS_HELP_END
|
||||
};
|
||||
|
||||
|
@ -2,8 +2,9 @@
|
||||
if (!this.Atomics)
|
||||
quit();
|
||||
|
||||
function m(stdlib, ffi, heap)
|
||||
{
|
||||
load(libdir + "asm.js");
|
||||
|
||||
var code = `
|
||||
"use asm";
|
||||
|
||||
var HEAP32 = new stdlib.SharedInt32Array(heap);
|
||||
@ -16,35 +17,33 @@ function m(stdlib, ffi, heap)
|
||||
// kernel is derived from the large test case in that bug.
|
||||
|
||||
function add_sharedEv(i1) {
|
||||
i1 = i1 | 0;
|
||||
var i2 = 0;
|
||||
var xx = 0;
|
||||
i2 = i1 + 4 | 0;
|
||||
i1 = load(HEAP32, i2 >> 2) | 0;
|
||||
_emscripten_asm_const_int(7, i2 | 0, i1 | 0) | 0;
|
||||
add(HEAP32, i2 >> 2, 1) | 0;
|
||||
_emscripten_asm_const_int(8, i2 | 0, load(HEAP32, i2 >> 2) | 0, i1 + 1 | 0) | 0;
|
||||
return xx|0;
|
||||
i1 = i1 | 0;
|
||||
var i2 = 0;
|
||||
var xx = 0;
|
||||
i2 = i1 + 4 | 0;
|
||||
i1 = load(HEAP32, i2 >> 2) | 0;
|
||||
_emscripten_asm_const_int(7, i2 | 0, i1 | 0) | 0;
|
||||
add(HEAP32, i2 >> 2, 1) | 0;
|
||||
_emscripten_asm_const_int(8, i2 | 0, load(HEAP32, i2 >> 2) | 0, i1 + 1 | 0) | 0;
|
||||
return xx|0;
|
||||
}
|
||||
|
||||
return {add_sharedEv:add_sharedEv};
|
||||
}
|
||||
|
||||
if (isAsmJSCompilationAvailable())
|
||||
assertEq(isAsmJSModule(m), true);
|
||||
`;
|
||||
|
||||
var x;
|
||||
|
||||
var sab = new SharedArrayBuffer(65536);
|
||||
var ffi =
|
||||
{ _emscripten_asm_const_int:
|
||||
function (...rest) {
|
||||
//print("OUT: " + rest.join(" "));
|
||||
if (rest[0] == 8)
|
||||
x = rest[2];
|
||||
}
|
||||
function (...rest) {
|
||||
//print("OUT: " + rest.join(" "));
|
||||
if (rest[0] == 8)
|
||||
x = rest[2];
|
||||
}
|
||||
};
|
||||
var {add_sharedEv} = m(this, ffi, sab);
|
||||
var m = asmCompile('stdlib', 'ffi', 'heap', code);
|
||||
var {add_sharedEv} = asmLink(m, this, ffi, sab);
|
||||
add_sharedEv(13812);
|
||||
|
||||
assertEq(x, 1);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -262,6 +262,9 @@ assertAsmTypeFail(USE_ASM + "function f() { var i=42,j=1.1; return +(i?i:j) } re
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,j=1.1; return +(i?+(i|0):j) } return f"))(), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,j=1; return (i?i:j)|0 } return f"))(), 42);
|
||||
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (0 > (-(~~1) >>> 0)) | 0; } return f"))(), 0);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 0 < 4294967294 | 0; } return f"))(), 1);
|
||||
|
||||
var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i|0)>(j|0)?(i+10)|0:(j+100)|0)|0 } return f"));
|
||||
assertEq(f(2, 4), 104);
|
||||
assertEq(f(-2, -4), 8);
|
||||
|
@ -45,8 +45,10 @@ BytecodeAnalysis::init(TempAllocator& alloc, GSNCache& gsn)
|
||||
if (!infos_.growByUninitialized(script_->length()))
|
||||
return false;
|
||||
|
||||
// We need a scope chain if any of the bindings are aliased.
|
||||
usesScopeChain_ = script_->hasAnyAliasedBindings();
|
||||
// We need a scope chain if the function is heavyweight.
|
||||
usesScopeChain_ = (script_->functionDelazifying() &&
|
||||
script_->functionDelazifying()->isHeavyweight());
|
||||
MOZ_ASSERT_IF(script_->hasAnyAliasedBindings(), usesScopeChain_);
|
||||
|
||||
jsbytecode* end = script_->codeEnd();
|
||||
|
||||
|
@ -1008,13 +1008,10 @@ CodeGenerator::visitRegExp(LRegExp* lir)
|
||||
callVM(CloneRegExpObjectInfo, lir);
|
||||
}
|
||||
|
||||
// The maximum number of pairs we can handle when executing RegExps inline.
|
||||
static const size_t RegExpMaxPairCount = 6;
|
||||
|
||||
// Amount of space to reserve on the stack when executing RegExps inline.
|
||||
static const size_t RegExpReservedStack = sizeof(irregexp::InputOutputData)
|
||||
+ sizeof(MatchPairs)
|
||||
+ RegExpMaxPairCount * sizeof(MatchPair);
|
||||
+ RegExpObject::MaxPairCount * sizeof(MatchPair);
|
||||
|
||||
static size_t
|
||||
RegExpPairsVectorStartOffset(size_t inputOutputDataStartOffset)
|
||||
@ -1093,7 +1090,7 @@ PrepareAndExecuteRegExp(JSContext* cx, MacroAssembler& masm, Register regexp, Re
|
||||
if (mode == RegExpShared::Normal) {
|
||||
// Don't handle RegExps with excessive parens.
|
||||
masm.load32(Address(temp1, RegExpShared::offsetOfParenCount()), temp2);
|
||||
masm.branch32(Assembler::AboveOrEqual, temp2, Imm32(RegExpMaxPairCount), failure);
|
||||
masm.branch32(Assembler::AboveOrEqual, temp2, Imm32(RegExpObject::MaxPairCount), failure);
|
||||
|
||||
// Fill in the paren count in the MatchPairs on the stack.
|
||||
masm.add32(Imm32(1), temp2);
|
||||
@ -1342,7 +1339,7 @@ JitCompartment::generateRegExpExecStub(JSContext* cx)
|
||||
|
||||
// The template object should have enough space for the maximum number of
|
||||
// pairs this stub can handle.
|
||||
MOZ_ASSERT(ObjectElements::VALUES_PER_HEADER + RegExpMaxPairCount ==
|
||||
MOZ_ASSERT(ObjectElements::VALUES_PER_HEADER + RegExpObject::MaxPairCount ==
|
||||
gc::GetGCKindSlots(templateObject->asTenured().getAllocKind()));
|
||||
|
||||
MacroAssembler masm(cx);
|
||||
|
@ -50,7 +50,7 @@ ParseARMCpuFeatures(const char* features, bool override = false)
|
||||
uint32_t flags = 0;
|
||||
|
||||
for (;;) {
|
||||
char ch = *features;
|
||||
char ch = *features;
|
||||
if (!ch) {
|
||||
// End of string.
|
||||
break;
|
||||
|
@ -825,7 +825,8 @@ RegExpCompartment::createMatchResultTemplateObject(JSContext* cx)
|
||||
MOZ_ASSERT(!matchResultTemplateObject_);
|
||||
|
||||
/* Create template array object */
|
||||
RootedArrayObject templateObject(cx, NewDenseUnallocatedArray(cx, 0, nullptr, TenuredObject));
|
||||
RootedArrayObject templateObject(cx, NewDenseUnallocatedArray(cx, RegExpObject::MaxPairCount,
|
||||
nullptr, TenuredObject));
|
||||
if (!templateObject)
|
||||
return matchResultTemplateObject_; // = nullptr
|
||||
|
||||
|
@ -360,6 +360,10 @@ class RegExpObject : public NativeObject
|
||||
|
||||
static const Class class_;
|
||||
|
||||
// The maximum number of pairs a MatchResult can have, without having to
|
||||
// allocate a bigger MatchResult.
|
||||
static const size_t MaxPairCount = 14;
|
||||
|
||||
/*
|
||||
* Note: The regexp statics flags are OR'd into the provided flags,
|
||||
* so this function is really meant for object creation during code
|
||||
|
@ -181,7 +181,7 @@ public class RestrictedProfiles {
|
||||
return isUserRestricted(GeckoAppShell.getContext());
|
||||
}
|
||||
|
||||
private static boolean isUserRestricted(final Context context) {
|
||||
public static boolean isUserRestricted(final Context context) {
|
||||
// Guest mode is supported in all Android versions.
|
||||
if (getInGuest()) {
|
||||
return true;
|
||||
|
@ -32,7 +32,7 @@ import java.util.zip.ZipFile;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
import org.apache.http.protocol.HTTP;
|
||||
import ch.boye.httpclientandroidlib.protocol.HTTP;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
@ -8,13 +8,13 @@ package org.mozilla.gecko.favicons;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.http.AndroidHttpClient;
|
||||
import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import ch.boye.httpclientandroidlib.Header;
|
||||
import ch.boye.httpclientandroidlib.HttpEntity;
|
||||
import ch.boye.httpclientandroidlib.HttpResponse;
|
||||
import ch.boye.httpclientandroidlib.client.methods.HttpGet;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
@ -72,7 +72,7 @@ public class LoadFaviconTask {
|
||||
private LinkedList<LoadFaviconTask> chainees;
|
||||
private boolean isChaining;
|
||||
|
||||
static AndroidHttpClient httpClient = AndroidHttpClient.newInstance(GeckoAppShell.getGeckoInterface().getDefaultUAString());
|
||||
static DefaultHttpClient httpClient = new DefaultHttpClient();
|
||||
|
||||
public LoadFaviconTask(Context context, String pageURL, String faviconURL, int flags, OnFaviconLoadedListener listener) {
|
||||
this(context, pageURL, faviconURL, flags, listener, -1, false);
|
||||
@ -128,6 +128,7 @@ public class LoadFaviconTask {
|
||||
}
|
||||
|
||||
HttpGet request = new HttpGet(faviconURI);
|
||||
request.setHeader("User-Agent", GeckoAppShell.getGeckoInterface().getDefaultUAString());
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
if (response == null) {
|
||||
return null;
|
||||
|
@ -697,7 +697,7 @@ OnSharedPreferenceChangeListener
|
||||
}
|
||||
}
|
||||
if (PREFS_DEVTOOLS.equals(key) &&
|
||||
RestrictedProfiles.isUserRestricted()) {
|
||||
RestrictedProfiles.isUserRestricted(this)) {
|
||||
preferences.removePreference(pref);
|
||||
i--;
|
||||
continue;
|
||||
|
@ -32,6 +32,9 @@ namespace net {
|
||||
// Initial elements buffer size.
|
||||
#define kInitialBufSize 64
|
||||
|
||||
// Max size of elements in bytes.
|
||||
#define kMaxElementsSize 64*1024
|
||||
|
||||
#define kCacheEntryVersion 1
|
||||
|
||||
#define NOW_SECONDS() (uint32_t(PR_Now() / PR_USEC_PER_SEC))
|
||||
@ -236,6 +239,17 @@ CacheFileMetadata::ReadMetadata(CacheFileMetadataListener *aListener)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
CacheFileMetadata::CalcMetadataSize(uint32_t aElementsSize, uint32_t aHashCount)
|
||||
{
|
||||
return sizeof(uint32_t) + // hash of the metadata
|
||||
aHashCount * sizeof(CacheHash::Hash16_t) + // array of chunk hashes
|
||||
sizeof(CacheFileMetadataHeader) + // metadata header
|
||||
mKey.Length() + 1 + // key with trailing null
|
||||
aElementsSize + // elements
|
||||
sizeof(uint32_t); // offset
|
||||
}
|
||||
|
||||
nsresult
|
||||
CacheFileMetadata::WriteMetadata(uint32_t aOffset,
|
||||
CacheFileMetadataListener *aListener)
|
||||
@ -250,10 +264,11 @@ CacheFileMetadata::WriteMetadata(uint32_t aOffset,
|
||||
|
||||
mIsDirty = false;
|
||||
|
||||
mWriteBuf = static_cast<char *>(moz_xmalloc(sizeof(uint32_t) +
|
||||
mHashCount * sizeof(CacheHash::Hash16_t) +
|
||||
sizeof(CacheFileMetadataHeader) + mKey.Length() + 1 +
|
||||
mElementsSize + sizeof(uint32_t)));
|
||||
mWriteBuf = static_cast<char *>(malloc(CalcMetadataSize(mElementsSize,
|
||||
mHashCount)));
|
||||
if (!mWriteBuf) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
char *p = mWriteBuf + sizeof(uint32_t);
|
||||
memcpy(p, mHashArray, mHashCount * sizeof(CacheHash::Hash16_t));
|
||||
@ -406,6 +421,8 @@ CacheFileMetadata::SetElement(const char *aKey, const char *aValue)
|
||||
|
||||
MarkDirty();
|
||||
|
||||
nsresult rv;
|
||||
|
||||
const uint32_t keySize = strlen(aKey) + 1;
|
||||
char *pos = const_cast<char *>(GetElement(aKey));
|
||||
|
||||
@ -431,7 +448,10 @@ CacheFileMetadata::SetElement(const char *aKey, const char *aValue)
|
||||
|
||||
// Update the value in place
|
||||
newSize -= oldValueSize;
|
||||
EnsureBuffer(newSize);
|
||||
rv = EnsureBuffer(newSize);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Move the remainder to the right place
|
||||
pos = mBuf + offset;
|
||||
@ -439,7 +459,10 @@ CacheFileMetadata::SetElement(const char *aKey, const char *aValue)
|
||||
} else {
|
||||
// allocate new meta data element
|
||||
newSize += keySize;
|
||||
EnsureBuffer(newSize);
|
||||
rv = EnsureBuffer(newSize);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Add after last element
|
||||
pos = mBuf + mElementsSize;
|
||||
@ -665,7 +688,7 @@ CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf,
|
||||
|
||||
if (realOffset >= size) {
|
||||
LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, creating "
|
||||
"empty metadata. [this=%p, realOffset=%d, size=%lld]", this,
|
||||
"empty metadata. [this=%p, realOffset=%u, size=%lld]", this,
|
||||
realOffset, size));
|
||||
|
||||
InitEmptyMetadata();
|
||||
@ -675,6 +698,21 @@ CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t maxHashCount = size / kChunkSize;
|
||||
uint32_t maxMetadataSize = CalcMetadataSize(kMaxElementsSize, maxHashCount);
|
||||
if (size - realOffset > maxMetadataSize) {
|
||||
LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, metadata would "
|
||||
"be too big, creating empty metadata. [this=%p, realOffset=%u, "
|
||||
"maxMetadataSize=%u, size=%lld]", this, realOffset, maxMetadataSize,
|
||||
size));
|
||||
|
||||
InitEmptyMetadata();
|
||||
|
||||
mListener.swap(listener);
|
||||
listener->OnMetadataRead(NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t usedOffset = size - mBufSize;
|
||||
|
||||
if (realOffset < usedOffset) {
|
||||
@ -932,9 +970,13 @@ CacheFileMetadata::CheckElements(const char *aBuf, uint32_t aSize)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsresult
|
||||
CacheFileMetadata::EnsureBuffer(uint32_t aSize)
|
||||
{
|
||||
if (aSize > kMaxElementsSize) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mBufSize < aSize) {
|
||||
if (mAllocExactSize) {
|
||||
// If this is not the only allocation, use power of two for following
|
||||
@ -955,11 +997,17 @@ CacheFileMetadata::EnsureBuffer(uint32_t aSize)
|
||||
aSize = kInitialBufSize;
|
||||
}
|
||||
|
||||
char *newBuf = static_cast<char *>(realloc(mBuf, aSize));
|
||||
if (!newBuf) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mBufSize = aSize;
|
||||
mBuf = static_cast<char *>(moz_xrealloc(mBuf, mBufSize));
|
||||
mBuf = newBuf;
|
||||
|
||||
DoMemoryReport(MemoryUsage());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -121,6 +121,7 @@ public:
|
||||
nsresult GetKey(nsACString &_retval);
|
||||
|
||||
nsresult ReadMetadata(CacheFileMetadataListener *aListener);
|
||||
uint32_t CalcMetadataSize(uint32_t aElementsSize, uint32_t aHashCount);
|
||||
nsresult WriteMetadata(uint32_t aOffset,
|
||||
CacheFileMetadataListener *aListener);
|
||||
nsresult SyncReadMetadata(nsIFile *aFile);
|
||||
@ -171,7 +172,7 @@ private:
|
||||
void InitEmptyMetadata();
|
||||
nsresult ParseMetadata(uint32_t aMetaOffset, uint32_t aBufOffset, bool aHaveKey);
|
||||
nsresult CheckElements(const char *aBuf, uint32_t aSize);
|
||||
void EnsureBuffer(uint32_t aSize);
|
||||
nsresult EnsureBuffer(uint32_t aSize);
|
||||
nsresult ParseKey(const nsACString &aKey);
|
||||
|
||||
nsRefPtr<CacheFileHandle> mHandle;
|
||||
|
@ -103,6 +103,18 @@ CacheFileOutputStream::Write(const char * aBuf, uint32_t aCount,
|
||||
return NS_ERROR_FILE_TOO_BIG;
|
||||
}
|
||||
|
||||
// We use 64-bit offset when accessing the file, unfortunatelly we use 32-bit
|
||||
// metadata offset, so we cannot handle data bigger than 4GB.
|
||||
if (mPos + aCount > PR_UINT32_MAX) {
|
||||
LOG(("CacheFileOutputStream::Write() - Entry's size exceeds 4GB while it "
|
||||
"isn't too big according to CacheObserver::EntryIsTooBig(). Failing "
|
||||
"and dooming the entry. [this=%p]", this));
|
||||
|
||||
mFile->DoomLocked(nullptr);
|
||||
CloseWithStatusLocked(NS_ERROR_FILE_TOO_BIG);
|
||||
return NS_ERROR_FILE_TOO_BIG;
|
||||
}
|
||||
|
||||
*_retval = aCount;
|
||||
|
||||
while (aCount) {
|
||||
|
@ -65,11 +65,11 @@ bool CacheObserver::sSmartCacheSizeEnabled = kDefaultSmartCacheSizeEnabled;
|
||||
static uint32_t const kDefaultPreloadChunkCount = 4;
|
||||
uint32_t CacheObserver::sPreloadChunkCount = kDefaultPreloadChunkCount;
|
||||
|
||||
static uint32_t const kDefaultMaxMemoryEntrySize = 4 * 1024; // 4 MB
|
||||
uint32_t CacheObserver::sMaxMemoryEntrySize = kDefaultMaxMemoryEntrySize;
|
||||
static int32_t const kDefaultMaxMemoryEntrySize = 4 * 1024; // 4 MB
|
||||
int32_t CacheObserver::sMaxMemoryEntrySize = kDefaultMaxMemoryEntrySize;
|
||||
|
||||
static uint32_t const kDefaultMaxDiskEntrySize = 50 * 1024; // 50 MB
|
||||
uint32_t CacheObserver::sMaxDiskEntrySize = kDefaultMaxDiskEntrySize;
|
||||
static int32_t const kDefaultMaxDiskEntrySize = 50 * 1024; // 50 MB
|
||||
int32_t CacheObserver::sMaxDiskEntrySize = kDefaultMaxDiskEntrySize;
|
||||
|
||||
static uint32_t const kDefaultMaxDiskChunksMemoryUsage = 10 * 1024; // 10MB
|
||||
uint32_t CacheObserver::sMaxDiskChunksMemoryUsage = kDefaultMaxDiskChunksMemoryUsage;
|
||||
@ -170,9 +170,9 @@ CacheObserver::AttachToPreferences()
|
||||
mozilla::Preferences::AddUintVarCache(
|
||||
&sPreloadChunkCount, "browser.cache.disk.preload_chunk_count", kDefaultPreloadChunkCount);
|
||||
|
||||
mozilla::Preferences::AddUintVarCache(
|
||||
mozilla::Preferences::AddIntVarCache(
|
||||
&sMaxDiskEntrySize, "browser.cache.disk.max_entry_size", kDefaultMaxDiskEntrySize);
|
||||
mozilla::Preferences::AddUintVarCache(
|
||||
mozilla::Preferences::AddIntVarCache(
|
||||
&sMaxMemoryEntrySize, "browser.cache.memory.max_entry_size", kDefaultMaxMemoryEntrySize);
|
||||
|
||||
mozilla::Preferences::AddUintVarCache(
|
||||
@ -472,9 +472,12 @@ CacheStorageEvictHelper::ClearStorage(bool const aPrivate,
|
||||
bool const CacheObserver::EntryIsTooBig(int64_t aSize, bool aUsingDisk)
|
||||
{
|
||||
// If custom limit is set, check it.
|
||||
int64_t preferredLimit = aUsingDisk
|
||||
? static_cast<int64_t>(sMaxDiskEntrySize) << 10
|
||||
: static_cast<int64_t>(sMaxMemoryEntrySize) << 10;
|
||||
int64_t preferredLimit = aUsingDisk ? sMaxDiskEntrySize : sMaxMemoryEntrySize;
|
||||
|
||||
// do not convert to bytes when the limit is -1, which means no limit
|
||||
if (preferredLimit > 0) {
|
||||
preferredLimit <<= 10;
|
||||
}
|
||||
|
||||
if (preferredLimit != -1 && aSize > preferredLimit)
|
||||
return true;
|
||||
|
@ -90,8 +90,8 @@ private:
|
||||
static uint32_t sDiskFreeSpaceHardLimit;
|
||||
static bool sSmartCacheSizeEnabled;
|
||||
static uint32_t sPreloadChunkCount;
|
||||
static uint32_t sMaxMemoryEntrySize;
|
||||
static uint32_t sMaxDiskEntrySize;
|
||||
static int32_t sMaxMemoryEntrySize;
|
||||
static int32_t sMaxDiskEntrySize;
|
||||
static uint32_t sMaxDiskChunksMemoryUsage;
|
||||
static uint32_t sMaxDiskPriorityChunksMemoryUsage;
|
||||
static uint32_t sCompressionLevel;
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#include "nsCookieService.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIPrivateBrowsingChannel.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "SerializedLoadContext.h"
|
||||
@ -17,6 +19,33 @@ using namespace mozilla::ipc;
|
||||
using mozilla::dom::PContentParent;
|
||||
using mozilla::net::NeckoParent;
|
||||
|
||||
namespace {
|
||||
|
||||
bool
|
||||
CreateDummyChannel(nsIURI* aHostURI, bool aIsPrivate, nsIChannel **aChannel)
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
nsresult rv = ssm->GetNoAppCodebasePrincipal(aHostURI, getter_AddRefs(principal));
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> dummyChannel;
|
||||
NS_NewChannel(getter_AddRefs(dummyChannel), aHostURI, principal,
|
||||
nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_INVALID);
|
||||
nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(dummyChannel);
|
||||
if (!pbChannel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pbChannel->SetPrivate(aIsPrivate);
|
||||
dummyChannel.forget(aChannel);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
@ -126,11 +155,22 @@ CookieServiceParent::RecvSetCookieString(const URIParams& aHost,
|
||||
return false;
|
||||
}
|
||||
|
||||
// This is a gross hack. We've already computed everything we need to know
|
||||
// for whether to set this cookie or not, but we need to communicate all of
|
||||
// this information through to nsICookiePermission, which indirectly
|
||||
// computes the information from the channel. We only care about the
|
||||
// aIsPrivate argument as nsCookieService::SetCookieStringInternal deals
|
||||
// with aIsForeign before we have to worry about nsCookiePermission trying
|
||||
// to use the channel to inspect it.
|
||||
nsCOMPtr<nsIChannel> dummyChannel;
|
||||
if (!CreateDummyChannel(hostURI, isPrivate, getter_AddRefs(dummyChannel))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsDependentCString cookieString(aCookieString, 0);
|
||||
//TODO: bug 812475, pass a real channel object
|
||||
mCookieService->SetCookieStringInternal(hostURI, aIsForeign, cookieString,
|
||||
aServerTime, aFromHttp, appId,
|
||||
isInBrowserElement, isPrivate, nullptr);
|
||||
isInBrowserElement, isPrivate, dummyChannel);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"access.boekhuis.nl", // bug 1151580
|
||||
"account.61.com.tw",
|
||||
"acs.sia.eu", // RC4
|
||||
"actiononline.stpete.org",
|
||||
"adman.you.gr",
|
||||
"adminweb.uthscsa.edu",
|
||||
"airportwifi.com", // bug 1116891
|
||||
@ -47,10 +46,10 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"ap.meitetsuunyu.co.jp",
|
||||
"apply.hkbn.net", // bug 1138451
|
||||
"apps.amerch.com",
|
||||
"apps.fpcu.org",
|
||||
"apps.sasken.com",
|
||||
"apps.state.or.us", // bug 1130472
|
||||
"appsrv.restat.com",
|
||||
"arcgames.com", // bug 1182932
|
||||
"ascii.jp",
|
||||
"asko.fi", // bug 1158584
|
||||
"b2b.feib.com.tw",
|
||||
@ -70,11 +69,11 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"buttons.verticalresponse.com",
|
||||
"c2g.jupiter.fl.us",
|
||||
"canadaca.geotrust.com", // bug 1137677
|
||||
"car2go.com", // bug 1185080
|
||||
"cbsfnotes1.blood.org.tw",
|
||||
"central.acadiau.ca", // bug 1152377
|
||||
"cherry.de", // bug 1141521
|
||||
"civilization.com", // bug 1156004
|
||||
"click2gov.sanangelotexas.us",
|
||||
"clientes.chilectra.cl",
|
||||
"club.guosen.com.cn",
|
||||
"coagov.aurora-il.org",
|
||||
@ -90,7 +89,6 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"cwu.edu",
|
||||
"dbank.hxb.com.cn",
|
||||
"dealer.autobytel.com",
|
||||
"dealer.autoc-one.jp",
|
||||
"dheb.delavska-hranilnica.si",
|
||||
"digibet.com",
|
||||
"digitalsecurity.intel.com", // bug 1148744
|
||||
@ -107,18 +105,14 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"ebpp.airtel.lk",
|
||||
"ebspay.boc.cn", // bug 1155567
|
||||
"ec-line.cn",
|
||||
"ecams.geico.com", // bug 1138613
|
||||
"echo.com",
|
||||
"echotrak.com",
|
||||
"ecom.morethangourmet.com",
|
||||
"ecourses.uthscsa.edu",
|
||||
"egov.leaguecity.com",
|
||||
"egov.town-menasha.com", // bug 1157536
|
||||
"emaildvla.direct.gov.uk", // bug 1116891
|
||||
"embroiderydesignsplus.com",
|
||||
"epicreg.com",
|
||||
"eremit.sbising.com",
|
||||
"escrowrefills.com",
|
||||
"eservices.palomar.edu",
|
||||
"essentialsupplies.com",
|
||||
"event.kasite.net",
|
||||
@ -135,10 +129,8 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"fubar.com",
|
||||
"gateway.halton.gov.uk",
|
||||
"gbe-bund.de",
|
||||
"geico.com", // bug 1138613
|
||||
"gestionesytramites.madrid.org",
|
||||
"giftcertificates.com",
|
||||
"hbk.bb.com.br", // bug 1135966
|
||||
"hercle.com",
|
||||
"hpshop.gr",
|
||||
"ibusiness.shacombank.com.hk", // bug 1141989
|
||||
@ -153,26 +145,20 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"jbclick.jaxbchfl.net", // bug 1158465
|
||||
"jifenpay.com",
|
||||
"jst.doded.mil", // bug 1152627
|
||||
"juror.fairfaxcounty.gov",
|
||||
"keirin.jp",
|
||||
"kjp.keinet.ne.jp",
|
||||
"kjp.oo.kawai-juku.ac.jp",
|
||||
"learn.ou.edu",
|
||||
"learn.swosu.edu",
|
||||
"lewisham.gov.uk",
|
||||
"lm-order.de",
|
||||
"login.chicagopolice.org",
|
||||
"login.ermis.gov.gr",
|
||||
"m.e-hon.ne.jp",
|
||||
"macif.fr", // bug 1167893
|
||||
"m.safari.cwu.edu", // bug 1143035
|
||||
"mail.izhnet.ru",
|
||||
"map.infonavit.org.mx",
|
||||
"marketday.com", // bug 1092998
|
||||
"matkahuolto.fi", // bug 1174957
|
||||
"mchrono.com",
|
||||
"mecsumai.com",
|
||||
"member.edenredticket.com",
|
||||
"mercernet.fr", // bug 1147649
|
||||
"merchant.edenredticket.com",
|
||||
"meta-ehealth.com",
|
||||
"mobile.aa.com", // bug 1141604
|
||||
@ -193,7 +179,6 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"myaccount3.westnet.com.au", // bug 1157139
|
||||
"mybank.nbcb.com.cn",
|
||||
"myhancock.hancockcollege.edu",
|
||||
"myntc.ntc.edu",
|
||||
"myuws.uws.edu.au",
|
||||
"mywebreservations.com",
|
||||
"na.aiononline.com", // bug 1139782
|
||||
@ -208,13 +193,11 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"online.newindia.co.in",
|
||||
"online.sainsburysbank.co.uk",
|
||||
"openwebosproject.org", // bug 1151990
|
||||
"opi.emersonclimate.com",
|
||||
"opus.pinellascounty.org",
|
||||
"owa.byui.edu",
|
||||
"ozone.ou.edu",
|
||||
"parents.ou.edu",
|
||||
"partnerweb.vmware.com", // bug 1142187
|
||||
"paslists.com", // for port 9211, bug 1155712
|
||||
"payment.condor.com", // bug 1152347
|
||||
"payment.safepass.cn",
|
||||
"payments.virginmedia.com", // bug 1129887
|
||||
@ -227,6 +210,7 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"publicjobs.ie",
|
||||
"publicrecords.com",
|
||||
"racenet.codemasters.com", // bug 1163716
|
||||
"rapidscansecure.com", // bug 1177212
|
||||
"recoup.com",
|
||||
"registration.o2.co.uk",
|
||||
"regonline.com", // bug 1139783
|
||||
@ -236,40 +220,27 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"reputation.com",
|
||||
"research-report.uws.edu.au",
|
||||
"reservations.usairways.com", // bug 1165400
|
||||
"rezstream.net",
|
||||
"rietumu.lv",
|
||||
"rotr.com",
|
||||
"roxyaffiliates.com",
|
||||
"sales.newchinalife.com",
|
||||
"sbank.hxb.com.cn",
|
||||
"sboseweb.mcpsweb.org",
|
||||
"school.keystoneschoolonline.com",
|
||||
"secure-checkout.t-mobile.com", // bug 1133648
|
||||
"secure.bg-mania.jp",
|
||||
"secure.crbonline.gov.uk", // bug 1166644
|
||||
"secure.fortisbc.com",
|
||||
"secure.ncsoft.com", // bug 1139782
|
||||
"secure.smartcart.com",
|
||||
"secure2.i-doxs.net", // bug 1140876
|
||||
"secure3.i-doxs.net", // bug 1140876
|
||||
"secure4.i-doxs.net", // bug 1140876
|
||||
"secure6.i-doxs.net", // bug 1140876
|
||||
"secure7.i-doxs.net", // bug 1140876
|
||||
"secure8.i-doxs.net", // bug 1140876
|
||||
"secureonline.dwp.gov.uk",
|
||||
"sems.hrd.ccsd.net",
|
||||
"service.autoc-one.jp",
|
||||
"services.apvma.gov.au",
|
||||
"services.geotrust.com", // bug 1137677
|
||||
"servizionline.infogroup.it",
|
||||
"shop.autoc-one.jp",
|
||||
"shop.kagome.co.jp",
|
||||
"shop.nanairo.coop", // bug 1128318
|
||||
"shop.wildstar-online.com", // bug 1139782
|
||||
"sisweb.ucd.ie",
|
||||
"slovanet.sk",
|
||||
"smartcart.com",
|
||||
"smarticon.geotrust.com", // bug 1137677
|
||||
"socialclub.rockstargames.com", // bug 1138673
|
||||
"soeasy.sodexo.be", // bug 1117157
|
||||
"ss2.sfcollege.edu",
|
||||
@ -280,16 +251,15 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"stenhouse.com",
|
||||
"store.moxa.com",
|
||||
"svrch13.sugarlandtx.gov",
|
||||
"swdownloads.blackberry.com", // bug 1182997
|
||||
"syzygy.co.uk",
|
||||
"tarjetacencosud.cl",
|
||||
"tele2.hr",
|
||||
"tienda.boe.es",
|
||||
"tiendas.mediamarkt.es",
|
||||
"trueblue.jetblue.com",
|
||||
"uralsg.megafon.ru", // bug 1153168
|
||||
"usacycling.org", // bug 1163791
|
||||
"userdoor.com",
|
||||
"uslugi.beeline.am",
|
||||
"utradehub.or.kr",
|
||||
"vod.skyperfectv.co.jp",
|
||||
"watch.sportsnet.ca", // bug 1144769
|
||||
@ -340,6 +310,7 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"www.ancelutil.com.uy",
|
||||
"www.animate-onlineshop.jp", // bug 1126652
|
||||
"www.apeasternpower.com",
|
||||
"www.arcgames.com", // bug 1182932
|
||||
"www.asko.fi", // bug 1158584
|
||||
"www.auroragov.org",
|
||||
"www.bancocredichile.cl",
|
||||
@ -362,10 +333,10 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"www.bredbandsbolaget.se", // bug 1158755
|
||||
"www.businessdirect.bt.com",
|
||||
"www.cafedumonde.jp",
|
||||
"www.car2go.com", // bug 1185080
|
||||
"www.careers.asio.gov.au",
|
||||
"www.cherry.de", // bug 1141521
|
||||
"www.chinapay.com", // bug 1137983
|
||||
"www.cihi.ca",
|
||||
"www.cipd.co.uk",
|
||||
"www.civilization.com", // bug 1156004
|
||||
"www.club-animate.jp",
|
||||
@ -389,14 +360,12 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"www.ec-line.cn",
|
||||
"www.echo.com",
|
||||
"www.echotrak.com",
|
||||
"www.embroiderydesignsplus.com",
|
||||
"www.epicreg.com",
|
||||
"www.ermis.gov.gr",
|
||||
"www.esadealumni.net",
|
||||
"www.esavingsaccount.co.uk",
|
||||
"www.escrowrefills.com",
|
||||
"www.essentialsupplies.com",
|
||||
"www.euronext.com", // bug 1136091
|
||||
"www.everyd.com",
|
||||
"www.ezpay.com.tw",
|
||||
"www.fhsaa.org",
|
||||
@ -405,17 +374,13 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"www.fontainebleau.com",
|
||||
"www.foundersc.com",
|
||||
"www.fubar.com",
|
||||
"www.fundsupermart.co.in",
|
||||
"www.gamers-onlineshop.jp", // bug 1126654
|
||||
"www.gbe-bund.de",
|
||||
"www.giftcertificates.com",
|
||||
"www.golfersland.net",
|
||||
"www.gtja.com",
|
||||
"www.hankyu-club.com",
|
||||
"www.haynes.co.uk",
|
||||
"www.hercle.com",
|
||||
"www.hn.10086.cn",
|
||||
"www.hotel-story.ne.jp",
|
||||
"www.hpshop.gr",
|
||||
"www.hsbank.cc",
|
||||
"www.hx168.com.cn",
|
||||
@ -426,9 +391,6 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"www.jifenpay.com",
|
||||
"www.kasite.net",
|
||||
"www.khan.co.kr",
|
||||
"www.komatsu-kenki.co.jp",
|
||||
"www.komatsu.co.jp",
|
||||
"www.komatsu.com",
|
||||
"www.kredodirect.com.ua", // bug 1095507
|
||||
"www.law888.com.tw",
|
||||
"www.lewisham.gov.uk",
|
||||
@ -436,19 +398,12 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"www.libraryvideo.com",
|
||||
"www.lm-order.de",
|
||||
"www.londonstockexchange.com",
|
||||
"www.macif.fr", // bug 1167893
|
||||
"www.marketday.com", // bug 1092998
|
||||
"www.matkahuolto.fi", // bug 1174957
|
||||
"www.matkahuolto.info",
|
||||
"www.matrics.or.jp",
|
||||
"www.mchrono.com",
|
||||
"www.mecsumai.com",
|
||||
"www.mercatoneuno.com",
|
||||
"www.mercernet.fr", // bug 1147649
|
||||
"www.meta-ehealth.com",
|
||||
"www.misterdonut.jp",
|
||||
"www.mizuno.jp",
|
||||
"www.monclick.it",
|
||||
"www.mp2.aeroport.fr",
|
||||
"www.mpay.co.th",
|
||||
"www.mtsindia.in", // RC4
|
||||
@ -462,34 +417,30 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"www.nishi.or.jp",
|
||||
"www.ocbcwhhk.com", // bug 1141746
|
||||
"www.openwebosproject.org", // bug 1151990
|
||||
"www.paslists.com", // for port 9211, bug 1155712
|
||||
"www.pen-kanagawa.ed.jp",
|
||||
"www.polla.cl",
|
||||
"www.publicjobs.ie",
|
||||
"www.publicrecords.com",
|
||||
"www.pwcrecruiting.com",
|
||||
"www.rapidscansecure.com", // bug 1177212
|
||||
"www.razorgator.com",
|
||||
"www.recoup.com",
|
||||
"www.regonline.com", // bug 1139783
|
||||
"www.renaultcredit.com.ar",
|
||||
"www.reputation.com",
|
||||
"www.rezstream.net",
|
||||
"www.rietumu.lv",
|
||||
"www.rimac.com.pe",
|
||||
"www.riversendtrading.com",
|
||||
"www.rotr.com",
|
||||
"www.roxyaffiliates.com",
|
||||
"www.s-book.net",
|
||||
"www.safepass.cn",
|
||||
"www.session.ne.jp",
|
||||
"www.shacombank.com.hk", // bug 1141989
|
||||
"www.shacomsecurities.com.hk", // bug 1141989
|
||||
"www.shop.bt.com",
|
||||
"www.slovanet.sk",
|
||||
"www.smartcart.com",
|
||||
"www.smartoffice.jp",
|
||||
"www.sokamocka.com",
|
||||
"www.sports-nakama.com",
|
||||
"www.starbucks.com", // bug 1167190
|
||||
"www.stenhouse.com",
|
||||
"www.sunderland.gov.uk",
|
||||
@ -515,15 +466,11 @@ static const char* const kIntolerantFallbackList[] =
|
||||
"www1.aeroplan.com", // bug 1137543
|
||||
"www1.isracard.co.il", // bug 1165582
|
||||
"www2.aeroplan.com", // bug 1137543
|
||||
"www2.bancobrasil.com.br", // bug 1135966
|
||||
"www2.wou.edu",
|
||||
"www28.bb.com.br", // bug 1135966
|
||||
"www3.aeroplan.com", // bug 1137543
|
||||
"www3.ibac.co.jp",
|
||||
"www3.taiheiyo-ferry.co.jp",
|
||||
"www4.aeroplan.com", // bug 1137543
|
||||
"www41.bb.com.br", // bug 1135966
|
||||
"www73.bb.com.br", // bug 1135966
|
||||
"wwws.kadokawa.co.jp",
|
||||
"xyk.cebbank.com", // bug 1145524
|
||||
"zenfolio.com",
|
||||
|
@ -1737,7 +1737,6 @@ private:
|
||||
static const char* const kFallbackWildcardList[] =
|
||||
{
|
||||
".kuronekoyamato.co.jp", // bug 1128366
|
||||
".userstorage.mega.co.nz", // bug 1133496
|
||||
".wildcard.test",
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,7 @@ support-files =
|
||||
[browser_DOMInputPasswordAdded.js]
|
||||
[browser_filldoorhanger.js]
|
||||
[browser_notifications.js]
|
||||
skip-if = os != "win" # Intermittent failures: Bug 1182296
|
||||
skip-if = true # Intermittent failures: Bug 1182296, bug 1148771
|
||||
[browser_passwordmgr_fields.js]
|
||||
[browser_passwordmgr_observers.js]
|
||||
[browser_passwordmgr_sort.js]
|
||||
|
@ -2994,8 +2994,16 @@ nsWindow::PrepareForFullscreenTransition(nsISupports** aData)
|
||||
{
|
||||
FullscreenTransitionInitData initData;
|
||||
nsCOMPtr<nsIScreen> screen = GetWidgetScreen();
|
||||
screen->GetRectDisplayPix(&initData.mBounds.x, &initData.mBounds.y,
|
||||
&initData.mBounds.width, &initData.mBounds.height);
|
||||
int32_t x, y, width, height;
|
||||
screen->GetRectDisplayPix(&x, &y, &width, &height);
|
||||
MOZ_ASSERT(BoundsUseDisplayPixels(),
|
||||
"Should only be called on top-level window");
|
||||
CSSToLayoutDeviceScale scale = GetDefaultScale();
|
||||
initData.mBounds.x = NSToIntRound(x * scale.scale);
|
||||
initData.mBounds.y = NSToIntRound(y * scale.scale);
|
||||
initData.mBounds.width = NSToIntRound(width * scale.scale);
|
||||
initData.mBounds.height = NSToIntRound(height * scale.scale);
|
||||
|
||||
// Create a semaphore for synchronizing the window handle which will
|
||||
// be created by the transition thread and used by the main thread for
|
||||
// posting the transition messages.
|
||||
|
Loading…
x
Reference in New Issue
Block a user