diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 5a962fb80809..acec12093ab6 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -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. diff --git a/browser/base/content/newtab/newTab.css b/browser/base/content/newtab/newTab.css index 0ee040ada8c5..fe095bb30fef 100644 --- a/browser/base/content/newtab/newTab.css +++ b/browser/base/content/newtab/newTab.css @@ -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; diff --git a/browser/base/content/test/plugins/browser.ini b/browser/base/content/test/plugins/browser.ini index e01114880f81..a3d633d62255 100644 --- a/browser/base/content/test/plugins/browser.ini +++ b/browser/base/content/test/plugins/browser.ini @@ -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] diff --git a/browser/components/loop/content/conversation.html b/browser/components/loop/content/conversation.html index a88300687d49..7631a74452e4 100644 --- a/browser/components/loop/content/conversation.html +++ b/browser/components/loop/content/conversation.html @@ -21,7 +21,6 @@ - diff --git a/browser/components/loop/content/js/client.js b/browser/components/loop/content/js/client.js index 3be748cbd962..4463146a9207 100644 --- a/browser/components/loop/content/js/client.js +++ b/browser/components/loop/content/js/client.js @@ -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); +})(); diff --git a/browser/components/loop/content/panel.html b/browser/components/loop/content/panel.html index d2aa202189be..6af78664cf72 100644 --- a/browser/components/loop/content/panel.html +++ b/browser/components/loop/content/panel.html @@ -16,7 +16,6 @@ - diff --git a/browser/components/loop/content/shared/css/common.css b/browser/components/loop/content/shared/css/common.css index 92b03dabdd19..aa13075e8b60 100644 --- a/browser/components/loop/content/shared/css/common.css +++ b/browser/components/loop/content/shared/css/common.css @@ -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 { diff --git a/browser/components/loop/content/shared/js/store.js b/browser/components/loop/content/shared/js/store.js index e537d6d42566..20301cdcee45 100644 --- a/browser/components/loop/content/shared/js/store.js +++ b/browser/components/loop/content/shared/js/store.js @@ -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; })(); diff --git a/browser/components/loop/content/shared/js/views.js b/browser/components/loop/content/shared/js/views.js index 98c410de6b5f..4384485bbcc2 100644 --- a/browser/components/loop/content/shared/js/views.js +++ b/browser/components/loop/content/shared/js/views.js @@ -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, diff --git a/browser/components/loop/content/shared/js/views.jsx b/browser/components/loop/content/shared/js/views.jsx index 346fa038f5f8..48442014ed3b 100644 --- a/browser/components/loop/content/shared/js/views.jsx +++ b/browser/components/loop/content/shared/js/views.jsx @@ -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 ( +
+
+ + {mozL10n.get("self_view_hidden_message")} + +
+ +
+
+ +
+ +
+ +
+
+
+ ); + } + }); + 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, diff --git a/browser/components/loop/jar.mn b/browser/components/loop/jar.mn index 754795cc218d..41173728e7f0 100644 --- a/browser/components/loop/jar.mn +++ b/browser/components/loop/jar.mn @@ -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 diff --git a/browser/components/loop/standalone/content/js/standaloneRoomViews.js b/browser/components/loop/standalone/content/js/standaloneRoomViews.js index 9e139b9c4df8..57c63121c7e6 100644 --- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js +++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js @@ -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()}, diff --git a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx index 2cc61164eb82..1b557af28acc 100644 --- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx +++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx @@ -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 (
@@ -463,38 +446,22 @@ loop.standaloneRoomViews = (function(mozL10n) { joinRoom={this.joinRoom} roomState={this.state.roomState} roomUsed={this.state.used} /> -
-
- - {mozL10n.get("self_view_hidden_message")} - -
- -
-
- -
- -
- -
-
-
+ - @@ -101,7 +100,10 @@ }); mocha.run(function () { - $("#mocha").append("

Complete.

"); + var completeNode = document.createElement("p"); + completeNode.setAttribute("id", "complete"); + completeNode.appendChild(document.createTextNode("Complete")); + document.getElementById("mocha").appendChild(completeNode); }); diff --git a/browser/components/loop/test/shared/index.html b/browser/components/loop/test/shared/index.html index 84f5f3c5d226..197a3191aa21 100644 --- a/browser/components/loop/test/shared/index.html +++ b/browser/components/loop/test/shared/index.html @@ -30,7 +30,6 @@ - @@ -95,7 +94,10 @@ }); mocha.run(function () { - $("#mocha").append("

Complete.

"); + var completeNode = document.createElement("p"); + completeNode.setAttribute("id", "complete"); + completeNode.appendChild(document.createTextNode("Complete")); + document.getElementById("mocha").appendChild(completeNode); }); diff --git a/browser/components/loop/test/shared/views_test.js b/browser/components/loop/test/shared/views_test.js index e50d699ef2ac..546a586d0b9b 100644 --- a/browser/components/loop/test/shared/views_test.js +++ b/browser/components/loop/test/shared/views_test.js @@ -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); + }); + }); }); diff --git a/browser/components/loop/test/standalone/index.html b/browser/components/loop/test/standalone/index.html index 8d6c50d1c2fd..08ffebc438c9 100644 --- a/browser/components/loop/test/standalone/index.html +++ b/browser/components/loop/test/standalone/index.html @@ -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("

Complete.

"); + var completeNode = document.createElement("p"); + completeNode.setAttribute("id", "complete"); + completeNode.appendChild(document.createTextNode("Complete")); + document.getElementById("mocha").appendChild(completeNode); }); diff --git a/browser/components/loop/test/standalone/standaloneRoomViews_test.js b/browser/components/loop/test/standalone/standaloneRoomViews_test.js index 3bf177c43e38..5514c6cb17c6 100644 --- a/browser/components/loop/test/standalone/standaloneRoomViews_test.js +++ b/browser/components/loop/test/standalone/standaloneRoomViews_test.js @@ -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 }); diff --git a/browser/components/preferences/content.js b/browser/components/preferences/content.js index 7b78159b9c85..1fe3da350807 100644 --- a/browser/components/preferences/content.js +++ b/browser/components/preferences/content.js @@ -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 = diff --git a/browser/components/preferences/content.xul b/browser/components/preferences/content.xul index e725597ebc48..da0cb1e11518 100644 --- a/browser/components/preferences/content.xul +++ b/browser/components/preferences/content.xul @@ -163,11 +163,13 @@ label="&translateWebPages.label;." accesskey="&translateWebPages.accesskey;" onsyncfrompreference="return gContentPane.updateButtons('translateButton', 'browser.translation.detectLanguage');"/> - - - +