Bug 1281619 - Land version 1.4.1 of the Loop system add-on in mozilla-central, rs=Standard8 for already reviewed code.

This commit is contained in:
Mark Banner 2016-06-22 21:47:37 +01:00
parent 2849315b84
commit dbedb24b41
68 changed files with 6719 additions and 6606 deletions

View File

@ -538,7 +538,8 @@ var WindowListener = {
state = "error";
mozL10nId += "-error";} else
if (this.isSlideshowOpen) {
state = "slideshow";} else
state = "slideshow";
suffix = ".label";} else
if (this.MozLoopService.screenShareActive) {
state = "action";
mozL10nId += "-screensharing";} else
@ -663,7 +664,9 @@ var WindowListener = {
this.activeSound.load();
this.activeSound.play();
this.activeSound.addEventListener("ended", function () {_this11.activeSound = undefined;}, false);},
this.activeSound.addEventListener("ended", function () {
_this11.activeSound = undefined;},
false);},
/**
@ -744,41 +747,7 @@ var WindowListener = {
this._listeningToTabSelect = false;
this._browserSharePaused = false;
this._currentRoomToken = null;
this._sendTelemetryEventsIfNeeded();},
/**
* Sends telemetry events for pause/ resume buttons if needed.
*/
_sendTelemetryEventsIfNeeded: function _sendTelemetryEventsIfNeeded() {
// The user can't click Resume button without clicking Pause button first.
if (!this._pauseButtonClicked) {
return;}
var buckets = this.constants.SHARING_SCREEN;
this.LoopAPI.sendMessageToHandler({
name: "TelemetryAddValue",
data: [
"LOOP_INFOBAR_ACTION_BUTTONS",
buckets.PAUSED] });
if (this._resumeButtonClicked) {
this.LoopAPI.sendMessageToHandler({
name: "TelemetryAddValue",
data: [
"LOOP_INFOBAR_ACTION_BUTTONS",
buckets.RESUMED] });}
this._pauseButtonClicked = false;
this._resumeButtonClicked = false;},
this._currentRoomToken = null;},
/**
@ -942,11 +911,8 @@ var WindowListener = {
buttonNode.accessKey = stringObj.accesskey;
LoopUI.MozLoopService.toggleBrowserSharing(_this13._browserSharePaused);
if (_this13._browserSharePaused) {
_this13._pauseButtonClicked = true;
// if paused we stop sharing remote cursors
_this13.removeRemoteCursor();} else
{
_this13._resumeButtonClicked = true;}
_this13.removeRemoteCursor();}
return true;},
@ -1418,10 +1384,10 @@ function startup(data) {
// Load our stylesheets.
var styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"].
getService(Components.interfaces.nsIStyleSheetService);
var sheets = ["chrome://loop-shared/skin/loop.css"];
var sheets = [
"chrome://loop-shared/skin/loop.css",
"chrome://loop/skin/platform.css"];var _iteratorNormalCompletion2 = true;var _didIteratorError2 = false;var _iteratorError2 = undefined;try {
if (AppConstants.platform != "linux") {
sheets.push("chrome://loop/skin/platform.css");}var _iteratorNormalCompletion2 = true;var _didIteratorError2 = false;var _iteratorError2 = undefined;try {
for (var _iterator2 = sheets[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {var sheet = _step2.value;

View File

@ -83,47 +83,6 @@ var getObjectAPIFunctionName = function getObjectAPIFunctionName(action) {
return funcName.charAt(0).toLowerCase() + funcName.substr(1);};
/**
* Retrieves a list of Social Providers from the Social API that are explicitly
* capable of sharing URLs.
* It also adds a listener that is fired whenever a new Provider is added or
* removed.
*
* @return {Array} Sorted list of share-capable Social Providers.
*/
var updateSocialProvidersCache = function updateSocialProvidersCache() {
var providers = [];var _iteratorNormalCompletion2 = true;var _didIteratorError2 = false;var _iteratorError2 = undefined;try {
for (var _iterator2 = Social.providers[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {var provider = _step2.value;
if (!provider.shareURL) {
continue;}
// Only pass the relevant data on to content.
providers.push({
iconURL: provider.iconURL,
name: provider.name,
origin: provider.origin });}} catch (err) {_didIteratorError2 = true;_iteratorError2 = err;} finally {try {if (!_iteratorNormalCompletion2 && _iterator2.return) {_iterator2.return();}} finally {if (_didIteratorError2) {throw _iteratorError2;}}}
var providersWasSet = !!gSocialProviders;
// Replace old with new.
gSocialProviders = providers.sort(function (a, b) {return (
a.name.toLowerCase().localeCompare(b.name.toLowerCase()));});
// Start listening for changes in the social provider list, if we're not
// doing that yet.
if (!providersWasSet) {
Services.obs.addObserver(updateSocialProvidersCache, "social:providers-changed", false);} else
{
// Dispatch an event to content to let stores freshen-up.
LoopAPIInternal.broadcastPushMessage("SocialProvidersChanged");}
return gSocialProviders;};
/**
* Checks that [browser.js]'s global variable `gMultiProcessBrowser` is active,
* instead of checking on first available browser element.
@ -139,7 +98,6 @@ var gBrowserSharingListeners = new Set();
var gBrowserSharingWindows = new Set();
var gPageListeners = null;
var gOriginalPageListeners = null;
var gSocialProviders = null;
var gStringBundle = null;
var gStubbedMessageHandlers = null;
var kBatchMessage = "Batch";
@ -277,27 +235,6 @@ var kMessageHandlers = {
reply();},
/**
* Activates the Social Share panel with the Social Provider panel opened
* when the popup open.
*
* @param {Object} message Message meant for the handler function, containing
* the following parameters in its `data` property:
* [ ]
* @param {Function} reply Callback function, invoked with the result of this
* message handler. The result will be sent back to
* the senders' channel.
*/
AddSocialShareProvider: function AddSocialShareProvider(message, reply) {
var win = Services.wm.getMostRecentWindow("navigator:browser");
if (!win || !win.SocialShare) {
reply();
return;}
win.SocialShare.showDirectory(win.LoopUI.toolbarButton.anchor);
reply();},
/**
* Composes an email via the external protocol service.
*
@ -415,9 +352,9 @@ var kMessageHandlers = {
// Get the map of strings.
var strings = MozLoopService.getStrings();
// Convert it to an object.
gStringBundle = {};var _iteratorNormalCompletion3 = true;var _didIteratorError3 = false;var _iteratorError3 = undefined;try {
for (var _iterator3 = strings.entries()[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {var _ref = _step3.value;var _ref2 = _slicedToArray(_ref, 2);var key = _ref2[0];var value = _ref2[1];
gStringBundle[key] = value;}} catch (err) {_didIteratorError3 = true;_iteratorError3 = err;} finally {try {if (!_iteratorNormalCompletion3 && _iterator3.return) {_iterator3.return();}} finally {if (_didIteratorError3) {throw _iteratorError3;}}}
gStringBundle = {};var _iteratorNormalCompletion2 = true;var _didIteratorError2 = false;var _iteratorError2 = undefined;try {
for (var _iterator2 = strings.entries()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {var _ref = _step2.value;var _ref2 = _slicedToArray(_ref, 2);var key = _ref2[0];var value = _ref2[1];
gStringBundle[key] = value;}} catch (err) {_didIteratorError2 = true;_iteratorError2 = err;} finally {try {if (!_iteratorNormalCompletion2 && _iterator2.return) {_iterator2.return();}} finally {if (_didIteratorError2) {throw _iteratorError2;}}}
reply(gStringBundle);},
@ -438,10 +375,7 @@ var kMessageHandlers = {
LOOP_SESSION_TYPE: LOOP_SESSION_TYPE,
LOOP_MAU_TYPE: LOOP_MAU_TYPE,
ROOM_CREATE: ROOM_CREATE,
ROOM_DELETE: ROOM_DELETE,
SHARING_ROOM_URL: SHARING_ROOM_URL,
SHARING_SCREEN: SHARING_SCREEN,
TWO_WAY_MEDIA_CONN_LENGTH: TWO_WAY_MEDIA_CONN_LENGTH });},
SHARING_ROOM_URL: SHARING_ROOM_URL });},
@ -555,8 +489,8 @@ var kMessageHandlers = {
* the senders' channel.
*/
GetErrors: function GetErrors(message, reply) {
var errors = {};var _iteratorNormalCompletion4 = true;var _didIteratorError4 = false;var _iteratorError4 = undefined;try {
for (var _iterator4 = MozLoopService.errors[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {var _ref3 = _step4.value;var _ref4 = _slicedToArray(_ref3, 2);var type = _ref4[0];var error = _ref4[1];
var errors = {};var _iteratorNormalCompletion3 = true;var _didIteratorError3 = false;var _iteratorError3 = undefined;try {
for (var _iterator3 = MozLoopService.errors[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {var _ref3 = _step3.value;var _ref4 = _slicedToArray(_ref3, 2);var type = _ref4[0];var error = _ref4[1];
// if error.error is an nsIException, just delete it since it's hard
// to clone across the boundary.
if (error.error instanceof Ci.nsIException) {
@ -566,7 +500,7 @@ var kMessageHandlers = {
delete error.error;}
errors[type] = cloneableError(error);}} catch (err) {_didIteratorError4 = true;_iteratorError4 = err;} finally {try {if (!_iteratorNormalCompletion4 && _iterator4.return) {_iterator4.return();}} finally {if (_didIteratorError4) {throw _iteratorError4;}}}
errors[type] = cloneableError(error);}} catch (err) {_didIteratorError3 = true;_iteratorError3 = err;} finally {try {if (!_iteratorNormalCompletion3 && _iterator3.return) {_iterator3.return();}} finally {if (_didIteratorError3) {throw _iteratorError3;}}}
return reply(errors);},
@ -699,25 +633,6 @@ var kMessageHandlers = {
win.gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetPageData");},
/**
* Returns a sorted list of Social Providers that can share URLs. See
* `updateSocialProvidersCache()` for more information.
*
* @param {Object} message Message meant for the handler function, containing
* the following parameters in its `data` property:
* [ ]
* @param {Function} reply Callback function, invoked with the result of this
* message handler. The result will be sent back to
* the senders' channel.
* @return {Array} Sorted list of share-capable Social Providers.
*/
GetSocialShareProviders: function GetSocialShareProviders(message, reply) {
if (!gSocialProviders) {
updateSocialProvidersCache();}
reply(gSocialProviders);},
/**
* Gets an object with data that represents the currently
* authenticated user's identity.
@ -990,15 +905,15 @@ var kMessageHandlers = {
if (gBrowserSharingListeners.size > 0) {
// There are still clients listening in, so keep on listening...
reply();
return;}var _iteratorNormalCompletion5 = true;var _didIteratorError5 = false;var _iteratorError5 = undefined;try {
return;}var _iteratorNormalCompletion4 = true;var _didIteratorError4 = false;var _iteratorError4 = undefined;try {
for (var _iterator5 = gBrowserSharingWindows[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {var win = _step5.value;
for (var _iterator4 = gBrowserSharingWindows[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {var win = _step4.value;
win = win.get();
if (!win) {
continue;}
win.LoopUI.stopBrowserSharing();}} catch (err) {_didIteratorError5 = true;_iteratorError5 = err;} finally {try {if (!_iteratorNormalCompletion5 && _iterator5.return) {_iterator5.return();}} finally {if (_didIteratorError5) {throw _iteratorError5;}}}
win.LoopUI.stopBrowserSharing();}} catch (err) {_didIteratorError4 = true;_iteratorError4 = err;} finally {try {if (!_iteratorNormalCompletion4 && _iterator4.return) {_iterator4.return();}} finally {if (_didIteratorError4) {throw _iteratorError4;}}}
NewTabURL.reset();
@ -1090,42 +1005,6 @@ var kMessageHandlers = {
reply();},
/**
* Share a room URL with the Social API.
*
* @param {Object} message Message meant for the handler function, containing
* the following parameters in its `data` property:
* [
* {String} providerOrigin URL fragment that identifies
* a social provider
* {String} roomURL URL of a room
* {String} title Title of the sharing message
* {String} body Body of the sharing message
* ]
* @param {Function} reply Callback function, invoked with the result of this
* message handler. The result will be sent back to
* the senders' channel.
*/
SocialShareRoom: function SocialShareRoom(message, reply) {
var win = Services.wm.getMostRecentWindow("navigator:browser");
if (!win || !win.SocialShare) {
reply();
return;}var _message$data10 = _slicedToArray(
message.data, 4);var providerOrigin = _message$data10[0];var roomURL = _message$data10[1];var title = _message$data10[2];var body = _message$data10[3];
var graphData = {
url: roomURL,
title: title };
if (body) {
graphData.body = body;}
win.SocialShare.sharePage(providerOrigin, graphData, null,
win.LoopUI.toolbarButton.anchor);
reply();},
/**
* Adds a value to a telemetry histogram.
*
@ -1141,8 +1020,8 @@ var kMessageHandlers = {
* message handler. The result will be sent back to
* the senders' channel.
*/
TelemetryAddValue: function TelemetryAddValue(message, reply) {var _message$data11 = _slicedToArray(
message.data, 2);var histogramId = _message$data11[0];var value = _message$data11[1];
TelemetryAddValue: function TelemetryAddValue(message, reply) {var _message$data10 = _slicedToArray(
message.data, 2);var histogramId = _message$data10[0];var value = _message$data10[1];
if (histogramId === "LOOP_ACTIVITY_COUNTER") {
var pref = "mau." + kMauPrefMap.get(value);
@ -1189,13 +1068,13 @@ var LoopAPIInternal = {
new RemotePages("about:loopconversation"),
// Slideshow added here to expose the loop api to make L10n work.
// XXX Can remove once slideshow is made remote.
new RemotePages("chrome://loop/content/panels/slideshow.html")];var _iteratorNormalCompletion6 = true;var _didIteratorError6 = false;var _iteratorError6 = undefined;try {
for (var _iterator6 = gPageListeners[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {var page = _step6.value;
new RemotePages("chrome://loop/content/panels/slideshow.html")];var _iteratorNormalCompletion5 = true;var _didIteratorError5 = false;var _iteratorError5 = undefined;try {
for (var _iterator5 = gPageListeners[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {var page = _step5.value;
page.addMessageListener(kMessageName, this.handleMessage.bind(this));}
// Subscribe to global events:
} catch (err) {_didIteratorError6 = true;_iteratorError6 = err;} finally {try {if (!_iteratorNormalCompletion6 && _iterator6.return) {_iterator6.return();}} finally {if (_didIteratorError6) {throw _iteratorError6;}}}Services.obs.addObserver(this.handleStatusChanged, "loop-status-changed", false);},
} catch (err) {_didIteratorError5 = true;_iteratorError5 = err;} finally {try {if (!_iteratorNormalCompletion5 && _iterator5.return) {_iterator5.return();}} finally {if (_didIteratorError5) {throw _iteratorError5;}}}Services.obs.addObserver(this.handleStatusChanged, "loop-status-changed", false);},
/**
@ -1351,14 +1230,14 @@ var LoopAPIInternal = {
MozLoopService.log.debug("Unable to send event through to target: " +
ex.message);
// Unregister event handlers when the message port is unreachable.
var _iteratorNormalCompletion7 = true;var _didIteratorError7 = false;var _iteratorError7 = undefined;try {for (var _iterator7 = events[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {var eventName = _step7.value;
api.off(eventName, handlerFunc);}} catch (err) {_didIteratorError7 = true;_iteratorError7 = err;} finally {try {if (!_iteratorNormalCompletion7 && _iterator7.return) {_iterator7.return();}} finally {if (_didIteratorError7) {throw _iteratorError7;}}}}};var _iteratorNormalCompletion8 = true;var _didIteratorError8 = false;var _iteratorError8 = undefined;try {
var _iteratorNormalCompletion6 = true;var _didIteratorError6 = false;var _iteratorError6 = undefined;try {for (var _iterator6 = events[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {var eventName = _step6.value;
api.off(eventName, handlerFunc);}} catch (err) {_didIteratorError6 = true;_iteratorError6 = err;} finally {try {if (!_iteratorNormalCompletion6 && _iterator6.return) {_iterator6.return();}} finally {if (_didIteratorError6) {throw _iteratorError6;}}}}};var _iteratorNormalCompletion7 = true;var _didIteratorError7 = false;var _iteratorError7 = undefined;try {
for (var _iterator8 = events[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {var eventName = _step8.value;
api.on(eventName, handlerFunc);}} catch (err) {_didIteratorError8 = true;_iteratorError8 = err;} finally {try {if (!_iteratorNormalCompletion8 && _iterator8.return) {_iterator8.return();}} finally {if (_didIteratorError8) {throw _iteratorError8;}}}
for (var _iterator7 = events[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {var eventName = _step7.value;
api.on(eventName, handlerFunc);}} catch (err) {_didIteratorError7 = true;_iteratorError7 = err;} finally {try {if (!_iteratorNormalCompletion7 && _iterator7.return) {_iterator7.return();}} finally {if (_didIteratorError7) {throw _iteratorError7;}}}
reply();
return { v: void 0 };}();if ((typeof _ret === "undefined" ? "undefined" : _typeof(_ret)) === "object") return _ret.v;}
@ -1388,16 +1267,16 @@ var LoopAPIInternal = {
*/
broadcastPushMessage: function broadcastPushMessage(name, data) {
if (!gPageListeners) {
return;}var _iteratorNormalCompletion9 = true;var _didIteratorError9 = false;var _iteratorError9 = undefined;try {
return;}var _iteratorNormalCompletion8 = true;var _didIteratorError8 = false;var _iteratorError8 = undefined;try {
for (var _iterator9 = gPageListeners[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {var page = _step9.value;
for (var _iterator8 = gPageListeners[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {var page = _step8.value;
try {
page.sendAsyncMessage(kPushMessageName, [name, data]);}
catch (ex) {
// Only make noise when the Remote Page Manager needs more time to
// initialize.
if (ex.result != Components.results.NS_ERROR_NOT_INITIALIZED) {
throw ex;}}}} catch (err) {_didIteratorError9 = true;_iteratorError9 = err;} finally {try {if (!_iteratorNormalCompletion9 && _iterator9.return) {_iterator9.return();}} finally {if (_didIteratorError9) {throw _iteratorError9;}}}},
throw ex;}}}} catch (err) {_didIteratorError8 = true;_iteratorError8 = err;} finally {try {if (!_iteratorNormalCompletion8 && _iterator8.return) {_iterator8.return();}} finally {if (_didIteratorError8) {throw _iteratorError8;}}}},
@ -1408,19 +1287,15 @@ var LoopAPIInternal = {
*/
destroy: function destroy() {
if (!gPageListeners) {
return;}var _iteratorNormalCompletion10 = true;var _didIteratorError10 = false;var _iteratorError10 = undefined;try {
return;}var _iteratorNormalCompletion9 = true;var _didIteratorError9 = false;var _iteratorError9 = undefined;try {
for (var _iterator10 = gPageListeners[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {var listener = _step10.value;
listener.destroy();}} catch (err) {_didIteratorError10 = true;_iteratorError10 = err;} finally {try {if (!_iteratorNormalCompletion10 && _iterator10.return) {_iterator10.return();}} finally {if (_didIteratorError10) {throw _iteratorError10;}}}
for (var _iterator9 = gPageListeners[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {var listener = _step9.value;
listener.destroy();}} catch (err) {_didIteratorError9 = true;_iteratorError9 = err;} finally {try {if (!_iteratorNormalCompletion9 && _iterator9.return) {_iterator9.return();}} finally {if (_didIteratorError9) {throw _iteratorError9;}}}
gPageListeners = null;
// Unsubscribe from global events.
Services.obs.removeObserver(this.handleStatusChanged, "loop-status-changed");
// Stop listening for changes in the social provider list, if necessary.
if (gSocialProviders) {
Services.obs.removeObserver(updateSocialProvidersCache, "social:providers-changed");}} };
Services.obs.removeObserver(this.handleStatusChanged, "loop-status-changed");} };

View File

@ -11,20 +11,6 @@ var LOOP_SESSION_TYPE = {
FXA: 2 };
/**
* Values that we segment 2-way media connection length telemetry probes
* into.
*
* @type {{SHORTER_THAN_10S: Number, BETWEEN_10S_AND_30S: Number,
* BETWEEN_30S_AND_5M: Number, MORE_THAN_5M: Number}}
*/
var TWO_WAY_MEDIA_CONN_LENGTH = {
SHORTER_THAN_10S: 0,
BETWEEN_10S_AND_30S: 1,
BETWEEN_30S_AND_5M: 2,
MORE_THAN_5M: 3 };
/**
* Values that we segment sharing a room URL action telemetry probes into.
*
@ -51,26 +37,6 @@ var ROOM_CREATE = {
CREATE_FAIL: 1 };
/**
* Values that we segment room delete action telemetry probes into.
*
* @type {{DELETE_SUCCESS: Number, DELETE_FAIL: Number}}
*/
var ROOM_DELETE = {
DELETE_SUCCESS: 0,
DELETE_FAIL: 1 };
/**
* Values that we segment sharing screen pause/ resume action telemetry probes into.
*
* @type {{PAUSED: Number, RESUMED: Number}}
*/
var SHARING_SCREEN = {
PAUSED: 0,
RESUMED: 1 };
/**
* Values that we segment copy panel action telemetry probes into.
*
@ -126,16 +92,12 @@ Cu.import("resource://gre/modules/FxAccountsOAuthClient.jsm");
Cu.importGlobalProperties(["URL"]);
this.EXPORTED_SYMBOLS = ["MozLoopService", "LOOP_SESSION_TYPE", "LOOP_MAU_TYPE",
"TWO_WAY_MEDIA_CONN_LENGTH", "SHARING_ROOM_URL", "SHARING_SCREEN", "COPY_PANEL",
"ROOM_CREATE", "ROOM_DELETE"];
"SHARING_ROOM_URL", "COPY_PANEL", "ROOM_CREATE"];
XPCOMUtils.defineConstant(this, "LOOP_SESSION_TYPE", LOOP_SESSION_TYPE);
XPCOMUtils.defineConstant(this, "TWO_WAY_MEDIA_CONN_LENGTH", TWO_WAY_MEDIA_CONN_LENGTH);
XPCOMUtils.defineConstant(this, "SHARING_ROOM_URL", SHARING_ROOM_URL);
XPCOMUtils.defineConstant(this, "SHARING_SCREEN", SHARING_SCREEN);
XPCOMUtils.defineConstant(this, "COPY_PANEL", COPY_PANEL);
XPCOMUtils.defineConstant(this, "ROOM_CREATE", ROOM_CREATE);
XPCOMUtils.defineConstant(this, "ROOM_DELETE", ROOM_DELETE);
XPCOMUtils.defineConstant(this, "LOOP_MAU_TYPE", LOOP_MAU_TYPE);
XPCOMUtils.defineLazyModuleGetter(this, "LoopAPI",
@ -829,7 +791,9 @@ var MozLoopServiceInternal = {
var report = convertToRTCStatsReport(internalFormat);
var logStr = "";
logs.forEach(function (s) {logStr += s + "\n";});
logs.forEach(function (s) {
logStr += s + "\n";});
// We have stats and logs.

View File

@ -151,43 +151,6 @@ html[dir="rtl"] .share-action-group > .invite-button:last-child {
color: #4a4a4a;
}
.share-service-dropdown {
color: #000;
text-align: start;
bottom: auto;
top: 0;
overflow: hidden;
overflow-y: auto;
}
/* When the dropdown is showing a vertical scrollbar, compensate for its width. */
body[platform="other"] .share-service-dropdown.overflow > .dropdown-menu-item,
body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
padding-inline-end: 20px;
}
.share-service-dropdown > .dropdown-menu-item > .icon {
width: 14px;
height: 14px;
margin-right: 4px;
}
.dropdown-menu-item > .icon-add-share-service {
background-image: url("../img/icons-16x16.svg#add");
background-repeat: no-repeat;
background-size: 12px 12px;
width: 12px;
height: 12px;
}
.dropdown-menu-item:hover > .icon-add-share-service {
background-image: url("../img/icons-16x16.svg#add-hover");
}
.dropdown-menu-item:hover:active > .icon-add-share-service {
background-image: url("../img/icons-16x16.svg#add-active");
}
.share-panel-container {
position: absolute;
top: 0;

View File

@ -179,9 +179,6 @@ loop.conversation = function (mozL10n) {
sdk: OT });
// expose for functional tests
loop.conversation._sdkDriver = sdkDriver;
// Create the stores.
var activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, {
isDesktop: true,
@ -236,15 +233,7 @@ loop.conversation = function (mozL10n) {
return {
AppControllerView: AppControllerView,
init: init,
/**
* Exposed for the use of functional tests to be able to check
* metric-related execution as the call sequence progresses.
*
* @type loop.OTSdkDriver
*/
_sdkDriver: null };}(
init: init };}(
document.mozL10n);

View File

@ -157,8 +157,7 @@ loop.shared.desktopViews = function (mozL10n) {
locationForMetrics: React.PropTypes.string.isRequired,
// This data is supplied by the activeRoomStore.
roomData: React.PropTypes.object.isRequired,
show: React.PropTypes.bool.isRequired,
socialShareProviders: React.PropTypes.array },
show: React.PropTypes.bool.isRequired },
render: function render() {var _this = this;
@ -204,84 +203,9 @@ loop.shared.desktopViews = function (mozL10n) {
locationForMetrics: _this.props.locationForMetrics,
roomData: _this.props.roomData });}
return null;}()),
return null;}())));} });
React.createElement(SocialShareDropdown, {
dispatcher: this.props.dispatcher,
ref: "menu",
roomUrl: this.props.roomData.roomUrl,
show: this.state.showMenu,
socialShareProviders: this.props.socialShareProviders })));} });
var SocialShareDropdown = React.createClass({ displayName: "SocialShareDropdown",
propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
roomUrl: React.PropTypes.string,
show: React.PropTypes.bool.isRequired,
socialShareProviders: React.PropTypes.array },
handleAddServiceClick: function handleAddServiceClick(event) {
event.preventDefault();
this.props.dispatcher.dispatch(new sharedActions.AddSocialShareProvider());},
handleProviderClick: function handleProviderClick(event) {
event.preventDefault();
var origin = event.currentTarget.dataset.provider;
var provider = this.props.socialShareProviders.
filter(function (socialProvider) {
return socialProvider.origin === origin;})[
0];
this.props.dispatcher.dispatch(new sharedActions.ShareRoomUrl({
provider: provider,
roomUrl: this.props.roomUrl,
previews: [] }));},
render: function render() {
// Don't render a thing when no data has been fetched yet.
if (!this.props.socialShareProviders) {
return null;}
var cx = classNames;
var shareDropdown = cx({
"share-service-dropdown": true,
"dropdown-menu": true,
"visually-hidden": true,
"hide": !this.props.show });
return (
React.createElement("ul", { className: shareDropdown },
React.createElement("li", { className: "dropdown-menu-item", onClick: this.handleAddServiceClick },
React.createElement("i", { className: "icon icon-add-share-service" }),
React.createElement("span", null, mozL10n.get("share_add_service_button"))),
this.props.socialShareProviders.length ? React.createElement("li", { className: "dropdown-menu-separator" }) : null,
this.props.socialShareProviders.map(function (provider, idx) {
return (
React.createElement("li", { className: "dropdown-menu-item",
"data-provider": provider.origin,
key: "provider-" + idx,
onClick: this.handleProviderClick },
React.createElement("img", { className: "icon", src: provider.iconURL }),
React.createElement("span", null, provider.name)));}.
bind(this))));} });
@ -291,7 +215,6 @@ loop.shared.desktopViews = function (mozL10n) {
CopyLinkButton: CopyLinkButton,
EmailLinkButton: EmailLinkButton,
FacebookShareButton: FacebookShareButton,
SharePanelView: SharePanelView,
SocialShareDropdown: SocialShareDropdown };}(
SharePanelView: SharePanelView };}(
navigator.mozL10n || document.mozL10n);

