merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-03-10 12:50:49 +01:00
Родитель c989894873 cc14fa87be
Коммит 451dae3178
29 изменённых файлов: 613 добавлений и 204 удалений

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

@ -1880,8 +1880,10 @@ pref("dom.ipc.reportProcessHangs", false);
pref("dom.ipc.reportProcessHangs", true);
#endif
#ifndef NIGHTLY_BUILD
// Disable reader mode by default.
pref("reader.parse-on-load.enabled", false);
#endif
// Disable ReadingList by default.
pref("browser.readinglist.enabled", false);

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

@ -221,8 +221,6 @@ let LoopCallsInternal = {
if (channelID == MozLoopService.channelIDs.callsFxA && MozLoopService.userProfile) {
this._getCalls(LOOP_SESSION_TYPE.FXA, version);
} else {
this._getCalls(LOOP_SESSION_TYPE.GUEST, version);
}
},

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

@ -623,6 +623,13 @@ function injectLoopAPI(targetWindow) {
}
},
TWO_WAY_MEDIA_CONN_LENGTH: {
enumerable: true,
get: function() {
return Cu.cloneInto(TWO_WAY_MEDIA_CONN_LENGTH, targetWindow);
}
},
fxAEnabled: {
enumerable: true,
get: function() {
@ -737,14 +744,14 @@ function injectLoopAPI(targetWindow) {
/**
* Adds a value to a telemetry histogram.
*
* @param {string} histogramId Name of the telemetry histogram to update.
* @param {integer} value Value to add to the histogram.
* @param {string} histogramId Name of the telemetry histogram to update.
* @param {string} value Label of bucket to increment in the histogram.
*/
telemetryAdd: {
telemetryAddKeyedValue: {
enumerable: true,
writable: true,
value: function(histogramId, value) {
Services.telemetry.getHistogramById(histogramId).add(value);
Services.telemetry.getKeyedHistogramById(histogramId).add(value);
}
},

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

@ -15,6 +15,20 @@ const LOOP_SESSION_TYPE = {
FXA: 2,
};
/***
* Buckets that we segment 2-way media connection length telemetry probes
* into.
*
* @type {{SHORTER_THAN_10S: string, BETWEEN_10S_AND_30S: string,
* BETWEEN_30S_AND_5M: string, MORE_THAN_5M: string}}
*/
const TWO_WAY_MEDIA_CONN_LENGTH = {
SHORTER_THAN_10S: "SHORTER_THAN_10S",
BETWEEN_10S_AND_30S: "BETWEEN_10S_AND_30S",
BETWEEN_30S_AND_5M: "BETWEEN_30S_AND_5M",
MORE_THAN_5M: "MORE_THAN_5M",
};
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
const PREF_LOG_LEVEL = "loop.debug.loglevel";
@ -28,7 +42,7 @@ Cu.import("resource://gre/modules/FxAccountsOAuthClient.jsm");
Cu.importGlobalProperties(["URL"]);
this.EXPORTED_SYMBOLS = ["MozLoopService", "LOOP_SESSION_TYPE"];
this.EXPORTED_SYMBOLS = ["MozLoopService", "LOOP_SESSION_TYPE", "TWO_WAY_MEDIA_CONN_LENGTH"];
XPCOMUtils.defineLazyModuleGetter(this, "injectLoopAPI",
"resource:///modules/loop/MozLoopAPI.jsm");
@ -157,37 +171,6 @@ let MozLoopServiceInternal = {
return initialDelay;
},
/**
* Gets the current latest expiry time for urls.
*
* In seconds since epoch.
*/
get expiryTimeSeconds() {
try {
return Services.prefs.getIntPref("loop.urlsExpiryTimeSeconds");
} catch (x) {
// It is ok for the pref not to exist.
return 0;
}
},
/**
* Sets the expiry time to either the specified time, or keeps it the same
* depending on which is latest.
*/
set expiryTimeSeconds(time) {
if (time > this.expiryTimeSeconds) {
Services.prefs.setIntPref("loop.urlsExpiryTimeSeconds", time);
}
},
/**
* Returns true if the expiry time is in the future.
*/
urlExpiryTimeIsInFuture: function() {
return this.expiryTimeSeconds * 1000 > Date.now();
},
/**
* Retrieves MozLoopService Firefox Accounts OAuth token.
*
@ -390,17 +373,20 @@ let MozLoopServiceInternal = {
let options = this.mocks.webSocket ? { mockWebSocket: this.mocks.webSocket } : {};
this.pushHandler.initialize(options); // This can be called more than once.
let callsID = sessionType == LOOP_SESSION_TYPE.GUEST ?
MozLoopService.channelIDs.callsGuest :
MozLoopService.channelIDs.callsFxA,
roomsID = sessionType == LOOP_SESSION_TYPE.GUEST ?
MozLoopService.channelIDs.roomsGuest :
MozLoopService.channelIDs.roomsFxA;
let regPromise = this.createNotificationChannel(
callsID, sessionType, "calls", LoopCalls.onNotification).then(() => {
return this.createNotificationChannel(
roomsID, sessionType, "rooms", roomsPushNotification)});
let regPromise;
if (sessionType == LOOP_SESSION_TYPE.GUEST) {
regPromise = this.createNotificationChannel(
MozLoopService.channelIDs.roomsGuest, sessionType, "rooms",
roomsPushNotification);
} else {
regPromise = this.createNotificationChannel(
MozLoopService.channelIDs.callsFxA, sessionType, "calls",
LoopCalls.onNotification).then(() => {
return this.createNotificationChannel(
MozLoopService.channelIDs.roomsFxA, sessionType, "rooms",
roomsPushNotification);
});
}
log.debug("assigning to deferredRegistrations for sessionType:", sessionType);
this.deferredRegistrations.set(sessionType, regPromise);
@ -587,11 +573,8 @@ let MozLoopServiceInternal = {
this.setError("login", error);
throw error;
});
} else if (this.urlExpiryTimeIsInFuture()) {
// If there are no Guest URLs in the future, don't use setError to notify the user since
// there isn't a need for a Guest registration at this time.
this.setError("registration", error);
}
this.setError("registration", error);
throw error;
};
@ -1058,7 +1041,6 @@ this.MozLoopService = {
// Channel ids that will be registered with the PushServer for notifications
return {
callsFxA: "25389583-921f-4169-a426-a4673658944b",
callsGuest: "801f754b-686b-43ec-bd83-1419bbf58388",
roomsFxA: "6add272a-d316-477c-8335-f00f73dfde71",
roomsGuest: "19d3f799-a8f3-4328-9822-b7cd02765832",
};
@ -1124,10 +1106,9 @@ this.MozLoopService = {
LoopRooms.on("joined", this.maybeResumeTourOnRoomJoined.bind(this));
// If expiresTime is not in the future and the user hasn't
// If there's no guest room created and the user hasn't
// previously authenticated then skip registration.
if (!MozLoopServiceInternal.urlExpiryTimeIsInFuture() &&
!LoopRooms.getGuestCreatedRoom() &&
if (!LoopRooms.getGuestCreatedRoom() &&
!MozLoopServiceInternal.fxAOAuthTokenData) {
return Promise.resolve("registration not needed");
}
@ -1204,11 +1185,10 @@ this.MozLoopService = {
});
try {
if (MozLoopServiceInternal.urlExpiryTimeIsInFuture() ||
LoopRooms.getGuestCreatedRoom()) {
if (LoopRooms.getGuestCreatedRoom()) {
yield this.promiseRegisteredWithServers(LOOP_SESSION_TYPE.GUEST);
} else {
log.debug("delayedInitialize: URL expiry time isn't in the future so not registering as a guest");
log.debug("delayedInitialize: Guest Room hasn't been created so not registering as a guest");
}
} catch (ex) {
log.debug("MozLoopService: Failure of guest registration", ex);
@ -1461,7 +1441,7 @@ this.MozLoopService = {
yield MozLoopServiceInternal.unregisterFromLoopServer(LOOP_SESSION_TYPE.FXA);
}
catch (err) {
throw err
throw err;
}
finally {
MozLoopServiceInternal.clearSessionToken(LOOP_SESSION_TYPE.FXA);

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

@ -66,6 +66,7 @@ loop.conversation = (function(mozL10n) {
client: this.props.client,
conversation: this.props.conversation,
sdk: this.props.sdk,
isDesktop: true,
conversationAppStore: this.props.conversationAppStore}
));
}
@ -120,8 +121,13 @@ loop.conversation = (function(mozL10n) {
var sdkDriver = new loop.OTSdkDriver({
isDesktop: true,
dispatcher: dispatcher,
sdk: OT
sdk: OT,
mozLoop: navigator.mozLoop
});
// expose for functional tests
loop.conversation._sdkDriver = sdkDriver;
var appVersionInfo = navigator.mozLoop.appVersionInfo;
var feedbackClient = new loop.FeedbackAPIClient(
navigator.mozLoop.getLoopPref("feedback.baseUrl"), {
@ -201,7 +207,15 @@ loop.conversation = (function(mozL10n) {
return {
AppControllerView: AppControllerView,
init: init
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
};
})(document.mozL10n);

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

@ -66,6 +66,7 @@ loop.conversation = (function(mozL10n) {
client={this.props.client}
conversation={this.props.conversation}
sdk={this.props.sdk}
isDesktop={true}
conversationAppStore={this.props.conversationAppStore}
/>);
}
@ -120,8 +121,13 @@ loop.conversation = (function(mozL10n) {
var sdkDriver = new loop.OTSdkDriver({
isDesktop: true,
dispatcher: dispatcher,
sdk: OT
sdk: OT,
mozLoop: navigator.mozLoop
});
// expose for functional tests
loop.conversation._sdkDriver = sdkDriver;
var appVersionInfo = navigator.mozLoop.appVersionInfo;
var feedbackClient = new loop.FeedbackAPIClient(
navigator.mozLoop.getLoopPref("feedback.baseUrl"), {
@ -201,7 +207,15 @@ loop.conversation = (function(mozL10n) {
return {
AppControllerView: AppControllerView,
init: init
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
};
})(document.mozL10n);

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

@ -347,10 +347,17 @@ loop.conversationViews = (function(mozL10n) {
conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel)
.isRequired,
sdk: React.PropTypes.object.isRequired,
isDesktop: React.PropTypes.bool,
conversationAppStore: React.PropTypes.instanceOf(
loop.store.ConversationAppStore).isRequired
},
getDefaultProps: function() {
return {
isDesktop: false
};
},
getInitialState: function() {
return {
callFailed: false, // XXX this should be removed when bug 1047410 lands.
@ -403,6 +410,7 @@ loop.conversationViews = (function(mozL10n) {
return (
React.createElement(sharedViews.ConversationView, {
isDesktop: this.props.isDesktop,
initiate: true,
sdk: this.props.sdk,
model: this.props.conversation,

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

@ -347,10 +347,17 @@ loop.conversationViews = (function(mozL10n) {
conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel)
.isRequired,
sdk: React.PropTypes.object.isRequired,
isDesktop: React.PropTypes.bool,
conversationAppStore: React.PropTypes.instanceOf(
loop.store.ConversationAppStore).isRequired
},
getDefaultProps: function() {
return {
isDesktop: false
};
},
getInitialState: function() {
return {
callFailed: false, // XXX this should be removed when bug 1047410 lands.
@ -403,6 +410,7 @@ loop.conversationViews = (function(mozL10n) {
return (
<sharedViews.ConversationView
isDesktop={this.props.isDesktop}
initiate={true}
sdk={this.props.sdk}
model={this.props.conversation}

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

@ -228,7 +228,8 @@ loop.store = loop.store || {};
"retryCall",
"mediaConnected",
"setMute",
"fetchRoomEmailLink"
"fetchRoomEmailLink",
"windowUnload"
]);
this.setStoreState({
@ -359,6 +360,15 @@ loop.store = loop.store || {};
}.bind(this));
},
/**
* Called when the window is unloaded, either by code, or by the user
* explicitly closing it. Expected to do any necessary housekeeping, such
* as shutting down the call cleanly and adding any relevant telemetry data.
*/
windowUnload: function() {
this._endSession();
},
/**
* Obtains the outgoing call data from the server and handles the
* result.

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

@ -27,7 +27,12 @@ loop.OTSdkDriver = (function() {
this.dispatcher = options.dispatcher;
this.sdk = options.sdk;
// Note that this will only be defined and usable in a desktop-local
// context, not in the standalone web client.
this.mozLoop = options.mozLoop;
this.connections = {};
this.connectionStartTime = this.CONNECTION_START_TIME_UNINITIALIZED;
this.dispatcher.register(this, [
"setupStreamElements",
@ -51,6 +56,9 @@ loop.OTSdkDriver = (function() {
};
OTSdkDriver.prototype = {
CONNECTION_START_TIME_UNINITIALIZED: -1,
CONNECTION_START_TIME_ALREADY_NOTED: -2,
/**
* Clones the publisher config into a new object, as the sdk modifies the
* properties object.
@ -228,12 +236,15 @@ loop.OTSdkDriver = (function() {
delete this.publisher;
}
this._noteConnectionLengthIfNeeded(this.connectionStartTime, performance.now());
// Also, tidy these variables ready for next time.
delete this._sessionConnected;
delete this._publisherReady;
delete this._publishedLocalStream;
delete this._subscribedRemoteStream;
this.connections = {};
this.connectionStartTime = this.CONNECTION_START_TIME_UNINITIALIZED;
},
/**
@ -297,6 +308,7 @@ loop.OTSdkDriver = (function() {
if (connection && (connection.id in this.connections)) {
delete this.connections[connection.id];
}
this._noteConnectionLengthIfNeeded(this.connectionStartTime, performance.now());
this.dispatcher.dispatch(new sharedActions.RemotePeerDisconnected({
peerHungup: event.reason === "clientDisconnected"
}));
@ -323,6 +335,8 @@ loop.OTSdkDriver = (function() {
return;
}
this._noteConnectionLengthIfNeeded(this.connectionStartTime,
performance.now());
this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
reason: reason
}));
@ -394,6 +408,7 @@ loop.OTSdkDriver = (function() {
this._subscribedRemoteStream = true;
if (this._checkAllStreamsConnected()) {
this.connectionStartTime = performance.now();
this.dispatcher.dispatch(new sharedActions.MediaConnected());
}
},
@ -513,6 +528,7 @@ loop.OTSdkDriver = (function() {
// Now record the fact, and check if we've got all media yet.
this._publishedLocalStream = true;
if (this._checkAllStreamsConnected()) {
this.connectionStartTime = performance.now();
this.dispatcher.dispatch(new sharedActions.MediaConnected());
}
}
@ -544,6 +560,72 @@ loop.OTSdkDriver = (function() {
this.dispatcher.dispatch(new sharedActions.ScreenSharingState({
state: SCREEN_SHARE_STATES.INACTIVE
}));
},
/**
* 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 this.connectionStartTime to
* this.CONNECTION_START_TIME_ALREADY_NOTED.
*
* @param {number} callLengthSeconds the call length in seconds
* @private
*/
_noteConnectionLength: function(callLengthSeconds) {
var bucket = this.mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.SHORTER_THAN_10S;
if (callLengthSeconds >= 10 && callLengthSeconds <= 30) {
bucket = this.mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_10S_AND_30S;
} else if (callLengthSeconds > 30 && callLengthSeconds <= 300) {
bucket = this.mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_30S_AND_5M;
} else if (callLengthSeconds > 300) {
bucket = this.mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.MORE_THAN_5M;
}
this.mozLoop.telemetryAddKeyedValue("LOOP_TWO_WAY_MEDIA_CONN_LENGTH",
bucket);
this.connectionStartTime = this.CONNECTION_START_TIME_ALREADY_NOTED;
this._connectionLengthNotedCalls++;
},
/**
* 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.mozLoop is not defined, we're assumed to be running in the
* standalone client and return immediately.
*
* @param {number} startTime in milliseconds
* @param {number} endTime in milliseconds
* @private
*/
_noteConnectionLengthIfNeeded: function(startTime, endTime) {
if (!this.mozLoop) {
return;
}
if (startTime == this.CONNECTION_START_TIME_ALREADY_NOTED ||
startTime == this.CONNECTION_START_TIME_UNINITIALIZED ||
startTime > endTime) {
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);
}
};

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

@ -251,12 +251,14 @@ loop.shared.views = (function(_, l10n) {
sdk: React.PropTypes.object.isRequired,
video: React.PropTypes.object,
audio: React.PropTypes.object,
initiate: React.PropTypes.bool
initiate: React.PropTypes.bool,
isDesktop: React.PropTypes.bool
},
getDefaultProps: function() {
return {
initiate: true,
isDesktop: false,
video: {enabled: true, visible: true},
audio: {enabled: true, visible: true}
};
@ -271,6 +273,23 @@ loop.shared.views = (function(_, l10n) {
componentDidMount: function() {
if (this.props.initiate) {
/**
* XXX This is a workaround for desktop machines that do not have a
* camera installed. As we don't yet have device enumeration, when
* we do, this can be removed (bug 1138851), and the sdk should handle it.
*/
if (this.props.isDesktop &&
!window.MediaStreamTrack.getSources) {
// If there's no getSources function, the sdk defines its own and caches
// the result. So here we define the "normal" one which doesn't get cached, so
// we can change it later.
window.MediaStreamTrack.getSources = function(callback) {
callback([{kind: "audio"}, {kind: "video"}]);
};
}
this.listenTo(this.props.sdk, "exception", this._handleSdkException.bind(this));
this.listenTo(this.props.model, "session:connected",
this._onSessionConnected);
this.listenTo(this.props.model, "session:stream-created",
@ -317,6 +336,35 @@ loop.shared.views = (function(_, l10n) {
}));
},
/**
* Handles the SDK Exception event.
*
* https://tokbox.com/opentok/libraries/client/js/reference/ExceptionEvent.html
*
* @param {ExceptionEvent} event
*/
_handleSdkException: function(event) {
/**
* XXX This is a workaround for desktop machines that do not have a
* camera installed. As we don't yet have device enumeration, when
* we do, this can be removed (bug 1138851), and the sdk should handle it.
*/
if (this.publisher &&
event.code === OT.ExceptionCodes.UNABLE_TO_PUBLISH &&
event.message === "GetUserMedia" &&
this.state.video.enabled) {
this.state.video.enabled = false;
window.MediaStreamTrack.getSources = function(callback) {
callback([{kind: "audio"}]);
};
this.stopListening(this.publisher);
this.publisher.destroy();
this.startPublishing();
}
},
/**
* Publishes remote streams available once a session is connected.
*

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

@ -251,12 +251,14 @@ loop.shared.views = (function(_, l10n) {
sdk: React.PropTypes.object.isRequired,
video: React.PropTypes.object,
audio: React.PropTypes.object,
initiate: React.PropTypes.bool
initiate: React.PropTypes.bool,
isDesktop: React.PropTypes.bool
},
getDefaultProps: function() {
return {
initiate: true,
isDesktop: false,
video: {enabled: true, visible: true},
audio: {enabled: true, visible: true}
};
@ -271,6 +273,23 @@ loop.shared.views = (function(_, l10n) {
componentDidMount: function() {
if (this.props.initiate) {
/**
* XXX This is a workaround for desktop machines that do not have a
* camera installed. As we don't yet have device enumeration, when
* we do, this can be removed (bug 1138851), and the sdk should handle it.
*/
if (this.props.isDesktop &&
!window.MediaStreamTrack.getSources) {
// If there's no getSources function, the sdk defines its own and caches
// the result. So here we define the "normal" one which doesn't get cached, so
// we can change it later.
window.MediaStreamTrack.getSources = function(callback) {
callback([{kind: "audio"}, {kind: "video"}]);
};
}
this.listenTo(this.props.sdk, "exception", this._handleSdkException.bind(this));
this.listenTo(this.props.model, "session:connected",
this._onSessionConnected);
this.listenTo(this.props.model, "session:stream-created",
@ -317,6 +336,35 @@ loop.shared.views = (function(_, l10n) {
}));
},
/**
* Handles the SDK Exception event.
*
* https://tokbox.com/opentok/libraries/client/js/reference/ExceptionEvent.html
*
* @param {ExceptionEvent} event
*/
_handleSdkException: function(event) {
/**
* XXX This is a workaround for desktop machines that do not have a
* camera installed. As we don't yet have device enumeration, when
* we do, this can be removed (bug 1138851), and the sdk should handle it.
*/
if (this.publisher &&
event.code === OT.ExceptionCodes.UNABLE_TO_PUBLISH &&
event.message === "GetUserMedia" &&
this.state.video.enabled) {
this.state.video.enabled = false;
window.MediaStreamTrack.getSources = function(callback) {
callback([{kind: "audio"}]);
};
this.stopListening(this.publisher);
this.publisher.destroy();
this.startPublishing();
}
},
/**
* Publishes remote streams available once a session is connected.
*

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

@ -103,6 +103,7 @@ class Test1BrowserCall(MarionetteTestCase):
self.assertEqual(media_container.tag_name, "div", "expect a video container")
def local_get_and_verify_room_url(self):
self.switch_to_chatbox()
button = self.wait_for_element_displayed(By.CLASS_NAME, "btn-copy")
button.click()
@ -111,8 +112,8 @@ class Test1BrowserCall(MarionetteTestCase):
room_url = pyperclip.paste()
self.assertIn(urlparse.urlparse(room_url).scheme, ['http', 'https'],
"room URL returned by server " + room_url +
" has invalid scheme")
"room URL returned by server: '" + room_url +
"' has invalid scheme")
return room_url
def standalone_load_and_join_room(self, url):
@ -152,7 +153,8 @@ class Test1BrowserCall(MarionetteTestCase):
self.switch_to_standalone()
self.check_video(".media .screen .OT_subscriber .OT_widget-container")
def local_leave_room_and_verify_feedback(self):
def remote_leave_room_and_verify_feedback(self):
self.switch_to_standalone()
button = self.marionette.find_element(By.CLASS_NAME, "btn-hangup")
button.click()
@ -161,6 +163,66 @@ class Test1BrowserCall(MarionetteTestCase):
feedback_form = self.wait_for_element_displayed(By.CLASS_NAME, "faces")
self.assertEqual(feedback_form.tag_name, "div", "expect feedback form")
def local_get_chatbox_window_expr(self, expr):
"""
:expr: a sub-expression which must begin with a property of the
global content window (e.g. "location.path")
:return: the value of the given sub-expression as evaluated in the
chatbox content window
"""
self.marionette.set_context("chrome")
self.marionette.switch_to_frame()
# XXX should be using wait_for_element_displayed, but need to wait
# for Marionette bug 1094246 to be fixed.
chatbox = self.wait_for_element_exists(By.TAG_NAME, 'chatbox')
script = '''
let chatBrowser = document.getAnonymousElementByAttribute(
arguments[0], 'class',
'chat-frame')
// note that using wrappedJSObject waives X-ray vision, which
// has security implications, but because we trust the code
// running in the chatbox, it should be reasonably safe
let chatGlobal = chatBrowser.contentWindow.wrappedJSObject;
return chatGlobal.''' + expr
return self.marionette.execute_script(script, [chatbox])
def local_get_media_start_time(self):
return self.local_get_chatbox_window_expr(
"loop.conversation._sdkDriver.connectionStartTime")
# 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")
def test_1_browser_call(self):
self.switch_to_panel()
@ -169,6 +231,9 @@ class Test1BrowserCall(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
@ -178,13 +243,23 @@ class Test1BrowserCall(MarionetteTestCase):
self.standalone_check_remote_video()
self.local_check_remote_video()
# since bi-directional media is connected, make sure we've set
# the start time
self.local_check_media_start_time_initialized()
# XXX To enable this, we either need to navigate the permissions prompt
# or have a route where we don't need the permissions prompt.
# self.local_enable_screenshare()
# self.standalone_check_remote_screenshare()
# hangup the call
self.local_leave_room_and_verify_feedback()
# We hangup on the remote side, because this also leaves the
# local chatbox with the local publishing media still connected,
# which means that the local_check_connection_length below
# verifies that the connection is noted at the time the remote media
# drops, rather than waiting until the window closes.
self.remote_leave_room_and_verify_feedback()
self.local_check_connection_length_noted()
def tearDown(self):
self.loop_test_servers.shutdown()

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

@ -20,22 +20,30 @@ add_task(function* test_initialize() {
});
/**
* Tests that boolean histograms exist and can be updated.
* Tests that enumerated bucket histograms exist and can be updated.
*/
add_task(function* test_mozLoop_telemetryAdd_boolean() {
for (let histogramId of [
"LOOP_CLIENT_CALL_URL_REQUESTS_SUCCESS",
"LOOP_CLIENT_CALL_URL_SHARED",
]) {
let histogram = Services.telemetry.getHistogramById(histogramId);
add_task(function* test_mozLoop_telemetryAdd_buckets() {
let histogramId = "LOOP_TWO_WAY_MEDIA_CONN_LENGTH";
let histogram = Services.telemetry.getKeyedHistogramById(histogramId);
let CONN_LENGTH = gMozLoopAPI.TWO_WAY_MEDIA_CONN_LENGTH;
histogram.clear();
for (let value of [false, false, true]) {
gMozLoopAPI.telemetryAdd(histogramId, value);
}
let snapshot = histogram.snapshot();
is(snapshot.counts[0], 2, "snapshot.counts[0] == 2");
is(snapshot.counts[1], 1, "snapshot.counts[1] == 1");
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]) {
gMozLoopAPI.telemetryAddKeyedValue(histogramId, value);
}
let snapshot = histogram.snapshot();
is(snapshot["SHORTER_THAN_10S"].sum, 1, "TWO_WAY_MEDIA_CONN_LENGTH.SHORTER_THAN_10S");
is(snapshot["BETWEEN_10S_AND_30S"].sum, 2, "TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_10S_AND_30S");
is(snapshot["BETWEEN_30S_AND_5M"].sum, 3, "TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_30S_AND_5M");
is(snapshot["MORE_THAN_5M"].sum, 4, "TWO_WAY_MEDIA_CONN_LENGTH.MORE_THAN_5M");
});

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

@ -770,6 +770,14 @@ describe("loop.store.ConversationStore", function () {
});
});
describe("#windowUnload", function() {
it("should disconnect from the servers via the sdk", function() {
store.windowUnload();
sinon.assert.calledOnce(sdkDriver.disconnectSession);
});
});
describe("Events", function() {
describe("Websocket progress", function() {
beforeEach(function() {

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

@ -12,7 +12,7 @@ describe("loop.OTSdkDriver", function () {
var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES;
var sandbox;
var dispatcher, driver, publisher, sdk, session, sessionData;
var dispatcher, driver, mozLoop, publisher, sdk, session, sessionData;
var fakeLocalElement, fakeRemoteElement, fakeScreenElement;
var publisherConfig, fakeEvent;
@ -64,9 +64,20 @@ describe("loop.OTSdkDriver", function () {
}
};
mozLoop = {
telemetryAddKeyedValue: sinon.stub(),
TWO_WAY_MEDIA_CONN_LENGTH: {
SHORTER_THAN_10S: "SHORTER_THAN_10S",
BETWEEN_10S_AND_30S: "BETWEEN_10S_AND_30S",
BETWEEN_30S_AND_5M: "BETWEEN_30S_AND_5M",
MORE_THAN_5M: "MORE_THAN_5M"
}
};
driver = new loop.OTSdkDriver({
dispatcher: dispatcher,
sdk: sdk
sdk: sdk,
mozLoop: mozLoop
});
});
@ -86,6 +97,12 @@ describe("loop.OTSdkDriver", function () {
new loop.OTSdkDriver({dispatcher: dispatcher});
}).to.Throw(/sdk/);
});
it("should initialize the connectionStartTime to 'uninitialized'", function() {
var driver = new loop.OTSdkDriver({sdk: sdk, dispatcher: dispatcher, mozLoop: mozLoop});
expect(driver.connectionStartTime).to.eql(driver.CONNECTION_START_TIME_UNINITIALIZED);
});
});
describe("#setupStreamElements", function() {
@ -293,7 +310,7 @@ describe("loop.OTSdkDriver", function () {
});
});
describe("#disconnectionSession", function() {
describe("#disconnectSession", function() {
it("should disconnect the session", function() {
driver.session = session;
@ -309,6 +326,94 @@ describe("loop.OTSdkDriver", function () {
sinon.assert.calledOnce(publisher.destroy);
});
it("should call _noteConnectionLengthIfNeeded with connection duration", function() {
driver.session = session;
var startTime = 1;
var endTime = 3;
driver.connectionStartTime = startTime;
sandbox.stub(performance, "now").returns(endTime);
sandbox.stub(driver, "_noteConnectionLengthIfNeeded");
driver.disconnectSession();
sinon.assert.calledWith(driver._noteConnectionLengthIfNeeded, startTime,
endTime);
});
it("should reset the connectionStartTime", function() {
driver.session = session;
var startTime = 1;
driver.connectionStartTime = startTime;
sandbox.stub(performance, "now");
sandbox.stub(driver, "_noteConnectionLengthIfNeeded");
driver.disconnectSession();
expect(driver.connectionStartTime).to.eql(driver.CONNECTION_START_TIME_UNINITIALIZED);
});
});
describe("#_noteConnectionLengthIfNeeded", function() {
var startTimeMS;
beforeEach(function() {
startTimeMS = 1;
driver.connectionStartTime = startTimeMS;
});
it("should set connectionStartTime to CONNECTION_START_TIME_ALREADY_NOTED", function() {
var endTimeMS = 3;
driver._noteConnectionLengthIfNeeded(startTimeMS, endTimeMS);
expect(driver.connectionStartTime).to.eql(driver.CONNECTION_START_TIME_ALREADY_NOTED);
});
it("should call mozLoop.noteConnectionLength with SHORTER_THAN_10S for calls less than 10s", function() {
var endTimeMS = 9000;
driver._noteConnectionLengthIfNeeded(startTimeMS, endTimeMS);
sinon.assert.calledOnce(mozLoop.telemetryAddKeyedValue);
sinon.assert.calledWith(mozLoop.telemetryAddKeyedValue,
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH",
mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.SHORTER_THAN_10S);
});
it("should call mozLoop.noteConnectionLength with BETWEEN_10S_AND_30S for 15s calls",
function() {
var endTimeMS = 15000;
driver._noteConnectionLengthIfNeeded(startTimeMS, endTimeMS);
sinon.assert.calledOnce(mozLoop.telemetryAddKeyedValue);
sinon.assert.calledWith(mozLoop.telemetryAddKeyedValue,
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH",
mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_10S_AND_30S);
});
it("should call mozLoop.noteConnectionLength with BETWEEN_30S_AND_5M for 60s calls",
function() {
var endTimeMS = 60 * 1000;
driver._noteConnectionLengthIfNeeded(startTimeMS, endTimeMS);
sinon.assert.calledOnce(mozLoop.telemetryAddKeyedValue);
sinon.assert.calledWith(mozLoop.telemetryAddKeyedValue,
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH",
mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_30S_AND_5M);
});
it("should call mozLoop.noteConnectionLength with MORE_THAN_5M for 10m calls", function() {
var endTimeMS = 10 * 60 * 1000;
driver._noteConnectionLengthIfNeeded(startTimeMS, endTimeMS);
sinon.assert.calledOnce(mozLoop.telemetryAddKeyedValue);
sinon.assert.calledWith(mozLoop.telemetryAddKeyedValue,
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH",
mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.MORE_THAN_5M);
});
});
describe("#forceDisconnectAll", function() {
@ -388,6 +493,23 @@ describe("loop.OTSdkDriver", function () {
sinon.assert.calledWithMatch(dispatcher.dispatch,
sinon.match.hasOwn("peerHungup", false));
});
it("should call _noteConnectionLengthIfNeeded with connection duration", function() {
driver.session = session;
var startTime = 1;
var endTime = 3;
driver.connectionStartTime = 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() {
@ -416,6 +538,23 @@ describe("loop.OTSdkDriver", function () {
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.connectionStartTime = startTime;
sandbox.stub(performance, "now").returns(endTime);
sandbox.stub(driver, "_noteConnectionLengthIfNeeded");
session.trigger("sessionDisconnected", {
reason: "networkDisconnected"
});
sinon.assert.calledWith(driver._noteConnectionLengthIfNeeded, startTime,
endTime);
});
});
describe("streamCreated (publisher/local)", function() {
@ -479,7 +618,7 @@ describe("loop.OTSdkDriver", function () {
fakeStream, fakeScreenElement, publisherConfig);
});
it("should dispach a mediaConnected action if both streams are up", function() {
it("should dispatch a mediaConnected action if both streams are up", function() {
driver._publishedLocalStream = true;
session.trigger("streamCreated", {stream: fakeStream});
@ -490,6 +629,17 @@ describe("loop.OTSdkDriver", function () {
sinon.match.hasOwn("name", "mediaConnected"));
});
it("should store the start time when both streams are up", function() {
driver._publishedLocalStream = true;
var startTime = 1;
sandbox.stub(performance, "now").returns(startTime);
session.trigger("streamCreated", {stream: fakeStream});
expect(driver.connectionStartTime).to.eql(startTime);
});
it("should not dispatch a mediaConnected action for screen sharing streams",
function() {
driver._publishedLocalStream = true;

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

@ -344,7 +344,8 @@ describe("loop.shared.views", function() {
}, Backbone.Events);
fakeSDK = {
initPublisher: sandbox.stub().returns(fakePublisher),
initSession: sandbox.stub().returns(fakeSession)
initSession: sandbox.stub().returns(fakeSession),
on: sandbox.stub()
};
model = new sharedModels.ConversationModel(fakeSessionData, {
sdk: fakeSDK

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

@ -126,7 +126,9 @@ describe("loop.webapp", function() {
client: client,
conversation: conversation,
notifications: notifications,
sdk: {},
sdk: {
on: sandbox.stub()
},
dispatcher: dispatcher
});
});

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

@ -32,6 +32,7 @@ Services.prefs.setBoolPref("loop.enabled", true);
// Cleanup function for all tests
do_register_cleanup(() => {
Services.prefs.clearUserPref("loop.enabled");
MozLoopService.errors.clear();
});
@ -50,6 +51,19 @@ function setupFakeLoopServer() {
});
}
/**
* Sets up the userProfile to make the service think we're logged into FxA.
*/
function setupFakeFxAUserProfile() {
MozLoopServiceInternal.fxAOAuthTokenData = { token_type: "bearer" };
MozLoopServiceInternal.fxAOAuthProfile = { email: "fake@invalid.com" };
do_register_cleanup(function() {
MozLoopServiceInternal.fxAOAuthTokenData = null;
MozLoopServiceInternal.fxAOAuthProfile = null;
});
}
function waitForCondition(aConditionFn, aMaxTries=50, aCheckInterval=100) {
function tryAgain() {
function tryNow() {

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

@ -22,55 +22,6 @@ let msgHandler = function(msg) {
}
};
add_task(function* test_busy_2guest_calls() {
actionReceived = false;
mockPushHandler.registrationPushURL = kEndPointUrl;
yield MozLoopService.promiseRegisteredWithServers(LOOP_SESSION_TYPE.GUEST);
let opened = 0;
let windowId;
Chat.open = function(contentWindow, origin, title, url) {
opened++;
windowId = url.match(/about:loopconversation\#(\d+)$/)[1];
};
mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
yield waitForCondition(() => { return actionReceived && opened > 0; }).then(() => {
do_check_true(opened === 1, "should open only one chat window");
do_check_true(actionReceived, "should respond with busy/reject to second call");
LoopCalls.clearCallInProgress(windowId);
}, () => {
do_throw("should have opened a chat window for first call and rejected second call");
});
});
add_task(function* test_busy_1fxa_1guest_calls() {
actionReceived = false;
yield MozLoopService.promiseRegisteredWithServers(LOOP_SESSION_TYPE.GUEST);
yield MozLoopService.promiseRegisteredWithServers(LOOP_SESSION_TYPE.FXA);
let opened = 0;
let windowId;
Chat.open = function(contentWindow, origin, title, url) {
opened++;
windowId = url.match(/about:loopconversation\#(\d+)$/)[1];
};
mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA);
mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
yield waitForCondition(() => { return actionReceived && opened > 0; }).then(() => {
do_check_true(opened === 1, "should open only one chat window");
do_check_true(actionReceived, "should respond with busy/reject to second call");
LoopCalls.clearCallInProgress(windowId);
}, () => {
do_throw("should have opened a chat window for first call and rejected second call");
});
});
add_task(function* test_busy_2fxa_calls() {
actionReceived = false;
@ -95,31 +46,6 @@ add_task(function* test_busy_2fxa_calls() {
});
});
add_task(function* test_busy_1guest_1fxa_calls() {
actionReceived = false;
yield MozLoopService.promiseRegisteredWithServers(LOOP_SESSION_TYPE.GUEST);
yield MozLoopService.promiseRegisteredWithServers(LOOP_SESSION_TYPE.FXA);
let opened = 0;
let windowId;
Chat.open = function(contentWindow, origin, title, url) {
opened++;
windowId = url.match(/about:loopconversation\#(\d+)$/)[1];
};
mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA);
yield waitForCondition(() => { return actionReceived && opened > 0; }).then(() => {
do_check_true(opened === 1, "should open only one chat window");
do_check_true(actionReceived, "should respond with busy/reject to second call");
LoopCalls.clearCallInProgress(windowId);
}, () => {
do_throw("should have opened a chat window for first call and rejected second call");
});
});
function run_test() {
setupFakeLoopServer();
@ -134,6 +60,8 @@ function run_test() {
Services.io.offline = false;
mockPushHandler.registrationPushURL = kEndPointUrl;
// For each notification received from the PushServer, MozLoopService will first query
// for any pending calls on the FxA hawk session and then again using the guest session.
// A pair of response objects in the callsResponses array will be consumed for each

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

@ -33,13 +33,13 @@ add_test(function test_do_not_disturb_disabled_should_open_chat_window() {
mockPushHandler.registrationPushURL = kEndPointUrl;
MozLoopService.promiseRegisteredWithServers().then(() => {
MozLoopService.promiseRegisteredWithServers(LOOP_SESSION_TYPE.FXA).then(() => {
let opened = false;
Chat.open = function() {
opened = true;
};
mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA);
waitForCondition(function() opened).then(() => {
run_next_test();
@ -58,7 +58,7 @@ add_test(function test_do_not_disturb_enabled_shouldnt_open_chat_window() {
opened = true;
};
mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA);
do_timeout(500, function() {
do_check_false(opened, "should not open a chat window");
@ -69,6 +69,8 @@ add_test(function test_do_not_disturb_enabled_shouldnt_open_chat_window() {
function run_test() {
setupFakeLoopServer();
setupFakeFxAUserProfile();
loopServer.registerPathHandler("/registration", (request, response) => {
response.setStatusLine(null, 200, "OK");
response.processAsync();

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

@ -173,14 +173,14 @@ add_task(cleanup_between_tests);
function run_test() {
setupFakeLoopServer();
// Set the expiry time one hour in the future so that an error is shown when the guest session expires.
MozLoopServiceInternal.expiryTimeSeconds = (Date.now() / 1000) + 3600;
Services.prefs.setBoolPref("loop.createdRoom", true);
do_register_cleanup(() => {
Services.prefs.clearUserPref("loop.hawk-session-token");
Services.prefs.clearUserPref("loop.hawk-session-token.fxa");
Services.prefs.clearUserPref("loop.urlsExpiryTimeSeconds");
Services.prefs.clearUserPref("network.dns.offline-localhost");
Services.prefs.clearUserPref("loop.createdRoom");
MozLoopService.errors.clear();
});

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

@ -18,35 +18,31 @@ add_task(function test_initialize_no_expiry() {
});
/**
* Tests that registration doesn't happen when the expiry time is
* in the past.
* Tests that registration doesn't happen when there has been no
* room created.
*/
add_task(function test_initialize_expiry_past() {
// Set time to be 2 seconds in the past.
let nowSeconds = Date.now() / 1000;
Services.prefs.setIntPref("loop.urlsExpiryTimeSeconds", nowSeconds - 2);
add_task(function test_initialize_no_guest_rooms() {
Services.prefs.setBoolPref("loop.createdRoom", false);
startTimerCalled = false;
MozLoopService.initialize();
Assert.equal(startTimerCalled, false,
"should not register when expiry time is in past");
"should not register when no guest rooms have been created");
});
/**
* Tests that registration happens when the expiry time is in
* the future.
*/
add_task(function test_initialize_starts_timer() {
// Set time to be 1 minute in the future
let nowSeconds = Date.now() / 1000;
Services.prefs.setIntPref("loop.urlsExpiryTimeSeconds", nowSeconds + 60);
add_task(function test_initialize_with_guest_rooms() {
Services.prefs.setBoolPref("loop.createdRoom", true);
startTimerCalled = false;
MozLoopService.initialize();
Assert.equal(startTimerCalled, true,
"should start the timer when expiry time is in the future");
"should start the timer when guest rooms have been created");
});
function run_test() {
@ -58,5 +54,9 @@ function run_test() {
startTimerCalled = true;
};
do_register_cleanup(function() {
Services.prefs.clearUserPref("loop.createdRoom");
});
run_next_test();
}

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

@ -12,13 +12,13 @@ add_test(function test_openChatWindow_on_notification() {
mockPushHandler.registrationPushURL = kEndPointUrl;
MozLoopService.promiseRegisteredWithServers().then(() => {
MozLoopService.promiseRegisteredWithServers(LOOP_SESSION_TYPE.FXA).then(() => {
let opened = false;
Chat.open = function() {
opened = true;
};
mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA);
waitForCondition(function() opened).then(() => {
do_check_true(opened, "should open a chat window");
@ -37,6 +37,8 @@ add_test(function test_openChatWindow_on_notification() {
function run_test() {
setupFakeLoopServer();
setupFakeFxAUserProfile();
loopServer.registerPathHandler("/registration", (request, response) => {
response.setStatusLine(null, 200, "OK");
response.processAsync();

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

@ -59,12 +59,11 @@ function run_test() {
response.setStatusLine(null, 200, "OK");
});
let nowSeconds = Date.now() / 1000;
Services.prefs.setIntPref("loop.urlsExpiryTimeSeconds", nowSeconds + 60);
Services.prefs.setBoolPref("loop.createdRoom", true);
do_register_cleanup(function() {
Services.prefs.clearUserPref("loop.hawk-session-token");
Services.prefs.clearUserPref("loop.urlsExpiryTimeSeconds");
Services.prefs.clearUserPref("loop.createdRoom");
});
run_next_test();

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

@ -13,17 +13,17 @@ const FAKE_FXA_PROFILE = JSON.stringify({
});
const LOOP_FXA_TOKEN_PREF = "loop.fxa_oauth.tokendata";
const LOOP_FXA_PROFILE_PREF = "loop.fxa_oauth.profile";
const LOOP_URL_EXPIRY_PREF = "loop.urlsExpiryTimeSeconds";
const LOOP_CREATED_ROOM_PREF = "loop.createdRoom";
const LOOP_INITIAL_DELAY_PREF = "loop.initialDelay";
/**
* This file is to test restart+reauth.
*/
add_task(function test_initialize_with_expired_urls_and_no_auth_token() {
add_task(function test_initialize_with_no_guest_rooms_and_no_auth_token() {
// Set time to be 2 seconds in the past.
var nowSeconds = Date.now() / 1000;
Services.prefs.setIntPref(LOOP_URL_EXPIRY_PREF, nowSeconds - 2);
Services.prefs.setBoolPref(LOOP_CREATED_ROOM_PREF, false);
Services.prefs.clearUserPref(LOOP_FXA_TOKEN_PREF);
yield MozLoopService.initialize().then((msg) => {
@ -34,8 +34,8 @@ add_task(function test_initialize_with_expired_urls_and_no_auth_token() {
});
});
add_task(function test_initialize_with_urls_and_no_auth_token() {
Services.prefs.setIntPref(LOOP_URL_EXPIRY_PREF, Date.now() / 1000 + 10);
add_task(function test_initialize_with_created_room_and_no_auth_token() {
Services.prefs.setBoolPref(LOOP_CREATED_ROOM_PREF, true);
Services.prefs.clearUserPref(LOOP_FXA_TOKEN_PREF);
loopServer.registerPathHandler("/registration", (request, response) => {
@ -114,7 +114,7 @@ function run_test() {
Services.prefs.clearUserPref(LOOP_INITIAL_DELAY_PREF);
Services.prefs.clearUserPref(LOOP_FXA_TOKEN_PREF);
Services.prefs.clearUserPref(LOOP_FXA_PROFILE_PREF);
Services.prefs.clearUserPref(LOOP_URL_EXPIRY_PREF);
Services.prefs.clearUserPref(LOOP_CREATED_ROOM_PREF);
});
run_next_test();

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

@ -34,7 +34,7 @@ add_test(function test_registration_invalid_token() {
MozLoopService.promiseRegisteredWithServers().then(() => {
// Due to the way the time stamp checking code works in hawkclient, we expect a couple
// of authorization requests before we reset the token.
Assert.equal(authorizationAttempts, 4); //hawk will repeat each registration attemtp twice: calls and rooms.
Assert.equal(authorizationAttempts, 2); // Hawk will repeat the registration attempt twice.
Assert.equal(Services.prefs.getCharPref(LOOP_HAWK_PREF), fakeSessionToken2);
run_next_test();
}, err => {

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

@ -163,7 +163,7 @@ let ReaderParent = {
/**
* Gets an article for a given URL. This method will download and parse a document
* if it does not find the article in the tab data or the cache.
* if it does not find the article in the browser data.
*
* @param url The article URL.
* @param browser The browser where the article is currently loaded.
@ -177,12 +177,6 @@ let ReaderParent = {
return article;
}
// Next, try to find a parsed article in the cache.
article = yield ReaderMode.getArticleFromCache(url);
if (article) {
return article;
}
// Article hasn't been found in the cache, we need to
// download the page and parse the article out of it.
return yield ReaderMode.downloadAndParseDocument(url);

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

@ -7180,6 +7180,13 @@
"kind": "boolean",
"description": "Stores 1 every time the URL is copied or shared."
},
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH": {
"expires_in_version": "43",
"kind": "count",
"keyed": true,
"releaseChannelCollection": "opt-out",
"description": "Connection length for bi-directionally connected media"
},
"E10S_AUTOSTART": {
"expires_in_version": "never",
"kind": "boolean",