View File

@ -687,7 +687,9 @@ loop.panel = _.extend(loop.panel || {}, function (_, mozL10n) {
topPos = clickYPos - listTop + clickOffset;}
// Ensure menu is not cut off at top
if (topPos < 0) {topPos = 0;}
if (topPos < 0) {
topPos = 0;}
return topPos;}
@ -1128,8 +1130,7 @@ loop.panel = _.extend(loop.panel || {}, function (_, mozL10n) {
facebookEnabled: this.state.facebookEnabled,
locationForMetrics: "panel",
roomData: roomData,
show: true,
socialShareProviders: this.state.socialShareProviders })));} });
show: true })));} });

View File

@ -77,7 +77,6 @@ loop.store = loop.store || {};
* @type {Array}
*/
actions: [
"addSocialShareProvider",
"createRoom",
"createdRoom",
"createRoomError",
@ -89,7 +88,6 @@ loop.store = loop.store || {};
"getAllRooms",
"getAllRoomsError",
"openRoom",
"shareRoomUrl",
"updateRoomContext",
"updateRoomContextDone",
"updateRoomContextError",
@ -348,10 +346,7 @@ loop.store = loop.store || {};
console.error("No URL sharing type bucket found for '" + from + "'");
return;}
loop.requestMulti(
["TelemetryAddValue", "LOOP_SHARING_ROOM_URL", bucket],
["TelemetryAddValue", "LOOP_ACTIVITY_COUNTER", this._constants.LOOP_MAU_TYPE.ROOM_SHARE]);},
loop.request("TelemetryAddValue", "LOOP_ACTIVITY_COUNTER", this._constants.LOOP_MAU_TYPE.ROOM_SHARE);},
/**
@ -373,7 +368,6 @@ loop.store = loop.store || {};
loop.requestMulti(
["NotifyUITour", "Loop:RoomURLEmailed"],
["TelemetryAddValue", "LOOP_SHARING_ROOM_URL", bucket],
["TelemetryAddValue", "LOOP_ACTIVITY_COUNTER", this._constants.LOOP_MAU_TYPE.ROOM_SHARE]);},
@ -411,49 +405,7 @@ loop.store = loop.store || {};
console.error("No URL sharing type bucket found for '" + from + "'");
return;}
loop.requestMulti(
["TelemetryAddValue", "LOOP_SHARING_ROOM_URL", bucket],
["TelemetryAddValue", "LOOP_ACTIVITY_COUNTER", this._constants.LOOP_MAU_TYPE.ROOM_SHARE]);},
/**
* Share a room url.
*
* @param {sharedActions.ShareRoomUrl} actionData The action data.
*/
shareRoomUrl: function shareRoomUrl(actionData) {
var providerOrigin = new URL(actionData.provider.origin).hostname;
var shareTitle = "";
var shareBody = null;
switch (providerOrigin) {
case "mail.google.com":
shareTitle = mozL10n.get("share_email_subject7");
shareBody = mozL10n.get("share_email_body7", {
callUrl: actionData.roomUrl });
shareBody += mozL10n.get("share_email_footer2");
break;
case "twitter.com":
default:
shareTitle = mozL10n.get("share_tweet", {
clientShortname2: mozL10n.get("clientShortname2") });
break;}
loop.requestMulti(
["SocialShareRoom", actionData.provider.origin, actionData.roomUrl,
shareTitle, shareBody],
["NotifyUITour", "Loop:RoomURLShared"]);},
/**
* Open the share panel to add a Social share provider.
*/
addSocialShareProvider: function addSocialShareProvider() {
loop.request("AddSocialShareProvider");},
loop.request("TelemetryAddValue", "LOOP_ACTIVITY_COUNTER", this._constants.LOOP_MAU_TYPE.ROOM_SHARE);},
/**
@ -467,12 +419,7 @@ loop.store = loop.store || {};
if (isError) {
this.dispatchAction(new sharedActions.DeleteRoomError({ error: result }));}
var buckets = this._constants.ROOM_DELETE;
loop.requestMulti(
["TelemetryAddValue", "LOOP_ROOM_DELETE", buckets[isError ?
"DELETE_FAIL" : "DELETE_SUCCESS"]],
["TelemetryAddValue", "LOOP_ACTIVITY_COUNTER", this._constants.LOOP_MAU_TYPE.ROOM_DELETE]);}.
loop.request("TelemetryAddValue", "LOOP_ACTIVITY_COUNTER", this._constants.LOOP_MAU_TYPE.ROOM_DELETE);}.
bind(this));},

View File

@ -372,8 +372,7 @@ loop.roomViews = function (mozL10n) {
facebookEnabled: this.props.facebookEnabled,
locationForMetrics: "conversation",
roomData: roomData,
show: shouldRenderInvitationOverlay,
socialShareProviders: this.state.socialShareProviders }))));}}} });
show: shouldRenderInvitationOverlay }))));}}} });

View File

@ -267,96 +267,4 @@ describe("loop.shared.desktopViews", function () {
roomData: {} });
expect(ReactDOM.findDOMNode(view)).eql(null);});});
describe("SocialShareDropdown", function () {
var fakeProvider, view;
beforeEach(function () {
fakeProvider = {
name: "foo",
origin: "https://foo",
iconURL: "http://example.com/foo.png" };});
afterEach(function () {
fakeProvider = null;});
function mountTestComponent(props) {
props = _.extend({
dispatcher: dispatcher,
show: true },
props);
return TestUtils.renderIntoDocument(
React.createElement(sharedDesktopViews.SocialShareDropdown, props));}
describe("#render", function () {
it("should show no contents when the Social Providers have not been fetched yet", function () {
view = mountTestComponent();
expect(ReactDOM.findDOMNode(view)).to.eql(null);});
it("should show an empty list when no Social Providers are available", function () {
view = mountTestComponent({
socialShareProviders: [] });
var node = ReactDOM.findDOMNode(view);
expect(node.querySelector(".icon-add-share-service")).to.not.eql(null);
expect(node.querySelectorAll(".dropdown-menu-item").length).to.eql(1);});
it("should show a list of available Social Providers", function () {
view = mountTestComponent({
socialShareProviders: [fakeProvider] });
var node = ReactDOM.findDOMNode(view);
expect(node.querySelector(".icon-add-share-service")).to.not.eql(null);
expect(node.querySelector(".dropdown-menu-separator")).to.not.eql(null);
var dropdownNodes = node.querySelectorAll(".dropdown-menu-item");
expect(dropdownNodes.length).to.eql(2);
expect(dropdownNodes[1].querySelector("img").src).to.eql(fakeProvider.iconURL);
expect(dropdownNodes[1].querySelector("span").textContent).
to.eql(fakeProvider.name);});});
describe("#handleAddServiceClick", function () {
it("should dispatch an action when the 'add provider' item is clicked", function () {
view = mountTestComponent({
socialShareProviders: [] });
var addItem = ReactDOM.findDOMNode(view).querySelector(".dropdown-menu-item:first-child");
React.addons.TestUtils.Simulate.click(addItem);
sinon.assert.calledOnce(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.AddSocialShareProvider());});});
describe("#handleProviderClick", function () {
it("should dispatch an action when a provider item is clicked", function () {
view = mountTestComponent({
roomUrl: "http://example.com",
socialShareProviders: [fakeProvider] });
var providerItem = ReactDOM.findDOMNode(view).querySelector(".dropdown-menu-item:last-child");
React.addons.TestUtils.Simulate.click(providerItem);
sinon.assert.calledOnce(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.ShareRoomUrl({
provider: fakeProvider,
roomUrl: "http://example.com",
previews: [] }));});});});});
expect(ReactDOM.findDOMNode(view)).eql(null);});});});

View File

@ -41,10 +41,6 @@ describe("loop.store.RoomStore", function () {
CREATE_SUCCESS: 0,
CREATE_FAIL: 1 },
ROOM_DELETE: {
DELETE_SUCCESS: 0,
DELETE_FAIL: 1 },
LOOP_MAU_TYPE: {
OPEN_PANEL: 0,
OPEN_CONVERSATION: 1,
@ -104,7 +100,9 @@ describe("loop.store.RoomStore", function () {
ctime: 1405518241 }];
document.mozL10n.get = function (str) {return str;};});
document.mozL10n.get = function (str) {
return str;};});
afterEach(function () {
@ -505,34 +503,10 @@ describe("loop.store.RoomStore", function () {
sinon.assert.calledOnce(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.DeleteRoomError({
error: err }));});
error: err }));});});
it("should log a telemetry event when the operation is successful", function () {
store.deleteRoom(new sharedActions.DeleteRoom({
roomToken: fakeRoomToken }));
sinon.assert.calledTwice(requestStubs.TelemetryAddValue);
sinon.assert.calledWithExactly(requestStubs.TelemetryAddValue.getCall(0),
"LOOP_ROOM_DELETE", 0);});
it("should log a telemetry event when the operation fails", function () {
var err = new Error("fake");
err.isError = true;
requestStubs["Rooms:Delete"].returns(err);
store.deleteRoom(new sharedActions.DeleteRoom({
roomToken: fakeRoomToken }));
sinon.assert.calledTwice(requestStubs.TelemetryAddValue);
sinon.assert.calledWithExactly(requestStubs.TelemetryAddValue.getCall(0),
"LOOP_ROOM_DELETE", 1);});});
describe("#copyRoomUrl", function () {
it("should copy the room URL", function () {
@ -542,29 +516,7 @@ describe("loop.store.RoomStore", function () {
sinon.assert.calledOnce(requestStubs.CopyString);
sinon.assert.calledWithExactly(requestStubs.CopyString, "http://invalid");});
it("should send a telemetry event for copy from panel", function () {
store.copyRoomUrl(new sharedActions.CopyRoomUrl({
roomUrl: "http://invalid",
from: "panel" }));
sinon.assert.calledTwice(requestStubs.TelemetryAddValue);
sinon.assert.calledWithExactly(requestStubs.TelemetryAddValue.getCall(0),
"LOOP_SHARING_ROOM_URL", 0);});
it("should send a telemetry event for copy from conversation", function () {
store.copyRoomUrl(new sharedActions.CopyRoomUrl({
roomUrl: "http://invalid",
from: "conversation" }));
sinon.assert.calledTwice(requestStubs.TelemetryAddValue);
sinon.assert.calledWithExactly(requestStubs.TelemetryAddValue.getCall(0),
"LOOP_SHARING_ROOM_URL", 1);});});
sinon.assert.calledWithExactly(requestStubs.CopyString, "http://invalid");});});
@ -647,76 +599,7 @@ describe("loop.store.RoomStore", function () {
sinon.assert.calledOnce(requestStubs.OpenURL);
sinon.assert.calledWithMatch(requestStubs.OpenURL, sharingSite);
sinon.assert.calledWithMatch(requestStubs.OpenURL, room);
sinon.assert.calledWithMatch(requestStubs.OpenURL, fallback);});
it("should send a telemetry event for facebook share from conversation", function () {
store.facebookShareRoomUrl(new sharedActions.FacebookShareRoomUrl({
from: "conversation",
roomUrl: "http://invalid" }));
sinon.assert.calledTwice(requestStubs.TelemetryAddValue);
sinon.assert.calledWithExactly(requestStubs.TelemetryAddValue.getCall(0),
"LOOP_SHARING_ROOM_URL", 4);});});
describe("#shareRoomUrl", function () {
var socialShareRoomStub;
beforeEach(function () {
socialShareRoomStub = sinon.stub();
LoopMochaUtils.stubLoopRequest({
SocialShareRoom: socialShareRoomStub });});
it("should pass the correct data for GMail sharing", function () {
var roomUrl = "http://invalid";
var origin = "https://mail.google.com/v1";
store.shareRoomUrl(new sharedActions.ShareRoomUrl({
roomUrl: roomUrl,
provider: {
origin: origin } }));
sinon.assert.calledOnce(socialShareRoomStub);
sinon.assert.calledWithExactly(socialShareRoomStub,
origin,
roomUrl,
"share_email_subject7",
"share_email_body7" +
"share_email_footer2");});
it("should pass the correct data for all other Social Providers", function () {
var roomUrl = "http://invalid2";
var origin = "https://twitter.com/share";
store.shareRoomUrl(new sharedActions.ShareRoomUrl({
roomUrl: roomUrl,
provider: {
origin: origin } }));
sinon.assert.calledOnce(socialShareRoomStub);
sinon.assert.calledWithExactly(socialShareRoomStub, origin,
roomUrl, "share_tweet", null);});});
describe("#addSocialShareProvider", function () {
it("should invoke to the correct mozLoop function", function () {
var stub = sinon.stub();
LoopMochaUtils.stubLoopRequest({
AddSocialShareProvider: stub });
store.addSocialShareProvider(new sharedActions.AddSocialShareProvider());
sinon.assert.calledOnce(stub);});});
sinon.assert.calledWithMatch(requestStubs.OpenURL, fallback);});});
@ -1038,8 +921,8 @@ describe("loop.store.RoomStore", function () {
from: "conversation" }));
sinon.assert.calledTwice(requestStubs["TelemetryAddValue"]);
sinon.assert.calledWithExactly(requestStubs["TelemetryAddValue"].getCall(1),
sinon.assert.calledOnce(requestStubs["TelemetryAddValue"]);
sinon.assert.calledWithExactly(requestStubs["TelemetryAddValue"],
"LOOP_ACTIVITY_COUNTER", store._constants.LOOP_MAU_TYPE.ROOM_SHARE);});
@ -1049,8 +932,8 @@ describe("loop.store.RoomStore", function () {
from: "conversation" }));
sinon.assert.calledTwice(requestStubs["TelemetryAddValue"]);
sinon.assert.calledWithExactly(requestStubs["TelemetryAddValue"].getCall(1),
sinon.assert.calledOnce(requestStubs["TelemetryAddValue"]);
sinon.assert.calledWithExactly(requestStubs["TelemetryAddValue"],
"LOOP_ACTIVITY_COUNTER", store._constants.LOOP_MAU_TYPE.ROOM_SHARE);});
@ -1060,8 +943,8 @@ describe("loop.store.RoomStore", function () {
from: "conversation" }));
sinon.assert.calledTwice(requestStubs["TelemetryAddValue"]);
sinon.assert.calledWithExactly(requestStubs["TelemetryAddValue"].getCall(1),
sinon.assert.calledOnce(requestStubs["TelemetryAddValue"]);
sinon.assert.calledWithExactly(requestStubs["TelemetryAddValue"],
"LOOP_ACTIVITY_COUNTER", store._constants.LOOP_MAU_TYPE.ROOM_SHARE);});
@ -1070,6 +953,6 @@ describe("loop.store.RoomStore", function () {
roomToken: "42abc" }));
sinon.assert.calledTwice(requestStubs["TelemetryAddValue"]);
sinon.assert.calledWithExactly(requestStubs["TelemetryAddValue"].getCall(1),
sinon.assert.calledOnce(requestStubs["TelemetryAddValue"]);
sinon.assert.calledWithExactly(requestStubs["TelemetryAddValue"],
"LOOP_ACTIVITY_COUNTER", store._constants.LOOP_MAU_TYPE.ROOM_DELETE);});});});

View File

@ -1,7 +1,7 @@
pref("loop.enabled", true);
pref("loop.remote.autostart", true);
#ifdef LOOP_DEV_XPI
pref("loop.server", "https://loop-dev.stage.mozaws.net/v0");
pref("loop.server", "https://loop.dev.mozaws.net/v0");
pref("loop.linkClicker.url", "https://loop-webapp-dev.stage.mozaws.net/");
#else
pref("loop.server", "https://loop.services.mozilla.com/v0");
@ -24,7 +24,6 @@ pref("loop.copy.ticket", -1);
pref("loop.debug.loglevel", "Error");
pref("loop.debug.dispatcher", false);
pref("loop.debug.sdk", false);
pref("loop.debug.twoWayMediaTelemetry", false);
pref("loop.feedback.dateLastSeenSec", 0);
pref("loop.feedback.periodSec", 15770000); // 6 months.
pref("loop.feedback.formURL", "https://www.surveygizmo.com/s3/2651383/Firefox-Hello-Product-Survey-II?version=%APP_VERSION%");

View File

@ -63,10 +63,6 @@ p {
display: none !important;
}
.visually-hidden {
visibility: hidden;
}
.tc {
text-align: center;
}
@ -466,13 +462,6 @@ html[dir="rtl"] .dropdown-menu {
background-color: #dbf7ff;
}
.dropdown-menu-separator {
height: 1px;
margin: 2px -2px 1px -2px;
border-top: 1px solid #dedede;
background-color: #fff;
}
/* Custom checkbox */
.checkbox-wrapper {

View File

@ -417,24 +417,6 @@ loop.shared.actions = function () {
// roomOrigin: String
}),
/**
* Share a room url via the Social API.
* XXX: should move to some roomActions module - refs bug 1079284
* @provider: one of the share-capable Social Providers included
* @roomUrl: the URL that is shared
*/
ShareRoomUrl: Action.define("shareRoomUrl", {
provider: Object,
roomUrl: String }),
/**
* Open the share panel to add a Social share provider.
* XXX: should move to some roomActions module - refs bug 1079284
*/
AddSocialShareProvider: Action.define("addSocialShareProvider", {}),
/**
* XXX: should move to some roomActions module - refs bug 1079284
*/
@ -458,9 +440,8 @@ loop.shared.actions = function () {
// roomInfoFailure: String - Optional.
// roomName: String - Optional.
// roomState: String - Optional.
roomUrl: String
// socialShareProviders: Array - Optional.
}),
roomUrl: String }),
/**
* Notifies if the user agent will handle the room or not.
@ -469,14 +450,6 @@ loop.shared.actions = function () {
handlesRoom: Boolean }),
/**
* Updates the Social API information when it is received.
* XXX: should move to some roomActions module - refs bug 1079284
*/
UpdateSocialShareInfo: Action.define("updateSocialShareInfo", {
socialShareProviders: Array }),
/**
* Starts the process for the user to join the room.
* XXX: should move to some roomActions module - refs bug 1079284

View File

@ -55,8 +55,7 @@ loop.store.ActiveRoomStore = function (mozL10n) {
roomDescription: "roomDescription",
roomInfoFailure: "roomInfoFailure",
roomName: "roomName",
roomState: "roomState",
socialShareProviders: "socialShareProviders" };
roomState: "roomState" };
var updateContextTimer = null;
@ -158,8 +157,6 @@ loop.store.ActiveRoomStore = function (mozL10n) {
roomName: null,
// True when sharing screen has been paused.
streamPaused: false,
// Social API state.
socialShareProviders: null,
// True if media has been connected both-ways.
mediaConnected: false,
// True if a chat message was sent or received during a session.
@ -273,7 +270,6 @@ loop.store.ActiveRoomStore = function (mozL10n) {
"startBrowserShare",
"endScreenShare",
"toggleBrowserSharing",
"updateSocialShareInfo",
"connectionStatus",
"mediaConnected",
"videoScreenStreamChanged"];
@ -288,13 +284,11 @@ loop.store.ActiveRoomStore = function (mozL10n) {
this._onUpdateListener = this._handleRoomUpdate.bind(this);
this._onDeleteListener = this._handleRoomDelete.bind(this);
this._onSocialShareUpdate = this._handleSocialShareUpdate.bind(this);
var roomToken = this._storeState.roomToken;
loop.request("Rooms:PushSubscription", ["delete:" + roomToken, "update:" + roomToken]);
loop.subscribe("Rooms:Delete:" + roomToken, this._handleRoomDelete.bind(this));
loop.subscribe("Rooms:Update:" + roomToken, this._handleRoomUpdate.bind(this));
loop.subscribe("SocialProvidersChanged", this._onSocialShareUpdate);},
loop.subscribe("Rooms:Update:" + roomToken, this._handleRoomUpdate.bind(this));},
/**
@ -320,16 +314,12 @@ loop.store.ActiveRoomStore = function (mozL10n) {
this._registerPostSetupActions();
// Get the window data from the Loop API.
return loop.requestMulti(
["Rooms:Get", actionData.roomToken],
["GetSocialShareProviders"]).
then(function (results) {
var room = results[0];
var socialShareProviders = results[1];
return loop.request("Rooms:Get", actionData.roomToken).then(function (result) {
var room = result;
if (room.isError) {
if (result.isError) {
this.dispatchAction(new sharedActions.RoomFailure({
error: room,
error: result,
failedJoinRequest: false }));
return;}
@ -341,8 +331,7 @@ loop.store.ActiveRoomStore = function (mozL10n) {
roomDescription: room.decryptedContext.description,
roomName: room.decryptedContext.roomName,
roomState: ROOM_STATES.READY,
roomUrl: room.roomUrl,
socialShareProviders: socialShareProviders }));
roomUrl: room.roomUrl }));
// For the conversation window, we need to automatically join the room.
@ -548,18 +537,6 @@ loop.store.ActiveRoomStore = function (mozL10n) {
/**
* Handles the updateSocialShareInfo action. Updates the room data with new
* Social API info.
*
* @param {sharedActions.UpdateSocialShareInfo} actionData
*/
updateSocialShareInfo: function updateSocialShareInfo(actionData) {
this.setStoreState({
socialShareProviders: actionData.socialShareProviders });},
/**
* Handles room updates notified by the Loop rooms API.
*
@ -585,18 +562,6 @@ loop.store.ActiveRoomStore = function (mozL10n) {
/**
* Handles an update of the position of the Share widget and changes to list
* of Social API providers, notified by the Loop API.
*/
_handleSocialShareUpdate: function _handleSocialShareUpdate() {
loop.request("GetSocialShareProviders").then(function (result) {
this.dispatchAction(new sharedActions.UpdateSocialShareInfo({
socialShareProviders: result }));}.
bind(this));},
/**
* Checks that there are audio and video devices available, and joins the
* room if there are. If there aren't then it will dispatch a ConnectionFailure
@ -751,9 +716,6 @@ loop.store.ActiveRoomStore = function (mozL10n) {
this._setRefreshTimeout(actionData.expires);
// Only send media telemetry on one side of the call: the desktop side.
actionData.sendTwoWayMediaTelemetry = this._isDesktop;
this._sdkDriver.connectSession(actionData);
loop.request("AddConversationContext", this._storeState.windowId,
@ -1161,10 +1123,6 @@ loop.store.ActiveRoomStore = function (mozL10n) {
return;}
if (loop.standaloneMedia) {
loop.standaloneMedia.multiplexGum.reset();}
if (this._browserSharingListener) {
// Remove the browser sharing listener as we don't need it now.
loop.unsubscribe("BrowserSwitch", this._browserSharingListener);
@ -1263,10 +1221,8 @@ loop.store.ActiveRoomStore = function (mozL10n) {
// There's no need to listen to these actions anymore.
this.dispatcher.unregister(this, [
"receivedTextChatMessage",
"sendTextChatMessage"]);
"sendTextChatMessage"]);},
// Ping telemetry of this session with successful message(s) exchange.
loop.request("TelemetryAddValue", "LOOP_ROOM_SESSION_WITHCHAT", 1);},
/**

View File

@ -78,7 +78,9 @@ var loop = loop || {};
// These functions should only be used in unit tests.
loop.request.inspect = function () {return _.extend({}, gListenersMap);};
loop.request.inspect = function () {
return _.extend({}, gListenersMap);};
loop.request.reset = function () {
gListeningForMessages = false;
gListenersMap = {};};
@ -187,7 +189,9 @@ var loop = loop || {};
// These functions should only be used in unit tests.
loop.subscribe.inspect = function () {return _.extend({}, gSubscriptionsMap);};
loop.subscribe.inspect = function () {
return _.extend({}, gSubscriptionsMap);};
loop.subscribe.reset = function () {
gListeningForPushMessages = false;
gSubscriptionsMap = {};};

View File

@ -45,15 +45,6 @@ loop.OTSdkDriver = function () {
"toggleBrowserSharing"]);
// Set loop.debug.twoWayMediaTelemetry to true in the browser
// by changing the hidden pref loop.debug.twoWayMediaTelemetry using
// about:config, or use
//
// localStorage.setItem("debug.twoWayMediaTelemetry", true);
loop.shared.utils.getBoolPreference("debug.twoWayMediaTelemetry", function (enabled) {
this._debugTwoWayMediaTelemetry = enabled;}.
bind(this));
// Set loop.debug.sdk to true in the browser, or in standalone:
// localStorage.setItem("debug.sdk", true);
loop.shared.utils.getBoolPreference("debug.sdk", function (enabled) {
@ -260,20 +251,12 @@ loop.OTSdkDriver = function () {
* - sessionId: The OT session ID
* - apiKey: The OT API key
* - sessionToken: The token for the OT session
* - sendTwoWayMediaTelemetry: boolean should we send telemetry on length
* of media sessions. Callers should ensure
* that this is only set for one side of the
* session so that things don't get
* double-counted.
*
* @param {Object} sessionData The session data for setting up the OT session.
*/
connectSession: function connectSession(sessionData) {
this.session = this.sdk.initSession(sessionData.sessionId);
this._sendTwoWayMediaTelemetry = !!sessionData.sendTwoWayMediaTelemetry;
this._setTwoWayMediaStartTime(this.CONNECTION_START_TIME_UNINITIALIZED);
this.session.on("sessionDisconnected",
this._onSessionDisconnected.bind(this));
this.session.on("connectionCreated", this._onConnectionCreated.bind(this));
@ -324,8 +307,6 @@ loop.OTSdkDriver = function () {
// Now reset the metrics as well.
this._resetMetrics();
this._noteConnectionLengthIfNeeded(this._getTwoWayMediaStartTime(), performance.now());
// Also, tidy these variables ready for next time.
delete this._sessionConnected;
delete this._publisherReady;
@ -334,8 +315,7 @@ loop.OTSdkDriver = function () {
delete this._mockPublisherEl;
delete this._publisherChannel;
delete this._subscriberChannel;
this.connections = {};
this._setTwoWayMediaStartTime(this.CONNECTION_START_TIME_UNINITIALIZED);},
this.connections = {};},
/**
@ -407,8 +387,6 @@ loop.OTSdkDriver = function () {
this._notifyMetricsEvent("Session.connectionDestroyed", "peer");
this._noteConnectionLengthIfNeeded(this._getTwoWayMediaStartTime(), performance.now());
this.dispatcher.dispatch(new sharedActions.RemotePeerDisconnected({
peerHungup: event.reason === "clientDisconnected" }));},
@ -435,8 +413,6 @@ loop.OTSdkDriver = function () {
return;}
this._noteConnectionLengthIfNeeded(this._getTwoWayMediaStartTime(),
performance.now());
this._notifyMetricsEvent("Session." + event.reason);
this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
reason: reason }));},
@ -526,6 +502,8 @@ loop.OTSdkDriver = function () {
break;
case "Session.networkDisconnected":
case "Session.forceDisconnected":
case "Session.subscribeCompleted":
case "Session.screen.subscribeCompleted":
break;
default:
// We don't want unexpected events being sent to the server, so
@ -646,9 +624,9 @@ loop.OTSdkDriver = function () {
srcMediaElement: sdkSubscriberVideo }));
this._notifyMetricsEvent("Session.subscribeCompleted");
this._subscribedRemoteStream = true;
if (this._checkAllStreamsConnected()) {
this._setTwoWayMediaStartTime(performance.now());
this.dispatcher.dispatch(new sharedActions.MediaConnected());}
@ -677,9 +655,10 @@ loop.OTSdkDriver = function () {
// _handleRemoteScreenShareCreated. Maybe these should be separate
// actions. But even so, this shouldn't be necessary....
this.dispatcher.dispatch(new sharedActions.ReceivingScreenShare({
receiving: true, srcMediaElement: sdkSubscriberVideo }));},
receiving: true, srcMediaElement: sdkSubscriberVideo }));
this._notifyMetricsEvent("Session.screen.subscribeCompleted");},
/**
@ -873,57 +852,6 @@ loop.OTSdkDriver = function () {
/**
* Implementation detail, may be set to one of the CONNECTION_START_TIME
* constants, or a positive integer in milliseconds.
*
* @private
*/
__twoWayMediaStartTime: undefined,
/**
* Used as a guard to make sure we don't inadvertently use an
* uninitialized value.
*/
CONNECTION_START_TIME_UNINITIALIZED: -1,
/**
* Use as a guard to ensure that we don't note any bidirectional sessions
* twice.
*/
CONNECTION_START_TIME_ALREADY_NOTED: -2,
/**
* Set and get the start time of the two-way media connection. These
* are done as wrapper functions so that we can log sets to make manual
* verification of various telemetry scenarios possible. The get API is
* analogous in order to follow the principle of least surprise for
* people consuming this code.
*
* If this._sendTwoWayMediaTelemetry is not true, returns immediately
* without making any changes, since this data is not used, and it makes
* reading the logs confusing for manual verification of both ends of the
* call in the same browser, which is a case we care about.
*
* @param start start time in milliseconds, as returned by
* performance.now()
* @private
*/
_setTwoWayMediaStartTime: function _setTwoWayMediaStartTime(start) {
if (!this._sendTwoWayMediaTelemetry) {
return;}
this.__twoWayMediaStartTime = start;
if (this._debugTwoWayMediaTelemetry) {
console.log("Loop Telemetry: noted two-way connection start, " +
"start time in ms:", start);}},
_getTwoWayMediaStartTime: function _getTwoWayMediaStartTime() {
return this.__twoWayMediaStartTime;},
/**
* Handles the event when the remote stream is destroyed.
*
@ -1050,13 +978,18 @@ loop.OTSdkDriver = function () {
* @param {OT.Event} event
*/
_onOTException: function _onOTException(event) {
var baseException = "sdk.exception.";
if (event.target && event.target === this.screenshare) {
baseException += "screen.";}
switch (event.code) {
case OT.ExceptionCodes.PUBLISHER_ICE_WORKFLOW_FAILED:
case OT.ExceptionCodes.SUBSCRIBER_ICE_WORKFLOW_FAILED:
this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
reason: FAILURE_DETAILS.ICE_FAILED }));
this._notifyMetricsEvent("sdk.exception." + event.code);
this._notifyMetricsEvent(baseException + event.code);
break;
case OT.ExceptionCodes.TERMS_OF_SERVICE_FAILURE:
this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
@ -1064,21 +997,17 @@ loop.OTSdkDriver = function () {
// We still need to log the exception so that the server knows why this
// attempt failed.
this._notifyMetricsEvent("sdk.exception." + event.code);
this._notifyMetricsEvent(baseException + event.code);
break;
case OT.ExceptionCodes.UNABLE_TO_PUBLISH:
// Don't report errors for GetUserMedia events as these are expected if
// the user denies the prompt.
if (event.message !== "GetUserMedia") {
var baseException = "sdk.exception.";
if (event.target && event.target === this.screenshare) {
baseException += "screen.";}
this._notifyMetricsEvent(baseException + event.code + "." + event.message);}
break;
default:
this._notifyMetricsEvent("sdk.exception." + event.code);
this._notifyMetricsEvent(baseException + event.code);
break;}},
@ -1150,7 +1079,6 @@ loop.OTSdkDriver = function () {
// Now record the fact, and check if we've got all media yet.
this._publishedLocalStream = true;
if (this._checkAllStreamsConnected()) {
this._setTwoWayMediaStartTime(performance.now());
this.dispatcher.dispatch(new sharedActions.MediaConnected());}}},
@ -1215,92 +1143,8 @@ loop.OTSdkDriver = function () {
* Called when a screenshare stream is published.
*/
_onScreenShareStreamCreated: function _onScreenShareStreamCreated() {
this._notifyMetricsEvent("Publisher.streamCreated");},
this._notifyMetricsEvent("Publisher.streamCreated");} };
/*
* XXX all of the bi-directional media connection telemetry stuff in this
* file, (much, but not all, of it is below) should be hoisted into its
* own object for maintainability and clarity, also in part because this
* stuff only wants to run one side of the connection, not both (tracked
* by bug 1145237).
*/
/**
* A hook exposed only for the use of the functional tests so that
* they can check that the bi-directional media count is being updated
* correctly.
*
* @type number
* @private
*/
_connectionLengthNotedCalls: 0,
/**
* Wrapper for adding a keyed value that also updates
* connectionLengthNoted calls and sets the twoWayMediaStartTime to
* this.CONNECTION_START_TIME_ALREADY_NOTED.
*
* @param {number} callLengthSeconds the call length in seconds
* @private
*/
_noteConnectionLength: function _noteConnectionLength(callLengthSeconds) {
var buckets = this._constants.TWO_WAY_MEDIA_CONN_LENGTH;
var bucket = buckets.SHORTER_THAN_10S;
if (callLengthSeconds >= 10 && callLengthSeconds <= 30) {
bucket = buckets.BETWEEN_10S_AND_30S;} else
if (callLengthSeconds > 30 && callLengthSeconds <= 300) {
bucket = buckets.BETWEEN_30S_AND_5M;} else
if (callLengthSeconds > 300) {
bucket = buckets.MORE_THAN_5M;}
loop.request("TelemetryAddValue", "LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1", bucket);
this._setTwoWayMediaStartTime(this.CONNECTION_START_TIME_ALREADY_NOTED);
this._connectionLengthNotedCalls++;
if (this._debugTwoWayMediaTelemetry) {
console.log("Loop Telemetry: noted two-way media connection " +
"in bucket: ", bucket);}},
/**
* Note connection length if it's valid (the startTime has been initialized
* and is not later than endTime) and not yet already noted. If
* this._sendTwoWayMediaTelemetry is not true, we return immediately.
*
* @param {number} startTime in milliseconds
* @param {number} endTime in milliseconds
* @private
*/
_noteConnectionLengthIfNeeded: function _noteConnectionLengthIfNeeded(startTime, endTime) {
if (!this._sendTwoWayMediaTelemetry) {
return;}
if (startTime === this.CONNECTION_START_TIME_ALREADY_NOTED ||
startTime === this.CONNECTION_START_TIME_UNINITIALIZED ||
startTime > endTime) {
if (this._debugTwoWayMediaTelemetry) {
console.log("_noteConnectionLengthIfNeeded called with " +
" invalid params, either the calls were never" +
" connected or there is a bug; startTime:", startTime,
"endTime:", endTime);}
return;}
var callLengthSeconds = (endTime - startTime) / 1000;
this._noteConnectionLength(callLengthSeconds);},
/**
* If set to true, make it easy to test/verify 2-way media connection
* telemetry code operation by viewing the logs.
*/
_debugTwoWayMediaTelemetry: false };
return OTSdkDriver;}();

View File

@ -217,7 +217,10 @@ loop.shared.views.chat = function (mozL10n) {
this.props.messageList.map(function (entry, i) {
if (entry.type === CHAT_MESSAGE_TYPES.SPECIAL) {
if (!this.props.showInitialContext) {return null;}
if (!this.props.showInitialContext) {
return null;}
switch (entry.contentType) {
case CHAT_CONTENT_TYPES.CONTEXT:
return (

View File

@ -13,8 +13,7 @@ describe("loop.store.ActiveRoomStore", function () {
var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES;
var ROOM_INFO_FAILURES = loop.shared.utils.ROOM_INFO_FAILURES;
var sandbox, dispatcher, store, requestStubs, fakeSdkDriver, fakeMultiplexGum;
var standaloneMediaRestore;
var sandbox, dispatcher, store, requestStubs, fakeSdkDriver;
var clock;
beforeEach(function () {
@ -38,7 +37,6 @@ describe("loop.store.ActiveRoomStore", function () {
"Rooms:PushSubscription": sinon.stub(),
SetScreenShareState: sinon.stub(),
GetActiveTabWindowId: sandbox.stub().returns(42),
GetSocialShareProviders: sinon.stub().returns([]),
TelemetryAddValue: sinon.stub() });
@ -56,15 +54,6 @@ describe("loop.store.ActiveRoomStore", function () {
endScreenShare: sinon.stub().returns(true) };
fakeMultiplexGum = {
reset: sandbox.spy() };
standaloneMediaRestore = loop.standaloneMedia;
loop.standaloneMedia = {
multiplexGum: fakeMultiplexGum };
store = new loop.store.ActiveRoomStore(dispatcher, {
sdkDriver: fakeSdkDriver });
@ -76,8 +65,7 @@ describe("loop.store.ActiveRoomStore", function () {
afterEach(function () {
sandbox.restore();
LoopMochaUtils.restore();
loop.standaloneMedia = standaloneMediaRestore;});
LoopMochaUtils.restore();});
describe("#constructor", function () {
@ -182,15 +170,6 @@ describe("loop.store.ActiveRoomStore", function () {
expect(store._storeState.failureReason).eql(FAILURE_DETAILS.EXPIRED_OR_INVALID);});
it("should reset the multiplexGum", function () {
store.roomFailure(new sharedActions.RoomFailure({
error: fakeError,
failedJoinRequest: false }));
sinon.assert.calledOnce(fakeMultiplexGum.reset);});
it("should disconnect from the servers via the sdk", function () {
store.roomFailure(new sharedActions.RoomFailure({
error: fakeError,
@ -370,8 +349,7 @@ describe("loop.store.ActiveRoomStore", function () {
participants: [],
roomName: fakeRoomData.decryptedContext.roomName,
roomState: ROOM_STATES.READY,
roomUrl: fakeRoomData.roomUrl,
socialShareProviders: [] }));});});
roomUrl: fakeRoomData.roomUrl }));});});
@ -806,28 +784,6 @@ describe("loop.store.ActiveRoomStore", function () {
describe("#updateSocialShareInfo", function () {
var fakeSocialShareInfo;
beforeEach(function () {
fakeSocialShareInfo = {
socialShareProviders: [{
name: "foo",
origin: "https://example.com",
iconURL: "icon.png" }] };});
it("should save the Social API information", function () {
store.updateSocialShareInfo(new sharedActions.UpdateSocialShareInfo(fakeSocialShareInfo));
var state = store.getStoreState();
expect(state.socialShareProviders).
eql(fakeSocialShareInfo.socialShareProviders);});});
describe("#joinRoom", function () {
var hasDevicesStub;
@ -1128,28 +1084,6 @@ describe("loop.store.ActiveRoomStore", function () {
actionData);});
it("should pass 'sendTwoWayMediaTelemetry' as true to connectSession if " +
"store._isDesktop is true", function () {
store._isDesktop = true;
store.joinedRoom(new sharedActions.JoinedRoom(fakeJoinedData));
sinon.assert.calledOnce(fakeSdkDriver.connectSession);
sinon.assert.calledWithMatch(fakeSdkDriver.connectSession,
sinon.match.has("sendTwoWayMediaTelemetry", true));});
it("should pass 'sendTwoWayTelemetry' as false to connectionSession if " +
"store._isDesktop is false", function () {
store._isDesktop = false;
store.joinedRoom(new sharedActions.JoinedRoom(fakeJoinedData));
sinon.assert.calledOnce(fakeSdkDriver.connectSession);
sinon.assert.calledWithMatch(fakeSdkDriver.connectSession,
sinon.match.has("sendTwoWayMediaTelemetry", false));});
it("should call LoopAPI.AddConversationContext", function () {
var actionData = new sharedActions.JoinedRoom(fakeJoinedData);
@ -1245,12 +1179,6 @@ describe("loop.store.ActiveRoomStore", function () {
expect(store.getStoreState().failureReason).eql("FAIL");});
it("should reset the multiplexGum", function () {
store.connectionFailure(connectionFailureAction);
sinon.assert.calledOnce(fakeMultiplexGum.reset);});
it("should disconnect from the servers via the sdk", function () {
store.connectionFailure(connectionFailureAction);
@ -1312,7 +1240,6 @@ describe("loop.store.ActiveRoomStore", function () {
store.connectionFailure(connectionFailureAction);
sinon.assert.notCalled(fakeMultiplexGum.reset);
sinon.assert.notCalled(fakeSdkDriver.disconnectSession);});});
@ -1958,12 +1885,6 @@ describe("loop.store.ActiveRoomStore", function () {
sinon.assert.calledWithExactly(requestStubs.SetScreenShareState, "1234", false);});
it("should reset the multiplexGum", function () {
store.windowUnload();
sinon.assert.calledOnce(fakeMultiplexGum.reset);});
it("should disconnect from the servers via the sdk", function () {
store.windowUnload();
@ -2027,12 +1948,6 @@ describe("loop.store.ActiveRoomStore", function () {
it("should reset the multiplexGum", function () {
store.leaveRoom();
sinon.assert.calledOnce(fakeMultiplexGum.reset);});
it("should disconnect from the servers via the sdk", function () {
store.leaveRoom();
@ -2129,24 +2044,6 @@ describe("loop.store.ActiveRoomStore", function () {
describe("#_handleSocialShareUpdate", function () {
it("should dispatch an UpdateRoomInfo action", function () {
store._handleSocialShareUpdate();
sinon.assert.calledOnce(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.UpdateSocialShareInfo({
socialShareProviders: [] }));});
it("should call respective mozLoop methods", function () {
store._handleSocialShareUpdate();
sinon.assert.calledOnce(requestStubs.GetSocialShareProviders);});});
describe("#_handleTextChatMessage", function () {
beforeEach(function () {
var fakeRoomData = {
@ -2204,22 +2101,7 @@ describe("loop.store.ActiveRoomStore", function () {
sentTimestamp: "1970-01-01T00:00:00.000Z" }));
assertWeDidNothing();});
it("should ping telemetry when a chat message arrived or is to be sent", function () {
store._handleTextChatMessage(new sharedActions.ReceivedTextChatMessage({
contentType: CHAT_CONTENT_TYPES.TEXT,
message: "Hello!",
receivedTimestamp: "1970-01-01T00:00:00.000Z" }));
sinon.assert.calledOnce(requestStubs.TelemetryAddValue);
sinon.assert.calledWithExactly(requestStubs.TelemetryAddValue,
"LOOP_ROOM_SESSION_WITHCHAT", 1);
expect(store.getStoreState().chatMessageExchanged).eql(true);
expect(dispatcher._eventData.hasOwnProperty("receivedTextChatMessage")).eql(false);
expect(dispatcher._eventData.hasOwnProperty("sendTextChatMessage")).eql(false);});});
assertWeDidNothing();});});

View File

@ -13,7 +13,7 @@ describe("loop.OTSdkDriver", function () {
var CURSOR_MESSAGE_TYPES = loop.shared.utils.CURSOR_MESSAGE_TYPES;
var sandbox, constants;
var dispatcher, driver, requestStubs, publisher, screenshare, sdk, session;
var dispatcher, driver, publisher, screenshare, sdk, session;
var sessionData, subscriber, publisherConfig, fakeEvent;
beforeEach(function () {
@ -31,11 +31,6 @@ describe("loop.OTSdkDriver", function () {
sessionToken: "1357924680" };
LoopMochaUtils.stubLoopRequest(requestStubs = {
TelemetryAddValue: sinon.stub(),
GetLoopPref: sinon.stub() });
dispatcher = new loop.Dispatcher();
sandbox.stub(dispatcher, "dispatch");
@ -84,12 +79,6 @@ describe("loop.OTSdkDriver", function () {
constants = {
TWO_WAY_MEDIA_CONN_LENGTH: {
SHORTER_THAN_10S: 0,
BETWEEN_10S_AND_30S: 1,
BETWEEN_30S_AND_5M: 2,
MORE_THAN_5M: 3 },
SHARING_STATE_CHANGE: {
WINDOW_ENABLED: 0,
WINDOW_DISABLED: 1,
@ -144,23 +133,6 @@ describe("loop.OTSdkDriver", function () {
it("should enable debug for two way media telemetry if required", function () {
// Simulate the pref being enabled.
sandbox.stub(loop.shared.utils, "getBoolPreference", function (prefName, callback) {
if (prefName === "debug.twoWayMediaTelemetry") {
callback(true);}});
driver = new loop.OTSdkDriver({
constants: constants,
dispatcher: dispatcher,
sdk: sdk });
expect(driver._debugTwoWayMediaTelemetry).eql(true);});
it("should enable debug on the sdk if required", function () {
// Simulate the pref being enabled.
sandbox.stub(loop.shared.utils, "getBoolPreference", function (prefName, callback) {
@ -446,15 +418,6 @@ describe("loop.OTSdkDriver", function () {
sinon.assert.calledWith(session.connect, "1234567890", "1357924680");});
it("should set the two-way media start time to 'uninitialized' " +
"when sessionData.sendTwoWayMediaTelemetry is true'", function () {
driver.connectSession(_.extend(sessionData,
{ sendTwoWayMediaTelemetry: true }));
expect(driver._getTwoWayMediaStartTime()).to.eql(
driver.CONNECTION_START_TIME_UNINITIALIZED);});
describe("On connection complete", function () {
beforeEach(function () {
sandbox.stub(window.console, "error");});
@ -637,109 +600,7 @@ describe("loop.OTSdkDriver", function () {
driver.disconnectSession();
sinon.assert.calledOnce(publisher.destroy);});
it("should call _noteConnectionLengthIfNeeded with connection duration", function () {
driver.session = session;
var startTime = 1;
var endTime = 3;
driver._sendTwoWayMediaTelemetry = true;
driver._setTwoWayMediaStartTime(startTime);
sandbox.stub(performance, "now").returns(endTime);
sandbox.stub(driver, "_noteConnectionLengthIfNeeded");
driver.disconnectSession();
sinon.assert.calledWith(driver._noteConnectionLengthIfNeeded, startTime,
endTime);});
it("should reset the two-way media connection start time", function () {
driver.session = session;
var startTime = 1;
driver._sendTwoWayMediaTelemetry = true;
driver._setTwoWayMediaStartTime(startTime);
sandbox.stub(performance, "now");
sandbox.stub(driver, "_noteConnectionLengthIfNeeded");
driver.disconnectSession();
expect(driver._getTwoWayMediaStartTime()).to.eql(
driver.CONNECTION_START_TIME_UNINITIALIZED);});});
describe("#_noteConnectionLengthIfNeeded", function () {
var startTimeMS;
beforeEach(function () {
startTimeMS = 1;
driver._sendTwoWayMediaTelemetry = true;
driver._setTwoWayMediaStartTime(startTimeMS);});
it("should set two-way media start time to CONNECTION_START_TIME_ALREADY_NOTED", function () {
var endTimeMS = 3;
driver._noteConnectionLengthIfNeeded(startTimeMS, endTimeMS);
expect(driver._getTwoWayMediaStartTime()).to.eql(
driver.CONNECTION_START_TIME_ALREADY_NOTED);});
it("should record telemetry with SHORTER_THAN_10S for calls less than 10s", function () {
var endTimeMS = 9000;
driver._noteConnectionLengthIfNeeded(startTimeMS, endTimeMS);
sinon.assert.calledOnce(requestStubs.TelemetryAddValue);
sinon.assert.calledWith(requestStubs.TelemetryAddValue,
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1",
constants.TWO_WAY_MEDIA_CONN_LENGTH.SHORTER_THAN_10S);});
it("should call record telemetry with BETWEEN_10S_AND_30S for 15s calls",
function () {
var endTimeMS = 15000;
driver._noteConnectionLengthIfNeeded(startTimeMS, endTimeMS);
sinon.assert.calledOnce(requestStubs.TelemetryAddValue);
sinon.assert.calledWith(requestStubs.TelemetryAddValue,
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1",
constants.TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_10S_AND_30S);});
it("should call record telemetry with BETWEEN_30S_AND_5M for 60s calls",
function () {
var endTimeMS = 60 * 1000;
driver._noteConnectionLengthIfNeeded(startTimeMS, endTimeMS);
sinon.assert.calledOnce(requestStubs.TelemetryAddValue);
sinon.assert.calledWith(requestStubs.TelemetryAddValue,
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1",
constants.TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_30S_AND_5M);});
it("should call record telemetry with MORE_THAN_5M for 10m calls", function () {
var endTimeMS = 10 * 60 * 1000;
driver._noteConnectionLengthIfNeeded(startTimeMS, endTimeMS);
sinon.assert.calledOnce(requestStubs.TelemetryAddValue);
sinon.assert.calledWith(requestStubs.TelemetryAddValue,
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1",
constants.TWO_WAY_MEDIA_CONN_LENGTH.MORE_THAN_5M);});
it("should not call record telemetry if driver._sendTwoWayMediaTelemetry is false",
function () {
var endTimeMS = 10 * 60 * 1000;
driver._sendTwoWayMediaTelemetry = false;
driver._noteConnectionLengthIfNeeded(startTimeMS, endTimeMS);
sinon.assert.notCalled(requestStubs.TelemetryAddValue);});});
sinon.assert.calledOnce(publisher.destroy);});});
@ -919,27 +780,10 @@ describe("loop.OTSdkDriver", function () {
state: "waiting",
connections: 0,
sendStreams: 0,
recvStreams: 0 }));});
recvStreams: 0 }));});});
it("should call _noteConnectionLengthIfNeeded with connection duration", function () {
driver.session = session;
var startTime = 1;
var endTime = 3;
driver._sendTwoWayMediaTelemetry = true;
driver._setTwoWayMediaStartTime(startTime);
sandbox.stub(performance, "now").returns(endTime);
sandbox.stub(driver, "_noteConnectionLengthIfNeeded");
session.trigger("connectionDestroyed", {
reason: "clientDisconnected" });
sinon.assert.calledWith(driver._noteConnectionLengthIfNeeded, startTime,
endTime);});});
describe("sessionDisconnected", function () {
it("should notify metrics", function () {
@ -981,25 +825,7 @@ describe("loop.OTSdkDriver", function () {
sinon.assert.calledWithMatch(dispatcher.dispatch,
sinon.match.hasOwn("name", "connectionFailure"));
sinon.assert.calledWithMatch(dispatcher.dispatch,
sinon.match.hasOwn("reason", FAILURE_DETAILS.EXPIRED_OR_INVALID));});
it("should call _noteConnectionLengthIfNeeded with connection duration", function () {
driver.session = session;
var startTime = 1;
var endTime = 3;
driver._sendTwoWayMediaTelemetry = true;
driver._setTwoWayMediaStartTime(startTime);
sandbox.stub(performance, "now").returns(endTime);
sandbox.stub(driver, "_noteConnectionLengthIfNeeded");
session.trigger("sessionDisconnected", {
reason: "networkDisconnected" });
sinon.assert.calledWith(driver._noteConnectionLengthIfNeeded, startTime,
endTime);});});
sinon.match.hasOwn("reason", FAILURE_DETAILS.EXPIRED_OR_INVALID));});});
@ -1166,29 +992,23 @@ describe("loop.OTSdkDriver", function () {
new sharedActions.MediaConnected({}));});
it("should store the start time when both streams are up and" +
" driver._sendTwoWayMediaTelemetry is true", function () {
driver._sendTwoWayMediaTelemetry = true;
it("should dispatch a connectionStatus action if both streams are up", function () {
driver._publishedLocalStream = true;
var startTime = 1;
sandbox.stub(performance, "now").returns(startTime);
session.trigger("streamCreated", { stream: fakeStream });
expect(driver._getTwoWayMediaStartTime()).to.eql(startTime);});
// Called twice due to the VideoDimensionsChanged above.
sinon.assert.called(dispatcher.dispatch);
sinon.assert.calledWithMatch(dispatcher.dispatch,
new sharedActions.ConnectionStatus({
event: "Session.subscribeCompleted",
state: "receiving",
// Local stream connection is faked, so connections/sendStreams=0.
connections: 0,
sendStreams: 0,
recvStreams: 1 }));});
it("should not store the start time when both streams are up and" +
" driver._isDesktop is false", function () {
driver._isDesktop = false;
driver._publishedLocalStream = true;
var startTime = 73;
sandbox.stub(performance, "now").returns(startTime);
session.trigger("streamCreated", { stream: fakeStream });
expect(driver._getTwoWayMediaStartTime()).to.not.eql(startTime);});
describe("Data channel setup", function () {
var fakeChannel;
@ -1365,7 +1185,45 @@ describe("loop.OTSdkDriver", function () {
// Called twice due to the VideoDimensionsChanged above.
sinon.assert.called(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.ReceivingScreenShare({ receiving: true }));});});});
new sharedActions.ReceivingScreenShare({ receiving: true }));});
describe("screen share subscribe completed", function () {
beforeEach(function () {
fakeStream.videoType = "screen";
session.subscribe.yieldsOn(driver, null, fakeSubscriberObject,
videoElement).returns(this.fakeSubscriberObject);});
it("should dispatch ReceivingScreenShare on completion", function () {
fakeStream.connection = fakeConnection;
fakeStream.hasVideo = false;
session.trigger("streamCreated", { stream: fakeStream });
sinon.assert.called(dispatcher.dispatch);
sinon.assert.calledWithExactly(dispatcher.dispatch,
new sharedActions.ReceivingScreenShare({
receiving: true,
srcMediaElement: videoElement }));});
it("should dispatch a connectionStatus action", function () {
session.trigger("streamCreated", { stream: fakeStream });
// Called twice due to the VideoDimensionsChanged above.
sinon.assert.called(dispatcher.dispatch);
sinon.assert.calledWithMatch(dispatcher.dispatch,
new sharedActions.ConnectionStatus({
event: "Session.screen.subscribeCompleted",
state: "receiving",
connections: 0,
sendStreams: 0,
recvStreams: 1 }));});});});});

View File

@ -261,6 +261,15 @@ body {
#mocha-stats .progress {
float: right;
padding-top: 0;
/**
* Set safe initial values, so mochas .progress does not inherit these
* properties from Bootstrap .progress (which causes .progress height to
* equal line height set in Bootstrap).
*/
height: auto;
box-shadow: none;
background-color: initial;
}
#mocha-stats em {

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/**
* ReactDOMServer v15.0.2
* ReactDOMServer v15.1.0
*
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.

View File

@ -1,5 +1,5 @@
/**
* ReactDOM v15.0.2
* ReactDOM v15.1.0
*
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.

View File

@ -1,5 +1,5 @@
/**
* ReactDOM v15.0.2
* ReactDOM v15.1.0
*
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -262,6 +262,7 @@ rooms_room_joined_owner_not_connected_label=El to collaciu ta esperando pa resto
peer_left_session=El to collaciu coló.
peer_unexpected_quit=El to collaciu desconeutóse de mou inesperáu.
peer_join_session=Xunióse'l to collaciu.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -267,6 +267,7 @@ self_view_hidden_message=Özünü göstərmə gizlədilib amma hələ də gönd
peer_left_session=Yoldaşınız çıxdı.
peer_unexpected_quit=Yoldaşınız gözlənilmədən ayrıldı.
peer_join_session=Yoldaşınız qoşuldu.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -7,6 +7,8 @@
## LOCALIZATION_NOTE(loopMenuItem_label): Label of the menu item that is placed
## inside the browser 'Tools' menu. Use the unicode ellipsis char, \u2026, or
## use "..." if \u2026 doesn't suit traditions in your locale.
loopMenuItem_label=Inicia una conversa…
loopMenuItem_accesskey=I
## LOCALIZATION_NOTE(sign_in_again_title_line_one, sign_in_again_title_line_two2):
## These are displayed together at the top of the panel when a user is needed to
@ -14,9 +16,13 @@
## and this is displayed in slightly larger font. Please arrange as necessary for
## your locale.
## {{clientShortname2}} will be replaced by the brand name for either string.
sign_in_again_title_line_one=Torneu a iniciar la sessió
sign_in_again_button=Inicia la sessió
## LOCALIZATION_NOTE(sign_in_again_use_as_guest_button2): {{clientSuperShortname}}
## will be replaced by the super short brandname.
panel_browse_with_friend_button=Navega per aquesta pàgina amb un amic
panel_disconnect_button=Desconnecta
## LOCALIZATION_NOTE(first_time_experience_subheading2, first_time_experience_subheading_button_above): Message inviting the
## user to create his or her first conversation.
@ -39,6 +45,10 @@
## LOCALIZATION_NOTE(invite_copy_link_button, invite_copied_link_button,
## invite_email_link_button, invite_facebook_button2): These labels appear under
## an iconic button for the invite view.
invite_copy_link_button=Copia l'enllaç
invite_copied_link_button=S'ha copiat
invite_email_link_button=Envia l'enllaç per correu
invite_facebook_button3=Facebook
# Error bars
## LOCALIZATION NOTE(session_expired_error_description,could_not_authenticate,password_changed_question,try_again_later,could_not_connect,check_internet_connection,login_expired,service_not_available,problem_accessing_account):

View File

@ -114,8 +114,8 @@ settings_menu_item_account=Účet
settings_menu_item_settings=Nastavení
settings_menu_item_signout=Odhlásit
settings_menu_item_signin=Přihlásit
settings_menu_item_turnnotificationson=Zapnout upozorně
settings_menu_item_turnnotificationsoff=Vypnout upozorně
settings_menu_item_turnnotificationson=Zapnout oznáme
settings_menu_item_turnnotificationsoff=Vypnout oznáme
settings_menu_item_feedback=Odeslat zpětnou vazbu
settings_menu_button_tooltip=Nastavení
@ -268,6 +268,7 @@ self_view_hidden_message=Váš obraz byl skryt, ale je nadále odesílán; pro j
peer_left_session=Váš přítel odešel.
peer_unexpected_quit=Váš přítel se nečekaně odpojil.
peer_join_session=Váš přítel se připojil.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -29,12 +29,12 @@ panel_disconnect_button=Datgysylltu
## LOCALIZATION_NOTE(first_time_experience_subheading2, first_time_experience_subheading_button_above): Message inviting the
## user to create his or her first conversation.
first_time_experience_subheading2=Cliciwch y botwm Helo i bori drwy'r tudalennau gwe gyda ffrind.
first_time_experience_subheading_button_above=Cliciwch ar y botwn uchod er mwyn pori tudalennau gwe gyda ffrind.
first_time_experience_subheading_button_above=Cliciwch ar y botwm uchod er mwyn pori tudalennau gwe gyda ffrind.
## LOCALIZATION_NOTE(first_time_experience_content, first_time_experience_content2): Message describing
## ways to use Hello project.
first_time_experience_content=Ei ddefnyddio i gynllunio gyda'n gilydd, gweithio gyda'n gilydd, chwerthin gyda'n gilydd.
first_time_experience_content2=Defnyddiwch Hello i wneud pethau: cynllunio, chwerthin, gweithio gyda'ch gilydd.
first_time_experience_content2=Defnyddiwch Hello i wneud pethau: cynllunio, chwerthin, gweithio.
first_time_experience_button_label2=Gweld sut mae'n gweithio
## First Time Experience Slides
@ -141,7 +141,7 @@ initiate_audio_video_call_button2=Cychwyn
initiate_audio_video_call_tooltip2=Cychwyn sgwrs fideo
initiate_audio_call_button2=Sgwrs llais
peer_ended_conversation2=Mae'r person roeddech yn galw wedi dod a'r sgwr i ben.
peer_ended_conversation2=Mae'r person roeddech yn galw wedi dod a'r sgwrs i ben.
restart_call=Ailymuno
## LOCALIZATION NOTE (contact_offline_title): Title which is displayed when the
@ -258,7 +258,7 @@ rooms_panel_title=Dewiswch sgwrs neu gychwyn un newydd
rooms_room_full_call_to_action_label=Dysgu rhagor am {{clientShortname}} »
rooms_room_full_call_to_action_nonFx_label=Llwytho {{brandShortname}} i lawr i gychwyn eich sgwrs eich hun
rooms_room_full_label=Mae eisioes dau berson yn y sgwrs.
rooms_room_full_label=Mae eisoes dau berson yn y sgwrs.
rooms_room_join_label=Ymuno â'r sgwrs
rooms_room_joined_owner_connected_label2=Mae eich ffrind nawr wedi cysylltu a bydd yn gallu gweld eich tabiau.
rooms_room_joined_owner_not_connected_label=Mae eich ffrind yn aros i gael pori {{roomURLHostname}} gyda chi.

View File

@ -218,7 +218,7 @@ infobar_button_disconnect_accesskey=t
copy_panel_message=Möchten Sie diese Webseite teilen? Teilen Sie Ihren Browser-Tab mit einem Freund.
copy_panel_dont_show_again_label=Nicht mehr anzeigen
copy_panel_cancel_button_label=Jetzt nicht.
copy_panel_accept_button_label=Ja, zeig mir, wie es geht.
copy_panel_accept_button_label=Ja (Anleitung öffnen).
# E10s not supported strings

View File

@ -14,9 +14,11 @@
## and this is displayed in slightly larger font. Please arrange as necessary for
## your locale.
## {{clientShortname2}} will be replaced by the brand name for either string.
sign_in_again_button=Είσοδος
## LOCALIZATION_NOTE(sign_in_again_use_as_guest_button2): {{clientSuperShortname}}
## will be replaced by the super short brandname.
panel_disconnect_button=Αποσύνδεση
## LOCALIZATION_NOTE(first_time_experience_subheading2, first_time_experience_subheading_button_above): Message inviting the
## user to create his or her first conversation.

View File

@ -267,6 +267,7 @@ self_view_hidden_message=Self-view hidden but still being sent; resize window \\
peer_left_session=Your friend has left.
peer_unexpected_quit=Your friend has unexpectedly disconnected.
peer_join_session=Your friend has joined.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -94,12 +94,6 @@ share_email_body7=A friend is waiting for you on Firefox Hello. Click the link t
share_email_body_context3=A friend is waiting for you on Firefox Hello. Click the link to connect and browse {{title}} together: {{callUrl}}
## LOCALIZATION NOTE (share_email_footer2): Common footer content for both email types
share_email_footer2=\n\n____________\nFirefox Hello lets you browse the Web with your friends. Use it when you want to get things done: plan together, work together, laugh together. Learn more at http://www.firefox.com/hello
## LOCALIZATION NOTE (share_tweeet): In this item, don't translate the part
## between {{..}}. Please keep the text below 117 characters to make sure it fits
## in a tweet.
share_tweet=Join me for a video conversation on {{clientShortname2}}!
share_add_service_button=Add a Service
## LOCALIZATION NOTE (copy_link_menuitem, email_link_menuitem, delete_conversation_menuitem):
## These menu items are displayed from a panel's context menu for a conversation.

View File

@ -7,6 +7,8 @@
## LOCALIZATION_NOTE(loopMenuItem_label): Label of the menu item that is placed
## inside the browser 'Tools' menu. Use the unicode ellipsis char, \u2026, or
## use "..." if \u2026 doesn't suit traditions in your locale.
loopMenuItem_label=Iniciar una conversación…
loopMenuItem_accesskey=n
## LOCALIZATION_NOTE(sign_in_again_title_line_one, sign_in_again_title_line_two2):
## These are displayed together at the top of the panel when a user is needed to
@ -14,99 +16,264 @@
## and this is displayed in slightly larger font. Please arrange as necessary for
## your locale.
## {{clientShortname2}} will be replaced by the brand name for either string.
sign_in_again_title_line_one=Ingrese nuevamente
sign_in_again_title_line_two2=para continuar usando {{clientShortname2}}
sign_in_again_button=Ingresar
## LOCALIZATION_NOTE(sign_in_again_use_as_guest_button2): {{clientSuperShortname}}
## will be replaced by the super short brandname.
sign_in_again_use_as_guest_button2=Usar {{clientSuperShortname}} como invitado
panel_browse_with_friend_button=Navegá esta página con un amigo
panel_disconnect_button=Desconectar
## LOCALIZATION_NOTE(first_time_experience_subheading2, first_time_experience_subheading_button_above): Message inviting the
## user to create his or her first conversation.
first_time_experience_subheading2=Clic en el botón Hello para navegar páginas web con un amigo.
first_time_experience_subheading_button_above=Clic en el botón que está encima para navegar páginas web con un amigo.
## LOCALIZATION_NOTE(first_time_experience_content, first_time_experience_content2): Message describing
## ways to use Hello project.
first_time_experience_content=Puede usarse para planificar juntos, trabajar juntos, reírse juntos.
first_time_experience_content2=Puede usarse para planificar juntos, trabajar juntos, reírse juntos.
first_time_experience_button_label2=Ver como funciona
## First Time Experience Slides
fte_slide_1_title=Navegá páginas web con un amigo
## LOCALIZATION_NOTE(fte_slide_1_copy): {{clientShortname2}}
## will be replaced by the short name 2.
fte_slide_1_copy=Si estás planificando un viaje o comprando un regalo, {{clientShortname2}} permite tomar decisiones más rápidas en tiempo real.
fte_slide_2_title2=Hecho para compartir la web
## LOCALIZATION_NOTE(fte_slide_2_copy2): {{clientShortname2}}
## will be replaced by the short name 2.
fte_slide_2_copy2=Ahora, cuando invités a un amigo a una sesión, {{clientShortname2}} compartirá automáticamente cualquier página web que estés viendo. Planifiquen. Compren. Decidan. Juntos.
fte_slide_3_title=Invitá a un amigo enviándole un enlace
## LOCALIZATION_NOTE(fte_slide_3_copy): {{clientSuperShortname}}
## will be replaced by the super short brand name.
fte_slide_3_copy={{clientSuperShortname}} funciona con la mayor parte de los navegadores de escritorio. No se necesitan cuentas y todos se conectan gratis.
## LOCALIZATION_NOTE(fte_slide_4_title): {{clientSuperShortname}}
## will be replaced by the super short brand name.
fte_slide_4_title=Buscá el ícono de {{clientSuperShortname}} para empezar
## LOCALIZATION_NOTE(fte_slide_4_copy): {{brandShortname}}
## will be replaced by the brand short name.
fte_slide_4_copy=Cuando encontraste una pagina sobre la que querés discutir, clic en el ícono en {{brandShortname}} para crear un enlace. ¡Después enviáselo a tu amigo como mejor te parezca!
invite_header_text_bold2=¡Invitá a un amigo a unirse!
invite_header_text4=Compartí este enlace para poder empezar a navegar la web juntos.
## LOCALIZATION_NOTE(invite_copy_link_button, invite_copied_link_button,
## invite_email_link_button, invite_facebook_button2): These labels appear under
## an iconic button for the invite view.
invite_copy_link_button=Copiar enlace
invite_copied_link_button=¡Copiado!
invite_email_link_button=Enlace por correo
invite_facebook_button3=Facebook
invite_your_link=Tu enlace:
# Error bars
## LOCALIZATION NOTE(session_expired_error_description,could_not_authenticate,password_changed_question,try_again_later,could_not_connect,check_internet_connection,login_expired,service_not_available,problem_accessing_account):
## These may be displayed at the top of the panel.
session_expired_error_description=Sesión expirada. Toda URL creada previamente y compartida no funcionará más.
could_not_authenticate=No se pudo autenticar
password_changed_question=¿Cambiaste tu contraseña?
try_again_later=Intentá nuevamente
could_not_connect=No se pudo conectar al servidor
check_internet_connection=Verificá la conexión a internet
login_expired=El ingreso ha expirado
service_not_available=Servicio no disponible en este momento
problem_accessing_account=Hubo un problema accediendo a la cuenta
## LOCALIZATION NOTE(retry_button): Displayed when there is an error to retry
## the appropriate action.
retry_button=Reintentar
share_email_subject7=Tu invitación a navegar la web juntos
## LOCALIZATION NOTE (share_email_body7): In this item, don't translate the
## part between {{..}} and leave the \n\n part alone
share_email_body7=Un amigo te está esperando en Firefox Hello. Clic en el enlace para conectar y navegar la web juntos: {{callUrl}}
## LOCALIZATION NOTE (share_email_body_context3): In this item, don't translate
## the part between {{..}} and leave the \n\n part alone.
share_email_body_context3=Un amigo te está esperando en Firefox Hello. Clic en el enlace para conectar y navegar {{title}} juntos: {{callUrl}}
## LOCALIZATION NOTE (share_email_footer2): Common footer content for both email types
share_email_footer2=\n\n____________\nFirefox Hello permite navegar la web con tus amigos. Usalo cuando quieras que se hagan las cosas: planificar juntos, trabajar juntos, reírse juntos. Conocé más en http://www.firefox.com/hello
## LOCALIZATION NOTE (share_tweeet): In this item, don't translate the part
## between {{..}}. Please keep the text below 117 characters to make sure it fits
## in a tweet.
share_tweet=¡Unite a una conversación en video en {{clientShortname2}}!
share_add_service_button=Agregar un servicio
## LOCALIZATION NOTE (copy_link_menuitem, email_link_menuitem, delete_conversation_menuitem):
## These menu items are displayed from a panel's context menu for a conversation.
copy_link_menuitem=Copiar enlace
email_link_menuitem=Enlace por correo
edit_name_menuitem=Editar nombre
delete_conversation_menuitem2=Borrar
panel_footer_signin_or_signup_link=Ingresar o registrarse
settings_menu_item_account=Cuenta
settings_menu_item_settings=Configuración
settings_menu_item_signout=Salir
settings_menu_item_signin=Ingresar
settings_menu_item_turnnotificationson=Habilitar notificaciones
settings_menu_item_turnnotificationsoff=Deshabilitar notificaciones
settings_menu_item_feedback=Enviar opinión
settings_menu_button_tooltip=Configuración
# Conversation Window Strings
initiate_call_button_label2=¿Listo para empezar la conversación?
incoming_call_title2=Pedido de conversación
incoming_call_block_button=Bloquear
hangup_button_title=Desconectar
hangup_button_caption2=Salir
## LOCALIZATION NOTE (call_with_contact_title): The title displayed
## when calling a contact. Don't translate the part between {{..}} because
## this will be replaced by the contact's name.
call_with_contact_title=Conversación con {{contactName}}
# Outgoing conversation
outgoing_call_title=¿Comenzar conversación?
initiate_audio_video_call_button2=Comenzar
initiate_audio_video_call_tooltip2=Comenzar una conversación con video
initiate_audio_call_button2=Conversación de voz
peer_ended_conversation2=La persona que estabas llamando terminó la conversación.
restart_call=Volvé a unirte
## LOCALIZATION NOTE (contact_offline_title): Title which is displayed when the
## contact is offline.
contact_offline_title=Esta persona no está conectada
## LOCALIZATION NOTE (call_timeout_notification_text): Title which is displayed
## when the call didn't go through.
call_timeout_notification_text=La llamada no prosperó.
## LOCALIZATION NOTE (cancel_button):
## This button is displayed when a call has failed.
cancel_button=Cancelar
rejoin_button=Volvé a unirte a la conversación
cannot_start_call_session_not_ready=No se puede comenzar la conversación, la sesión no está lista.
network_disconnected=La conexión de red terminó abruptamente.
connection_error_see_console_notification=Falló la llamada; mirá la consola para más detalles.
no_media_failure_message=No se encontró cámara o micrófono.
ice_failure_message=Falló la conexión. El firewall puede estar bloqueando llamadas.
## LOCALIZATION NOTE (legal_text_and_links3): In this item, don't translate the
## parts between {{..}} because these will be replaced with links with the labels
## from legal_text_tos and legal_text_privacy. clientShortname will be replaced
## by the brand name.
legal_text_and_links3=Al usar {{clientShortname}} acepta los {{terms_of_use}} y la {{privacy_notice}}.
legal_text_tos=Términos de uso
legal_text_privacy=Nota de privacidad
## LOCALIZATION NOTE (powered_by_beforeLogo, powered_by_afterLogo):
## These 2 strings are displayed before and after a 'Telefonica'
## logo.
powered_by_beforeLogo=Con tecnología de
powered_by_afterLogo=
## LOCALIZATION_NOTE (feedback_rejoin_button): Displayed on the feedback form after
## a signed-in to signed-in user call.
feedback_rejoin_button=Volver a unirse
## LOCALIZATION NOTE (feedback_report_user_button): Used to report a user in the case of
## an abusive user.
feedback_report_user_button=Informar usuario
feedback_window_heading=¿Cómo fue la conversación?
feedback_request_button=Dejar opinión
rooms_list_recently_browsed2=Navegado recientemente
rooms_list_currently_browsing2=Navegando actualmente
rooms_signout_alert=Las conversaciones abiertas se cerrarán
room_name_untitled_page=Página sin título
## LOCALIZATION NOTE (door_hanger_return, door_hanger_prompt_name, door_hanger_button): Dialog message on leaving conversation
door_hanger_bye=¡Nos vemos!
door_hanger_return2=Podés volver a esta sesión compartida en cualquier momento desde el panel de Hello. ¿Querés ponerle un nombre para que sea más fácil de recordar?
door_hanger_current=Nombre actual:
door_hanger_button2=Aceptar
# Infobar strings
infobar_screenshare_no_guest_message=En cuanto tu amigo se una, podrán ver cualquier pestaña en la que se haga clic.
infobar_screenshare_browser_message2=Estás compartiendo tus pestañas. Cualquier pestaña en la que hagás clic puede ser vista por tus amigos
infobar_screenshare_browser_message3=Ahora estás compartiendo tus pestañas. Tu amigo verá cualquier pestaña en la que hagás clic.
infobar_screenshare_stop_sharing_message2=Ya no estás compartiendo las pestañas.
infobar_screenshare_stop_no_guest_message=Dejaste de compartir tus pestañas. Cuando tu amigo se una, no podrá ver nada hasta que se reinicie la comparticion.
infobar_button_restart_label2=Reiniciar compartición
infobar_button_restart_accesskey=e
infobar_button_stop_label2=Dejar de compartir
infobar_button_stop_accesskey=a
infobar_button_disconnect_label=Desconectar
infobar_button_disconnect_accesskey=D
# Copy panel strings
copy_panel_message=¿Necesitás compartir esta página web? Compartí la pestaña del navegador con un amigo.
copy_panel_dont_show_again_label=No mostrar nuevamente
copy_panel_cancel_button_label=No ahora
copy_panel_accept_button_label=Si, mostrarme como
# E10s not supported strings
e10s_not_supported_button_label=Abrir nueva ventana
e10s_not_supported_subheading={{brandShortname}} no funciona en una ventana multiproceso.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
## LOCALIZATION NOTE: In this file, don't translate the part between {{..}}
# Text chat strings
chat_textbox_placeholder=Esscribí aquí...
## LOCALIZATION NOTE(clientShortname2): This should not be localized and
## should remain "Firefox Hello" for all locales.
clientShortname2=Firefox Hello
conversation_has_ended=Se terminó tu conversación.
generic_failure_message=Estamos con problemas técnicos...
generic_failure_no_reason2=¿Querés probar de vuelta?
help_label=Ayuda
mute_local_audio_button_title=Deshabilitá tu audio
unmute_local_audio_button_title=Habilitá tu audio
mute_local_video_button_title2=Deshabilitar video
unmute_local_video_button_title2=Habilitar video
## LOCALIZATION NOTE (retry_call_button):
## This button is displayed when a call has failed.
retry_call_button=Probar de nuevo
rooms_leave_button_label=Salir
rooms_panel_title=Elegí una conversación o empezá una nueva
rooms_room_full_call_to_action_label=Aprendé más sobre ({clientShortname}) »
rooms_room_full_call_to_action_nonFx_label=Descargá ({brandShortname}) para empezar la tuya
rooms_room_full_label=Ya hay dos personas en esta conversación.
rooms_room_join_label=Unite a la conversación
rooms_room_joined_owner_connected_label2=Ahroa tu amigo está conectado y podrá ver tus pestañas.
rooms_room_joined_owner_not_connected_label=Tu amigo está esperando para navegar ({roomURLHostname}) con vos.
self_view_hidden_message=La vista propia está oculta pero se envía de todas maneras; cambiá el tamaño de la ventana para verlo
peer_left_session=Tu amigo se fue.
peer_unexpected_quit=Tu amigo se desconectó de manera inesperada.
peer_join_session=Tu amigo se unió.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.
tos_failure_message=({clientShortname}) no está disponible en tu país.
display_name_guest=Invitado
## LOCALIZATION NOTE(clientSuperShortname): This should not be localized and
## should remain "Hello" for all locales.
clientSuperShortname=Hello

View File

@ -268,6 +268,7 @@ self_view_hidden_message=La vista local está oculta pero continúa siendo envia
peer_left_session=Tu amigo se ha ido.
peer_unexpected_quit=Tu amigo se ha desconectado inesperadamente.
peer_join_session=Tu amigo se ha unido.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -267,6 +267,7 @@ self_view_hidden_message=Auto-vista oculta pero enviándose; redimensiona ventan
peer_left_session=Tu amigo se ha ido.
peer_unexpected_quit=Tu amigo se ha desconectado inesperadamente.
peer_join_session=Tu amigo se ha unido.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -268,6 +268,7 @@ self_view_hidden_message=Sinu pilti edastatakse, kuid see on praegu peidetud. Pi
peer_left_session=Sõber on lahkunud.
peer_unexpected_quit=Ühendus sõbraga on ootamatult katkenud.
peer_join_session=Sinu sõber liitus.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -203,6 +203,8 @@ door_hanger_button2=تایید!
infobar_screenshare_no_guest_message=هر موقع دوستان شما متصل شوند، آنها قادر خواهند بود هر زبانه‌ای که روی‌اش کلیک می‌کنید را ببینند.
infobar_screenshare_browser_message2=شما در حال اشتراک‌گذاری زبانه‌های خود هستید. هر زبانه‌ای که بر روی‌اش کلیک کنید، توسط دوستانتان دید میشود
infobar_screenshare_browser_message3=شما هم‌اکنون در حال اشتراک‌گذاری زبانه‌های خود هستید. دوستان شما هر زبانه‌ای که روی‌اش کلیک کنید را خواهند دید.
infobar_screenshare_stop_sharing_message2=شما هیچ زبانه‌ای را با دیگران به اشتراک نگذاشته‌اید.
infobar_screenshare_stop_no_guest_message=شما به اشتراک گذاری زبانه‌های خود را متوقف کرده‌اید. وقتی دوستان شما وارد شوند، قادر به دیدن چیزی نخواهند بود تا زمانی که شما به اشتراک گذاری را از نو راه‌اندازی کنید.
infobar_button_restart_label2=راه‌اندازی مجدد اشتراک‌گذاری
infobar_button_restart_accesskey=e
infobar_button_stop_label2=توقف اشتراک‌گذاری
@ -265,6 +267,7 @@ self_view_hidden_message=نمای فردی پنهان شده است ولی ار
peer_left_session=دوست شما گفت‌وگو را ترک کرد.
peer_unexpected_quit=دوست شما بطور غیرمنتظره‌ای قطع شد.
peer_join_session=دوستان شما وارد شده‌اند.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -45,7 +45,7 @@ fte_slide_1_copy=Oft jo no in reis planne of in kado sykje, mei {{clientShortnam
fte_slide_2_title2=Makke om it web te dielen
## LOCALIZATION_NOTE(fte_slide_2_copy2): {{clientShortname2}}
## will be replaced by the short name 2.
fte_slide_2_copy2=As jo no in freon útnoegje foar in sesje, sil {{clientShortname2}} automatysk websiden dy't jo besjen diele. Plan. Winkelje. Beslis. Tegearre.
fte_slide_2_copy2=As jo no in freon útnûgje foar in sesje, sil {{clientShortname2}} automatysk websiden dy't jo besjen diele. Plan. Winkelje. Beslis. Tegearre.
fte_slide_3_title=Noegje in freon út troch in keppeling te dielen
## LOCALIZATION_NOTE(fte_slide_3_copy): {{clientSuperShortname}}
## will be replaced by the super short brand name.
@ -85,7 +85,7 @@ problem_accessing_account=Der wie in probleem mei tagong ta jo account
## the appropriate action.
retry_button=Nochris probearje
share_email_subject7=Jo útnoeging om tegearre op it web te sneupjen
share_email_subject7=Jo útnûging om tegearre op it web te sneupjen
## LOCALIZATION NOTE (share_email_body7): In this item, don't translate the
## part between {{..}} and leave the \n\n part alone
share_email_body7=In freon wachtet op dy op Firefox Hello. Klik op de keppeling om te ferbinen en sneup tegearre op it web: {{callUrl}}

View File

@ -45,7 +45,7 @@ fte_slide_1_copy=Oft jo no in reis planne of in kado sykje, mei {{clientShortnam
fte_slide_2_title2=Makke om it web te dielen
## LOCALIZATION_NOTE(fte_slide_2_copy2): {{clientShortname2}}
## will be replaced by the short name 2.
fte_slide_2_copy2=As jo no in freon útnoegje foar in sesje, sil {{clientShortname2}} automatysk websiden dy't jo besjen diele. Plan. Winkelje. Beslis. Tegearre.
fte_slide_2_copy2=As jo no in freon útnûgje foar in sesje, sil {{clientShortname2}} automatysk websiden dy't jo besjen diele. Plan. Winkelje. Beslis. Tegearre.
fte_slide_3_title=Noegje in freon út troch in keppeling te dielen
## LOCALIZATION_NOTE(fte_slide_3_copy): {{clientSuperShortname}}
## will be replaced by the super short brand name.
@ -85,7 +85,7 @@ problem_accessing_account=Der wie in probleem mei tagong ta jo account
## the appropriate action.
retry_button=Nochris probearje
share_email_subject7=Jo útnoeging om tegearre op it web te sneupjen
share_email_subject7=Jo útnûging om tegearre op it web te sneupjen
## LOCALIZATION NOTE (share_email_body7): In this item, don't translate the
## part between {{..}} and leave the \n\n part alone
share_email_body7=In freon wachtet op dy op Firefox Hello. Klik op de keppeling om te ferbinen en sneup tegearre op it web: {{callUrl}}

View File

@ -7,6 +7,7 @@
## LOCALIZATION_NOTE(loopMenuItem_label): Label of the menu item that is placed
## inside the browser 'Tools' menu. Use the unicode ellipsis char, \u2026, or
## use "..." if \u2026 doesn't suit traditions in your locale.
loopMenuItem_label=התחלת שיחה…
## LOCALIZATION_NOTE(sign_in_again_title_line_one, sign_in_again_title_line_two2):
## These are displayed together at the top of the panel when a user is needed to
@ -14,35 +15,61 @@
## and this is displayed in slightly larger font. Please arrange as necessary for
## your locale.
## {{clientShortname2}} will be replaced by the brand name for either string.
sign_in_again_title_line_one=נא להתחבר שוב
sign_in_again_title_line_two2=כדי להמשיך להשתמש ב־{{clientShortname2}}
## LOCALIZATION_NOTE(sign_in_again_use_as_guest_button2): {{clientSuperShortname}}
## will be replaced by the super short brandname.
sign_in_again_use_as_guest_button2=השתמש ב־{{clientSuperShortname}} כאורח
panel_browse_with_friend_button=גלישה בדף זה עם חבר
panel_disconnect_button=התנתקות
## LOCALIZATION_NOTE(first_time_experience_subheading2, first_time_experience_subheading_button_above): Message inviting the
## user to create his or her first conversation.
first_time_experience_subheading2=לחץ על כפתור ה־Hello כדי לגלוש באתרים עם חבר.
first_time_experience_subheading_button_above=לחץ על הכפתור שלמעלה כדי לגלוש באתרים עם חבר.
## LOCALIZATION_NOTE(first_time_experience_content, first_time_experience_content2): Message describing
## ways to use Hello project.
first_time_experience_content=השתמש בזה כדי לתכנן ביחד, לעבוד ביחד, לצחוק ביחד.
first_time_experience_button_label2=ראו כיצד זה עובד
## First Time Experience Slides
fte_slide_1_title=גלישה באתרים עם חבר
## LOCALIZATION_NOTE(fte_slide_1_copy): {{clientShortname2}}
## will be replaced by the short name 2.
fte_slide_2_title2=נועד לשיתוף הרשת
## LOCALIZATION_NOTE(fte_slide_2_copy2): {{clientShortname2}}
## will be replaced by the short name 2.
fte_slide_3_title=הזמנת חבר באמצעות שליחת קישור
## LOCALIZATION_NOTE(fte_slide_3_copy): {{clientSuperShortname}}
## will be replaced by the super short brand name.
fte_slide_3_copy={{clientSuperShortname}} עובד עם רוב הדפדפנים השולחניים. אין צורך בחשבונות וכולם יכולים להתחבר בחינם.
## LOCALIZATION_NOTE(fte_slide_4_title): {{clientSuperShortname}}
## will be replaced by the super short brand name.
fte_slide_4_title=אתר את סמל ה־{{clientSuperShortname}} כדי להתחיל
## LOCALIZATION_NOTE(fte_slide_4_copy): {{brandShortname}}
## will be replaced by the brand short name.
invite_header_text_bold2=הזמן חבר שיצטרף אליך!
invite_header_text4=שתף קישור זה כך שתוכלו לגלוש ברשת ביחד.
## LOCALIZATION_NOTE(invite_copy_link_button, invite_copied_link_button,
## invite_email_link_button, invite_facebook_button2): These labels appear under
## an iconic button for the invite view.
invite_copy_link_button=העתקת קישור
invite_copied_link_button=הועתק!
invite_email_link_button=שליחת קישור בדואר אלקטרוני
invite_facebook_button3=Facebook
invite_your_link=הקישור שלך:
# Error bars
## LOCALIZATION NOTE(session_expired_error_description,could_not_authenticate,password_changed_question,try_again_later,could_not_connect,check_internet_connection,login_expired,service_not_available,problem_accessing_account):
## These may be displayed at the top of the panel.
could_not_authenticate=לא ניתן לאמת
password_changed_question=האם שינית את ססמתך?
try_again_later=נא לנסות שוב מאוחר יותר
could_not_connect=לא ניתן להתחבר לשרת
service_not_available=השירות אינו זמין כעת
## LOCALIZATION NOTE(retry_button): Displayed when there is an error to retry
## the appropriate action.
@ -56,15 +83,29 @@
## between {{..}}. Please keep the text below 117 characters to make sure it fits
## in a tweet.
share_add_service_button=הוספת שירות
## LOCALIZATION NOTE (copy_link_menuitem, email_link_menuitem, delete_conversation_menuitem):
## These menu items are displayed from a panel's context menu for a conversation.
copy_link_menuitem=העתקת קישור
email_link_menuitem=שליחת קישור בדוא״ל
edit_name_menuitem=עריכת שם
delete_conversation_menuitem2=מחיקה
panel_footer_signin_or_signup_link=הרשמה או התחברות
settings_menu_item_account=חשבון
settings_menu_item_settings=הגדרות
settings_menu_item_signout=התנתקות
settings_menu_item_turnnotificationson=הפעלת התראות
settings_menu_item_turnnotificationsoff=נטרול התראות
settings_menu_item_feedback=שליחת משוב
settings_menu_button_tooltip=הגדרות
# Conversation Window Strings
incoming_call_block_button=חסימה
hangup_button_title=ניתוק
hangup_button_caption2=יציאה
@ -75,6 +116,8 @@ hangup_button_caption2=יציאה
# Outgoing conversation
initiate_audio_video_call_tooltip2=התחלת שיחת וידאו
initiate_audio_call_button2=שיחת וידאו
## LOCALIZATION NOTE (contact_offline_title): Title which is displayed when the
@ -84,12 +127,15 @@ hangup_button_caption2=יציאה
## LOCALIZATION NOTE (cancel_button):
## This button is displayed when a call has failed.
cancel_button=ביטול
## LOCALIZATION NOTE (legal_text_and_links3): In this item, don't translate the
## parts between {{..}} because these will be replaced with links with the labels
## from legal_text_tos and legal_text_privacy. clientShortname will be replaced
## by the brand name.
legal_text_tos=תנאי שימוש
legal_text_privacy=הצהרת פרטיות
## LOCALIZATION NOTE (powered_by_beforeLogo, powered_by_afterLogo):
## These 2 strings are displayed before and after a 'Telefonica'
@ -99,19 +145,30 @@ hangup_button_caption2=יציאה
## a signed-in to signed-in user call.
## LOCALIZATION NOTE (feedback_report_user_button): Used to report a user in the case of
## an abusive user.
feedback_report_user_button=דיווח על משתמש
feedback_request_button=יציאה מהמשוב
tour_label=סיור
room_name_untitled_page=דף ללא כותרת
## LOCALIZATION NOTE (door_hanger_return, door_hanger_prompt_name, door_hanger_button): Dialog message on leaving conversation
door_hanger_bye=להתראות!
door_hanger_current=שם נוכחי:
door_hanger_button2=קיבלתי!
# Infobar strings
infobar_button_disconnect_label=התנתקות
# Copy panel strings
copy_panel_accept_button_label=כן, הראו לי כיצד
# E10s not supported strings
e10s_not_supported_button_label=פתיחת חלון חדש
e10s_not_supported_subheading={{brandShortname}} לא עובד בחלון מרובה תהליכים.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
@ -119,11 +176,14 @@ hangup_button_caption2=יציאה
## LOCALIZATION NOTE: In this file, don't translate the part between {{..}}
# Text chat strings
chat_textbox_placeholder=הקלד כאן…
## LOCALIZATION NOTE(clientShortname2): This should not be localized and
## should remain "Firefox Hello" for all locales.
clientShortname2=Firefox Hello
conversation_has_ended=הדיון הסתיים.
conversation_has_ended=השיחה הסתיימה.
generic_failure_message=יש לנו קשיים טכניים…
generic_failure_no_reason2=לנסות שוב?
@ -131,6 +191,8 @@ help_label=עזרה
mute_local_audio_button_title=השתקת השמע שלך
unmute_local_audio_button_title=ביטול השתקת השמע שלך
mute_local_video_button_title2=נטרול וידאו
unmute_local_video_button_title2=אפשר וידאו
## LOCALIZATION NOTE (retry_call_button):
## This button is displayed when a call has failed.
@ -138,12 +200,24 @@ retry_call_button=ניסיון חוזר
rooms_leave_button_label=עזיבה
rooms_panel_title=בחר בשיחה או התחל שיחה חדשה
rooms_room_join_label=הצטרפות לדיון
rooms_room_full_call_to_action_label=מידע נוסף אודות {{clientShortname}} »
rooms_room_full_label=יש כבר שני אנשים בשיחה זו.
rooms_room_join_label=הצטרפות לשיחה
rooms_room_joined_owner_connected_label2=חברך כרגע מחובר ויוכל לצפות בלשוניות שלך.
rooms_room_joined_owner_not_connected_label=חברך ממתין לגלוש ב־{{roomURLHostname}} יחד אתך.
peer_left_session=חברך עזב.
peer_unexpected_quit=חברך התנתק באופן לא צפוי.
peer_join_session=חברך הצטרף.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.
tos_failure_message={{clientShortname}} אינו זמין במדינה שלך.
display_name_guest=אורח
## LOCALIZATION NOTE(clientSuperShortname): This should not be localized and
## should remain "Hello" for all locales.

View File

@ -265,8 +265,9 @@ rooms_room_joined_owner_not_connected_label=Teman Anda sedang menunggu untuk men
self_view_hidden_message=Tampilan diri sedang tersembunyi tetapi tetap dikirim, ubah ukuran jendela untuk menampilkannya
peer_left_session=Teman anda telah pergi.
peer_unexpected_quit=Teman anda tiba-tiba terputus.
peer_left_session=Teman Anda telah pergi.
peer_unexpected_quit=Teman Anda tiba-tiba tak tersambung.
peer_join_session=Teman Anda telah bergabung.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -267,6 +267,7 @@ self_view_hidden_message=Lanteprima della fotocamera è nascosta, ma linte
peer_left_session=L'interlocutore si è disconnesso.
peer_unexpected_quit=L'interlocutore si è inaspettatamente disconnesso.
peer_join_session=Linterlocutore si è aggiunto alla conversazione.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -24,6 +24,7 @@ sign_in_again_button=로그인
sign_in_again_use_as_guest_button2=손님으로 {{clientSuperShortname}} 쓰기
panel_browse_with_friend_button=친구와 함께 이 페이지 사용
panel_disconnect_button=연결 끊음
## LOCALIZATION_NOTE(first_time_experience_subheading2, first_time_experience_subheading_button_above): Message inviting the
## user to create his or her first conversation.

View File

@ -222,7 +222,7 @@ copy_panel_accept_button_label=Ja, toon me hoe
# E10s not supported strings
e10s_not_supported_button_label=Nieuw venster openen
e10s_not_supported_subheading={{brandShortname}} werkt niet in een multi-process-venster.
e10s_not_supported_subheading={{brandShortname}} werkt niet in een multiprocess-venster.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

View File

@ -35,7 +35,7 @@ first_time_experience_subheading_button_above=Trykk på knappen ovanfor for å s
## ways to use Hello project.
first_time_experience_content=Bruk han til å planleggja, arbeida, og ha det moro i lag.
first_time_experience_content2=Bruk han til å få gjort ting: planlegging, arbeid og for å ha det moro i lag.
first_time_experience_button_label2=Sjå korleis det fungerar
first_time_experience_button_label2=Sjå korleis det fungerer
## First Time Experience Slides
fte_slide_1_title=Surf på nettsider med ein ven
@ -45,11 +45,11 @@ fte_slide_1_copy=Om du planlegg ei reise eller leitar du etter ein present, {{cl
fte_slide_2_title2=Laga for å dela nettet
## LOCALIZATION_NOTE(fte_slide_2_copy2): {{clientShortname2}}
## will be replaced by the short name 2.
fte_slide_2_copy2=Når du inviterer ein ven til ei ykt, vil {{clientShortname2}} automatisk dela nettsidene du ser på. Planlegg. Handla. Ta avgjerder. Saman.
fte_slide_2_copy2=Når du inviterer inn ein ven til ei økt, vil {{clientShortname2}} automatisk dela alle nettsider du viser. Planlegg. Gjer innkjøp. Ta avgjerder. Ilag.
fte_slide_3_title=Inviter ein ven ved å senda ei lenke
## LOCALIZATION_NOTE(fte_slide_3_copy): {{clientSuperShortname}}
## will be replaced by the super short brand name.
fte_slide_3_copy={{clientSuperShortname}} fungerar med dei fleste nettlesarar. Det treng ingen konto og elle tilkoplingar er gratis.
fte_slide_3_copy={{clientSuperShortname}} fungerer med dei fleste nettlesarar. Du treng ingen konto og alle tilkoplingar er gratis.
## LOCALIZATION_NOTE(fte_slide_4_title): {{clientSuperShortname}}
## will be replaced by the super short brand name.
fte_slide_4_title=Finn ikonet for {{clientSuperShortname}} for å koma i gang
@ -222,7 +222,7 @@ copy_panel_accept_button_label=Ja, vis meg korleis
# E10s not supported strings
e10s_not_supported_button_label=Opna nytt vindauge
e10s_not_supported_subheading={{brandShortname}} fungerar ikkje i eit multiprosessvindauge.
e10s_not_supported_subheading={{brandShortname}} fungerer ikkje i eit multiprosessvindauge.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
@ -267,6 +267,7 @@ self_view_hidden_message=Bildet frå eige kamera er skjult, men vert framleis se
peer_left_session=Venane dine fór.
peer_unexpected_quit=Venane dine har uventa kopla seg frå.
peer_join_session=Venen din er no med.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -23,9 +23,9 @@ first_time_experience_button_label2=Przekonaj się, jak to działa
fte_slide_1_title=Przeglądaj strony WWW wspólnie ze znajomymi
fte_slide_1_copy=Niezależnie czy planujesz wycieczkę, zakup prezentu, {{clientShortname2}} pozwala podejmować decyzje szybciej.
fte_slide_2_title2=Stworzony, by dzielić się siecią
fte_slide_2_copy2=Zapraszając znajomego do czatu, {{clientShortname2}} automatycznie udostępni stronę którą oglądasz. Planuj. Rób zakupy. Decyduj. Wspólnie.
fte_slide_2_copy2=Zapraszając znajomego do czatu, {{clientShortname2}} automatycznie udostępni stronę, którą oglądasz. Planuj. Rób zakupy. Decyduj. Wspólnie.
fte_slide_3_title=Zaproś znajomego wysyłając odnośnik
fte_slide_3_copy={{clientSuperShortname}} działa w większości przeglądarek na komputery. Nie jest wymagane zakładnie kont i wszyscy łączą się bez opłat.
fte_slide_3_copy={{clientSuperShortname}} działa w większości przeglądarek na komputery. Nie jest wymagane zakładanie kont i wszyscy łączą się bez opłat.
fte_slide_4_title=Odszukaj ikonę {{clientSuperShortname}}, aby rozpocząć
fte_slide_4_copy=Po znalezieniu strony do omówienia, kliknij ikonę w {{brandShortname}}, aby utworzyć odnośnik. Wyślij go znajomemu jakkolwiek chcesz!
@ -117,9 +117,6 @@ rooms_list_currently_browsing2=Obecnie aktywne
rooms_signout_alert=Otwarte rozmowy zostaną zamknięte
room_name_untitled_page=Strona bez tytułu
door_hanger_return=Do zobaczenia! Do tej współdzielonej sesji można zawsze wrócić przez panel Hello.
door_hanger_prompt_name=Czy nadać jej nazwę ułatwiającą jej zapamiętanie? Obecna nazwa to:
door_hanger_button=OK
door_hanger_bye=Do zobaczenia!
door_hanger_return2=Zawsze można powrócić do tej udostępnianej sesji poprzez panel Firefox Hello. Czy nadać ułatwiającą jej zapamiętanie nazwę?
door_hanger_current=Obecna nazwa:
@ -128,7 +125,8 @@ door_hanger_button2=OK
infobar_screenshare_no_guest_message=Jak tylko znajomy dołączy, będzie mógł oglądać zawartość każdej karty, którą klikniesz.
infobar_screenshare_browser_message2=Udostępniasz obraz kart. Rozmówcy mogą oglądać zawartość każdej karty, którą klikniesz.
infobar_screenshare_browser_message3=Udostępniasz obraz kart. Rozmówcy mogą oglądać zawartość każdej karty, którą klikniesz.
infobar_screenshare_stop_sharing_message=Udostępnianie obrazu kart zostało wstrzymane
infobar_screenshare_stop_sharing_message2=Udostępnianie obrazu kart zostało wstrzymane.
infobar_screenshare_stop_no_guest_message=Udostępnianie obrazu kart zostało wstrzymane. Gdy ktoś dołączy do rozmowy, nic nie zobaczy dopóki nie wznowisz udostępniania.
infobar_button_restart_label2=Wznów udostępnianie
infobar_button_restart_accesskey=W
infobar_button_stop_label2=Nie udostępniaj dłużej
@ -174,10 +172,11 @@ rooms_room_join_label=Dołącz do rozmowy
rooms_room_joined_owner_connected_label2=Zestawiono połączenie, druga osoba będzie od teraz mogła widzieć Twoje karty.
rooms_room_joined_owner_not_connected_label=Ktoś czeka, aby wspólnie przeglądać {{roomURLHostname}}.
self_view_hidden_message=Obraz z kamery jest ukryty ale nadal wysyłany (powiększenie okna ukaże go)
self_view_hidden_message=Obraz z kamery jest ukryty, ale nadal wysyłany (powiększenie okna ukaże go)
peer_left_session=Rozmówca się rozłączył.
peer_unexpected_quit=Rozmówca nieoczekiwanie się rozłączył.
peer_join_session=Dołączył rozmówca.
tos_failure_message=Usługa {{clientShortname}} nie jest dostępna w tym kraju.

View File

@ -267,6 +267,7 @@ self_view_hidden_message=Vista própria oculta mas ainda a ser enviada; redimens
peer_left_session=O seu amigo saiu.
peer_unexpected_quit=O seu amigo foi desligado de forma inesperada.
peer_join_session=O seu amigo entrou.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -34,6 +34,7 @@ first_time_experience_subheading_button_above=Clicca sin il buttun survart per n
## LOCALIZATION_NOTE(first_time_experience_content, first_time_experience_content2): Message describing
## ways to use Hello project.
first_time_experience_content=Fa diever da la funcziun per planisar ensemen, lavurar ensemen, rir ensemen.
first_time_experience_content2=Fa diever da la funcziun per planisar ensemen, lavurar ensemen, rir ensemen.
first_time_experience_button_label2=Mussar co che quai funcziunescha
## First Time Experience Slides
@ -193,6 +194,7 @@ rooms_signout_alert=Conversaziuns avertas vegnan serradas
room_name_untitled_page=Pagina senza titel
## LOCALIZATION NOTE (door_hanger_return, door_hanger_prompt_name, door_hanger_button): Dialog message on leaving conversation
door_hanger_bye=A pli tard!
# Infobar strings

View File

@ -7,6 +7,8 @@
## LOCALIZATION_NOTE(loopMenuItem_label): Label of the menu item that is placed
## inside the browser 'Tools' menu. Use the unicode ellipsis char, \u2026, or
## use "..." if \u2026 doesn't suit traditions in your locale.
loopMenuItem_label=Pornește o conversație…
loopMenuItem_accesskey=t
## LOCALIZATION_NOTE(sign_in_again_title_line_one, sign_in_again_title_line_two2):
## These are displayed together at the top of the panel when a user is needed to
@ -14,35 +16,56 @@
## and this is displayed in slightly larger font. Please arrange as necessary for
## your locale.
## {{clientShortname2}} will be replaced by the brand name for either string.
sign_in_again_title_line_one=Te rugăm să te autentifici din nou
sign_in_again_title_line_two2=pentru a continua să folosești {{clientShortname2}}
sign_in_again_button=Autentificare
## LOCALIZATION_NOTE(sign_in_again_use_as_guest_button2): {{clientSuperShortname}}
## will be replaced by the super short brandname.
sign_in_again_use_as_guest_button2=Folosește {{clientSuperShortname}} ca oaspete
panel_browse_with_friend_button=Navighează pe această pagină cu un prieten
panel_disconnect_button=Deconectare
## LOCALIZATION_NOTE(first_time_experience_subheading2, first_time_experience_subheading_button_above): Message inviting the
## user to create his or her first conversation.
first_time_experience_subheading2=Clic pe butonul Hello pentru a naviga pe pagini web cu un prieten.
first_time_experience_subheading_button_above=Clic pe butonul de mai sus pentru a naviga pe pagini web cu un prieten.
## LOCALIZATION_NOTE(first_time_experience_content, first_time_experience_content2): Message describing
## ways to use Hello project.
first_time_experience_content=Folosește-l pentru a planifica împreună, a lucra împreună, a râde împreună.
first_time_experience_content2=Folosește-l pentru realizarea unor lucruri: pentru a planifica împreună, a lucra împreună, a râde împreună.
first_time_experience_button_label2=Vezi cum funcționează
## First Time Experience Slides
fte_slide_1_title=Navighează pe pagini web cu un prieten
## LOCALIZATION_NOTE(fte_slide_1_copy): {{clientShortname2}}
## will be replaced by the short name 2.
fte_slide_2_title2=Realizat pentru a împărtăși webul
## LOCALIZATION_NOTE(fte_slide_2_copy2): {{clientShortname2}}
## will be replaced by the short name 2.
## LOCALIZATION_NOTE(fte_slide_3_copy): {{clientSuperShortname}}
## will be replaced by the super short brand name.
## LOCALIZATION_NOTE(fte_slide_4_title): {{clientSuperShortname}}
## will be replaced by the super short brand name.
fte_slide_4_title=Găsește iconița {{clientSuperShortname}} pentru a începe
## LOCALIZATION_NOTE(fte_slide_4_copy): {{brandShortname}}
## will be replaced by the brand short name.
## LOCALIZATION_NOTE(invite_copy_link_button, invite_copied_link_button,
## invite_email_link_button, invite_facebook_button2): These labels appear under
## an iconic button for the invite view.
invite_copied_link_button=Copiat!
invite_email_link_button=Trimite e-mail cu linkul
invite_facebook_button3=Facebook
invite_your_link=Linkul tău:
# Error bars
## LOCALIZATION NOTE(session_expired_error_description,could_not_authenticate,password_changed_question,try_again_later,could_not_connect,check_internet_connection,login_expired,service_not_available,problem_accessing_account):
## These may be displayed at the top of the panel.
session_expired_error_description=Sesiune expirată. Toate URL-urile pe care le-ai creat anterior și partajate nu vor mai funcționa.
could_not_authenticate=Nu se poate autentifica
try_again_later=Te rugăm să încerci din nou mai târziu
## LOCALIZATION NOTE(retry_button): Displayed when there is an error to retry
## the appropriate action.
@ -56,15 +79,23 @@
## between {{..}}. Please keep the text below 117 characters to make sure it fits
## in a tweet.
share_add_service_button=Adaugă un serviciu
## LOCALIZATION NOTE (copy_link_menuitem, email_link_menuitem, delete_conversation_menuitem):
## These menu items are displayed from a panel's context menu for a conversation.
email_link_menuitem=Trimite e-mail cu linkul
settings_menu_item_account=Cont
settings_menu_item_settings=Setări
settings_menu_button_tooltip=Setări
# Conversation Window Strings
initiate_call_button_label2=Ești gata să pornești conversația?
incoming_call_title2=Cerere de conversație
incoming_call_block_button=Blochează
hangup_button_title=Închide
hangup_button_caption2=Ieșire
@ -75,7 +106,11 @@ hangup_button_caption2=Ieșire
# Outgoing conversation
outgoing_call_title=Pornești conversația?
initiate_audio_video_call_button2=Pornește
initiate_audio_video_call_tooltip2=Pornește o conversație video
restart_call=Realătură-te
## LOCALIZATION NOTE (contact_offline_title): Title which is displayed when the
## contact is offline.
@ -85,6 +120,7 @@ hangup_button_caption2=Ieșire
## LOCALIZATION NOTE (cancel_button):
## This button is displayed when a call has failed.
cannot_start_call_session_not_ready=Nu se poate porni apelul, sesiunea nu este pregătită.
## LOCALIZATION NOTE (legal_text_and_links3): In this item, don't translate the
## parts between {{..}} because these will be replaced with links with the labels
@ -106,6 +142,9 @@ hangup_button_caption2=Ieșire
# Infobar strings
infobar_button_restart_label2=Repornește partajarea
infobar_button_restart_accesskey=R
infobar_button_stop_label2=Oprește partajarea
# Copy panel strings
@ -125,8 +164,8 @@ chat_textbox_placeholder=Tastează aici…
## should remain "Firefox Hello" for all locales.
clientShortname2=Firefox Hello
conversation_has_ended=Conversația s-a încheiat.
generic_failure_message=Momentan întâmpinăm dificultăți tehnice…
conversation_has_ended=Conversația ta s-a încheiat.
generic_failure_message=Întâmpinăm dificultăți tehnice…
generic_failure_no_reason2=Dorești să încerci din nou?
@ -134,16 +173,16 @@ help_label=Ajutor
mute_local_audio_button_title=Închide sunetul
unmute_local_audio_button_title=Pornește sunetul
mute_local_video_button_title2=Oprește video
unmute_local_video_button_title2=Pornește video
mute_local_video_button_title2=Oprește videoul
unmute_local_video_button_title2=Pornește videoul
## LOCALIZATION NOTE (retry_call_button):
## This button is displayed when a call has failed.
retry_call_button=Reîncearcă
rooms_leave_button_label=Părăsire
rooms_leave_button_label=Părăsește
rooms_panel_title=Alege o conversație sau începe una nouă
rooms_panel_title=Alege o conversație sau pornește una nouă
rooms_room_full_call_to_action_label=Află mai multe despre {{clientShortname}} »
rooms_room_full_call_to_action_nonFx_label=Descarcă {{brandShortname}} pentru a porni propria conversație

View File

@ -41,7 +41,7 @@ first_time_experience_button_label2=Посмотреть, как это рабо
fte_slide_1_title=Просматривайте веб-страницы с другом
## LOCALIZATION_NOTE(fte_slide_1_copy): {{clientShortname2}}
## will be replaced by the short name 2.
fte_slide_1_copy=Бу то планирование поездки или покупка подарка, {{clientShortname2}} позволяет вам принимать решения быстрее в реальном времени.
fte_slide_1_copy=Будь то планирование поездки или покупка подарка, {{clientShortname2}} позволяет вам принимать решения быстрее в реальном времени.
fte_slide_2_title2=Создан для совместной работы в Интернете
## LOCALIZATION_NOTE(fte_slide_2_copy2): {{clientShortname2}}
## will be replaced by the short name 2.

View File

@ -268,6 +268,7 @@ self_view_hidden_message=Záber z kamery je skrytý, napriek tomu sa stále odos
peer_left_session=Váš priateľ odišiel.
peer_unexpected_quit=Váš priateľ neočakávane ukončil spojenie.
peer_join_session=Váš priateľ sa pripojil.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -268,6 +268,7 @@ self_view_hidden_message=Приказ вашег екрана је сакрив
peer_left_session=Ваш пријатељ је изашао.
peer_unexpected_quit=Ваш пријатељ се неочекивано искључио.
peer_join_session=Ваш пријатељ се придружио.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -267,6 +267,7 @@ self_view_hidden_message=Kendi görünümünüz gizlendi ama hâlâ gönderiliyo
peer_left_session=Arkadaşınız çıktı.
peer_unexpected_quit=Arkadaşınızın bağlantısı koptu.
peer_join_session=Arkadaşınız geldi.
## LOCALIZATION NOTE (tos_failure_message): Don't translate {{clientShortname}}
## as this will be replaced by clientShortname2.

View File

@ -0,0 +1,25 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
/* Only apply to browser.xul documents */
@-moz-document url("chrome://browser/content/browser.xul") {
/**
* XXX Due to bug 1228542, anything in this file that overrides a browser style
* must specify !important. Otherwise the style won't get applied correctly
* due to the limitations caused by the bug.
*/
#loop-button[state="slideshow"] {
background: none;
}
#loop-button[state="slideshow"] > .toolbarbutton-badge-stack {
background: var(--toolbarbutton-hover-background) !important;
background-clip: padding-box !important;
border-color: var(--toolbarbutton-hover-bordercolor) !important;
box-shadow: var(--toolbarbutton-hover-boxshadow) !important;
}
}

View File

@ -23,4 +23,15 @@
list-style-image: url(chrome://loop/skin/toolbar-lunaSilver@2x.png)
}
}
#loop-button[state="slideshow"] {
background: none;
}
#loop-button[state="slideshow"] > .toolbarbutton-badge-stack {
background: var(--toolbarbutton-hover-background) !important;
background-clip: padding-box !important;
border-color: var(--toolbarbutton-hover-bordercolor) !important;
box-shadow: var(--toolbarbutton-hover-boxshadow) !important;
}
}

View File

@ -16,7 +16,6 @@ skip-if = os == "linux" # Bug 1266041
[browser_mozLoop_chat.js]
[browser_mozLoop_context.js]
[browser_mozLoop_infobar.js]
[browser_mozLoop_socialShare.js]
[browser_panel_privateBrowsing.js]
[browser_mozLoop_sharingListeners.js]
[browser_mozLoop_telemetry.js]

View File

@ -6,7 +6,9 @@ var [, gHandlers] = LoopAPI.inspect();
add_task(function* test_mozLoop_appVersionInfo() {
let appVersionInfo;
gHandlers.GetAppVersionInfo({}, result => { appVersionInfo = result; });
gHandlers.GetAppVersionInfo({}, result => {
appVersionInfo = result;
});
Assert.ok(appVersionInfo, "should have appVersionInfo");

View File

@ -1,98 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
Cu.import("resource://gre/modules/Promise.jsm");
const { SocialService } = Cu.import("resource://gre/modules/SocialService.jsm", {});
var [, gHandlers] = LoopAPI.inspect();
const kShareProvider = {
name: "provider 1",
origin: "https://example.com",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png",
shareURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar_empty.html"
};
const kShareProviderInvalid = {
name: "provider 1",
origin: "https://example2.com"
};
const kActivationPage = "https://example.com/browser/browser/base/content/test/social/share_activate.html";
registerCleanupFunction(function* () {
Services.prefs.clearUserPref("social.shareDirectory");
yield new Promise(resolve => SocialService.disableProvider(kShareProvider.origin, resolve));
yield new Promise(resolve => SocialService.disableProvider(kShareProviderInvalid.origin, resolve));
Assert.strictEqual(Social.providers.length, 0, "all providers should be removed");
SocialShare.uninit();
});
add_task(function* test_mozLoop_addSocialShareProvider() {
Services.prefs.setCharPref("social.shareDirectory", kActivationPage);
gHandlers.AddSocialShareProvider({}, () => {});
yield promiseWaitForCondition(() => SocialShare.panel.state == "open");
Assert.equal(SocialShare.iframe.getAttribute("src"), "about:providerdirectory",
"Provider directory page should be visible");
SocialShare.panel.hidePopup();
});
add_task(function* test_mozLoop_getSocialShareProviders() {
let providers;
gHandlers.GetSocialShareProviders({}, result => { providers = result; });
Assert.strictEqual(providers.length, 0, "Provider list should be empty initially");
// Add a provider.
yield new Promise(resolve => SocialService.addProvider(kShareProvider, resolve));
gHandlers.GetSocialShareProviders({}, result => { providers = result; });
Assert.strictEqual(providers.length, 1,
"The newly added provider should be part of the list");
let provider = providers[0];
Assert.strictEqual(provider.iconURL, kShareProvider.iconURL, "Icon URLs should match");
Assert.strictEqual(provider.name, kShareProvider.name, "Names should match");
Assert.strictEqual(provider.origin, kShareProvider.origin, "Origins should match");
// Add another provider that should not be picked up by Loop.
yield new Promise(resolve => SocialService.addProvider(kShareProviderInvalid, resolve));
gHandlers.GetSocialShareProviders({}, result => { providers = result; });
Assert.strictEqual(providers.length, 1,
"The newly added provider should not be part of the list");
// Let's add a valid second provider object.
let provider2 = Object.create(kShareProvider);
provider2.name = "Wildly different name";
provider2.origin = "https://example3.com";
yield new Promise(resolve => SocialService.addProvider(provider2, resolve));
gHandlers.GetSocialShareProviders({}, result => { providers = result; });
Assert.strictEqual(providers.length, 2,
"The newly added provider should be part of the list");
Assert.strictEqual(providers[1].name, provider2.name,
"Providers should be ordered alphabetically");
// Remove the second valid provider.
yield new Promise(resolve => SocialService.disableProvider(provider2.origin, resolve));
gHandlers.GetSocialShareProviders({}, result => { providers = result; });
Assert.strictEqual(providers.length, 1,
"The uninstalled provider should not be part of the list");
Assert.strictEqual(providers[0].name, kShareProvider.name, "Names should match");
});
add_task(function* test_mozLoop_socialShareRoom() {
gHandlers.SocialShareRoom({ data: [kShareProvider.origin, "https://someroom.com",
"Some Title"] }, () => {});
yield promiseWaitForCondition(() => SocialShare.panel.state == "open");
Assert.equal(SocialShare.iframe.getAttribute("origin"), kShareProvider.origin,
"Origins should match");
Assert.equal(SocialShare.iframe.getAttribute("src"), kShareProvider.shareURL,
"Provider's share page should be displayed");
SocialShare.panel.hidePopup();
});

View File

@ -9,7 +9,9 @@
var [, gHandlers] = LoopAPI.inspect();
var gConstants;
gHandlers.GetAllConstants({}, constants => { gConstants = constants; });
gHandlers.GetAllConstants({}, constants => {
gConstants = constants;
});
function resetMauPrefs() {
Services.prefs.clearUserPref("loop.mau.openPanel");
@ -36,65 +38,6 @@ add_task(function* test_initialize() {
});
});
/**
* Tests that enumerated bucket histograms exist and can be updated.
*/
add_task(function* test_mozLoop_telemetryAdd_buckets() {
let histogramId = "LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1";
let histogram = Services.telemetry.getHistogramById(histogramId);
let CONN_LENGTH = gConstants.TWO_WAY_MEDIA_CONN_LENGTH;
histogram.clear();
for (let value of [CONN_LENGTH.SHORTER_THAN_10S,
CONN_LENGTH.BETWEEN_10S_AND_30S,
CONN_LENGTH.BETWEEN_10S_AND_30S,
CONN_LENGTH.BETWEEN_30S_AND_5M,
CONN_LENGTH.BETWEEN_30S_AND_5M,
CONN_LENGTH.BETWEEN_30S_AND_5M,
CONN_LENGTH.MORE_THAN_5M,
CONN_LENGTH.MORE_THAN_5M,
CONN_LENGTH.MORE_THAN_5M,
CONN_LENGTH.MORE_THAN_5M]) {
gHandlers.TelemetryAddValue({ data: [histogramId, value] }, () => {});
}
let snapshot = histogram.snapshot();
is(snapshot.counts[CONN_LENGTH.SHORTER_THAN_10S], 1, "TWO_WAY_MEDIA_CONN_LENGTH.SHORTER_THAN_10S");
is(snapshot.counts[CONN_LENGTH.BETWEEN_10S_AND_30S], 2, "TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_10S_AND_30S");
is(snapshot.counts[CONN_LENGTH.BETWEEN_30S_AND_5M], 3, "TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_30S_AND_5M");
is(snapshot.counts[CONN_LENGTH.MORE_THAN_5M], 4, "TWO_WAY_MEDIA_CONN_LENGTH.MORE_THAN_5M");
});
add_task(function* test_mozLoop_telemetryAdd_sharingURL_buckets() {
let histogramId = "LOOP_SHARING_ROOM_URL";
let histogram = Services.telemetry.getHistogramById(histogramId);
const SHARING_TYPES = gConstants.SHARING_ROOM_URL;
histogram.clear();
for (let value of [SHARING_TYPES.COPY_FROM_PANEL,
SHARING_TYPES.COPY_FROM_CONVERSATION,
SHARING_TYPES.COPY_FROM_CONVERSATION,
SHARING_TYPES.EMAIL_FROM_CALLFAILED,
SHARING_TYPES.EMAIL_FROM_CALLFAILED,
SHARING_TYPES.EMAIL_FROM_CALLFAILED,
SHARING_TYPES.EMAIL_FROM_CONVERSATION,
SHARING_TYPES.EMAIL_FROM_CONVERSATION,
SHARING_TYPES.EMAIL_FROM_CONVERSATION,
SHARING_TYPES.EMAIL_FROM_CONVERSATION]) {
gHandlers.TelemetryAddValue({ data: [histogramId, value] }, () => {});
}
let snapshot = histogram.snapshot();
Assert.strictEqual(snapshot.counts[SHARING_TYPES.COPY_FROM_PANEL], 1,
"SHARING_ROOM_URL.COPY_FROM_PANEL");
Assert.strictEqual(snapshot.counts[SHARING_TYPES.COPY_FROM_CONVERSATION], 2,
"SHARING_ROOM_URL.COPY_FROM_CONVERSATION");
Assert.strictEqual(snapshot.counts[SHARING_TYPES.EMAIL_FROM_CALLFAILED], 3,
"SHARING_ROOM_URL.EMAIL_FROM_CALLFAILED");
Assert.strictEqual(snapshot.counts[SHARING_TYPES.EMAIL_FROM_CONVERSATION], 4,
"SHARING_ROOM_URL.EMAIL_FROM_CONVERSATION");
});
add_task(function* test_mozLoop_telemetryAdd_roomCreate_buckets() {
let histogramId = "LOOP_ROOM_CREATE";
let histogram = Services.telemetry.getHistogramById(histogramId);
@ -114,59 +57,6 @@ add_task(function* test_mozLoop_telemetryAdd_roomCreate_buckets() {
"SHARING_ROOM_URL.CREATE_FAIL");
});
add_task(function* test_mozLoop_telemetryAdd_roomDelete_buckets() {
let histogramId = "LOOP_ROOM_DELETE";
let histogram = Services.telemetry.getHistogramById(histogramId);
const ACTION_TYPES = gConstants.ROOM_DELETE;
histogram.clear();
for (let value of [ACTION_TYPES.DELETE_SUCCESS,
ACTION_TYPES.DELETE_FAIL,
ACTION_TYPES.DELETE_FAIL]) {
gHandlers.TelemetryAddValue({ data: [histogramId, value] }, () => {});
}
let snapshot = histogram.snapshot();
Assert.strictEqual(snapshot.counts[ACTION_TYPES.DELETE_SUCCESS], 1,
"SHARING_ROOM_URL.DELETE_SUCCESS");
Assert.strictEqual(snapshot.counts[ACTION_TYPES.DELETE_FAIL], 2,
"SHARING_ROOM_URL.DELETE_FAIL");
});
add_task(function* test_mozLoop_telemetryAdd_roomSessionWithChat() {
let histogramId = "LOOP_ROOM_SESSION_WITHCHAT";
let histogram = Services.telemetry.getHistogramById(histogramId);
histogram.clear();
let snapshot;
for (let i = 1; i < 4; ++i) {
gHandlers.TelemetryAddValue({ data: [histogramId, 1] }, () => {});
snapshot = histogram.snapshot();
Assert.strictEqual(snapshot.counts[0], i);
}
});
add_task(function* test_mozLoop_telemetryAdd_infobarActionButtons() {
let histogramId = "LOOP_INFOBAR_ACTION_BUTTONS";
let histogram = Services.telemetry.getHistogramById(histogramId);
const ACTION_TYPES = gConstants.SHARING_SCREEN;
histogram.clear();
for (let value of [ACTION_TYPES.PAUSED,
ACTION_TYPES.PAUSED,
ACTION_TYPES.RESUMED]) {
gHandlers.TelemetryAddValue({ data: [histogramId, value] }, () => {});
}
let snapshot = histogram.snapshot();
Assert.strictEqual(snapshot.counts[ACTION_TYPES.RESUMED], 1,
"SHARING_SCREEN.RESUMED");
Assert.strictEqual(snapshot.counts[ACTION_TYPES.PAUSED], 2,
"SHARING_SCREEN.PAUSED");
});
add_task(function* test_mozLoop_telemetryAdd_loopMauType_buckets() {
let histogramId = "LOOP_ACTIVITY_COUNTER";
let histogram = Services.telemetry.getHistogramById(histogramId);

View File

@ -9,7 +9,7 @@
<Description about="urn:mozilla:install-manifest">
<em:id>loop@mozilla.org</em:id>
<em:bootstrap>true</em:bootstrap>
<em:version>1.4.0</em:version>
<em:version>1.4.1</em:version>
<em:type>2</em:type>
<!-- Target Application this extension can install into,

View File

@ -11,7 +11,7 @@ CONTENT_SERVER_URL = environ.get("CONTENT_SERVER_URL") or \
LOOP_SERVER_URLS = {
"local": "http://localhost:" + str(LOOP_SERVER_PORT),
"dev": "https://loop-dev.stage.mozaws.net",
"dev": "https://loop.dev.mozaws.net",
"stage": "https://loop.stage.mozaws.net",
"prod": "https://loop.services.mozilla.com"
}

View File

@ -18,6 +18,11 @@ class LoopTestDriver():
def setUp(self, marionette):
self.marionette = marionette
# XXX This should be unnecessary once bug 1254132 is fixed.
def set_context(self, context):
self.context = context
self.marionette.set_context(context)
def wait_for_element_displayed(self, by, locator, timeout=None):
Wait(self.marionette, timeout,
ignored_exceptions=[NoSuchElementException, StaleElementException])\
@ -42,13 +47,25 @@ class LoopTestDriver():
.until(lambda e: element.is_enabled(),
message="Timed out waiting for element to be enabled")
def wait_for_element_attribute_to_be_false(self, element, attribute, timeout=10):
def wait_for_element_property_to_be_false(self, element, property, timeout=10):
# XXX We have to switch between get_attribute and get_property here as the
# content mode now required get_property for real properties of HTMLElements.
# However, in some places (e.g. switch_to_chatbox), we're still operating in
# a chrome mode. So we have to use get_attribute for these.
# Bug 1277065 should fix this for marionette, alternately this should go
# away when the e10s bug 1254132 is fixed.
def check_property(m):
if self.context == "content":
return not element.get_property(property)
return element.get_attribute(property) == "false"
Wait(self.marionette, timeout) \
.until(lambda e: element.get_attribute(attribute) == "false",
message="Timeout out waiting for " + attribute + " to be false")
.until(check_property,
message="Timeout out waiting for " + property + " to be false")
def open_panel(self):
self.marionette.set_context("chrome")
self.set_context("chrome")
self.marionette.switch_to_frame()
button = self.marionette.find_element(By.ID, "loop-button")
@ -56,13 +73,13 @@ class LoopTestDriver():
button.click()
def switch_to_panel(self):
self.marionette.set_context("chrome")
self.set_context("chrome")
# switch to the frame
frame = self.marionette.find_element(By.ID, "loop-panel-iframe")
self.marionette.switch_to_frame(frame)
def switch_to_chatbox(self):
self.marionette.set_context("chrome")
self.set_context("chrome")
self.marionette.switch_to_frame()
contentBox = "content"
@ -94,7 +111,7 @@ class LoopTestDriver():
copyLink.click()
def switch_to_standalone(self):
self.marionette.set_context("content")
self.set_context("content")
def load_homepage(self):
self.switch_to_standalone()
@ -128,8 +145,8 @@ class LoopTestDriver():
# Assumes the standalone or the conversation window is selected first.
def check_video(self, selector):
video = self.wait_for_element_displayed(By.CSS_SELECTOR, selector, 30)
self.wait_for_element_attribute_to_be_false(video, "paused")
self.assertEqual(video.get_attribute("ended"), "false")
self.wait_for_element_property_to_be_false(video, "paused")
self.wait_for_element_property_to_be_false(video, "ended")
def local_check_room_self_video(self):
self.switch_to_chatbox()

View File

@ -1,5 +1,7 @@
[DEFAULT]
run-if = buildapp == 'browser'
# app == 'Firefox' is used for running in the Loop repo.
# buildapp == 'browser' is used for mozilla-central & co.
run-if = buildapp == 'browser' || app == 'Firefox'
[test_1_browser_call.py]
[test_2_linkclicker.py]

View File

@ -147,38 +147,6 @@ class Test1BrowserCall(LoopTestDriver, MarionetteTestCase):
return self.marionette.execute_script(script, [chatbox])
def local_get_media_start_time(self):
return self.local_get_chatbox_window_expr(
"loop.conversation._sdkDriver._getTwoWayMediaStartTime()")
# XXX could be memoized
def local_get_media_start_time_uninitialized(self):
return self.local_get_chatbox_window_expr(
"loop.conversation._sdkDriver.CONNECTION_START_TIME_UNINITIALIZED"
)
def local_check_media_start_time_uninitialized(self):
self.assertEqual(
self.local_get_media_start_time(),
self.local_get_media_start_time_uninitialized(),
"media start time should be uninitialized before "
"link clicker enters room")
def local_check_media_start_time_initialized(self):
self.assertNotEqual(
self.local_get_media_start_time(),
self.local_get_media_start_time_uninitialized(),
"media start time should be initialized after "
"media is bidirectionally connected")
def local_check_connection_length_noted(self):
noted_calls = self.local_get_chatbox_window_expr(
"loop.conversation._sdkDriver._connectionLengthNotedCalls")
self.assertGreater(noted_calls, 0,
"OTSdkDriver._connectionLengthNotedCalls should be "
"> 0, noted_calls = " + str(noted_calls))
def local_close_conversation(self):
self.marionette.set_context("chrome")
self.marionette.switch_to_frame()
@ -216,9 +184,6 @@ class Test1BrowserCall(LoopTestDriver, MarionetteTestCase):
# Check the self video in the conversation window
self.local_check_room_self_video()
# make sure that the media start time is not initialized
self.local_check_media_start_time_uninitialized()
room_url = self.local_get_and_verify_room_url()
# load the link clicker interface into the current content browser
@ -231,10 +196,6 @@ class Test1BrowserCall(LoopTestDriver, MarionetteTestCase):
# Check text messaging
self.check_text_messaging()
# since bi-directional media is connected, make sure we've set
# the start time
self.local_check_media_start_time_initialized()
# Check that screenshare was automatically started
self.standalone_check_remote_screenshare()
@ -245,8 +206,6 @@ class Test1BrowserCall(LoopTestDriver, MarionetteTestCase):
# drops, rather than waiting until the window closes.
self.remote_leave_room()
self.local_check_connection_length_noted()
# Hangup on local will open feedback window first
self.local_close_conversation()
self.check_feedback_form()