Bug 1011472 - Add audio alert for incoming call r=florian,standard8

This commit is contained in:
Adam Roach [:abr]
2014-06-26 18:55:03 -05:00
parent c809ffde16
commit c7c126a64c
6 changed files with 120 additions and 8 deletions

View File

@@ -1512,6 +1512,7 @@ pref("image.mem.max_decoded_image_kb", 256000);
#ifdef MOZ_LOOP #ifdef MOZ_LOOP
pref("loop.server", "https://loop.services.mozilla.com"); pref("loop.server", "https://loop.services.mozilla.com");
pref("loop.do_not_disturb", false); pref("loop.do_not_disturb", false);
pref("loop.ringtone", "chrome://browser/content/loop/shared/sounds/Firefox-Long.ogg");
#endif #endif
// serverURL to be assigned by services team // serverURL to be assigned by services team

View File

@@ -24,6 +24,9 @@ this.EXPORTED_SYMBOLS = ["injectLoopAPI"];
* @param {nsIDOMWindow} targetWindow The content window to attach the API. * @param {nsIDOMWindow} targetWindow The content window to attach the API.
*/ */
function injectLoopAPI(targetWindow) { function injectLoopAPI(targetWindow) {
let ringer;
let ringerStopper;
let api = { let api = {
/** /**
* Sets and gets the "do not disturb" mode activation flag. * Sets and gets the "do not disturb" mode activation flag.
@@ -149,6 +152,50 @@ function injectLoopAPI(targetWindow) {
value: function(prefName) { value: function(prefName) {
return MozLoopService.getLoopCharPref(prefName); return MozLoopService.getLoopCharPref(prefName);
} }
},
/**
* Starts alerting the user about an incoming call
*/
startAlerting: {
enumerable: true,
configurable: true,
writable: true,
value: function() {
let chromeWindow = getChromeWindow(targetWindow);
chromeWindow.getAttention();
ringer = new chromeWindow.Audio();
ringer.src = Services.prefs.getCharPref("loop.ringtone");
ringer.loop = true;
ringer.load();
ringer.play();
targetWindow.document.addEventListener("visibilitychange",
ringerStopper = function(event) {
if (event.currentTarget.hidden) {
api.stopAlerting.value();
}
});
}
},
/**
* Stops alerting the user about an incoming call
*/
stopAlerting: {
enumerable: true,
configurable: true,
writable: true,
value: function() {
if (ringerStopper) {
targetWindow.document.removeEventListener("visibilitychange",
ringerStopper);
ringerStopper = null;
}
if (ringer) {
ringer.pause();
ringer = null;
}
}
} }
}; };
@@ -168,3 +215,12 @@ function injectLoopAPI(targetWindow) {
// Handle window.close correctly on the panel and chatbox. // Handle window.close correctly on the panel and chatbox.
hookWindowCloseForPanelClose(targetWindow); hookWindowCloseForPanelClose(targetWindow);
} }
function getChromeWindow(contentWin) {
return contentWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
}

View File

@@ -53,8 +53,7 @@ loop.conversation = (function(OT, mozL10n) {
*/ */
handleDecline: function(event) { handleDecline: function(event) {
event.preventDefault(); event.preventDefault();
// XXX For now, we just close the window. this.model.trigger("decline");
window.close();
} }
}); });
@@ -95,6 +94,7 @@ loop.conversation = (function(OT, mozL10n) {
routes: { routes: {
"incoming/:version": "incoming", "incoming/:version": "incoming",
"call/accept": "accept", "call/accept": "accept",
"call/decline": "decline",
"call/ongoing": "conversation", "call/ongoing": "conversation",
"call/ended": "ended" "call/ended": "ended"
}, },
@@ -120,10 +120,14 @@ loop.conversation = (function(OT, mozL10n) {
* by the router from the URL. * by the router from the URL.
*/ */
incoming: function(loopVersion) { incoming: function(loopVersion) {
window.navigator.mozLoop.startAlerting();
this._conversation.set({loopVersion: loopVersion}); this._conversation.set({loopVersion: loopVersion});
this._conversation.once("accept", function() { this._conversation.once("accept", function() {
this.navigate("call/accept", {trigger: true}); this.navigate("call/accept", {trigger: true});
}.bind(this)); }.bind(this));
this._conversation.once("decline", function() {
this.navigate("call/decline", {trigger: true});
}.bind(this));
this.loadView(new IncomingCallView({model: this._conversation})); this.loadView(new IncomingCallView({model: this._conversation}));
}, },
@@ -131,12 +135,22 @@ loop.conversation = (function(OT, mozL10n) {
* Accepts an incoming call. * Accepts an incoming call.
*/ */
accept: function() { accept: function() {
window.navigator.mozLoop.stopAlerting();
this._conversation.initiate({ this._conversation.initiate({
baseServerUrl: window.navigator.mozLoop.serverUrl, baseServerUrl: window.navigator.mozLoop.serverUrl,
outgoing: false outgoing: false
}); });
}, },
/**
* Declines an incoming call.
*/
decline: function() {
window.navigator.mozLoop.stopAlerting();
// XXX For now, we just close the window
window.close();
},
/** /**
* conversation is the route when the conversation is active. The start * conversation is the route when the conversation is active. The start
* route should be navigated to first. * route should be navigated to first.

View File

@@ -21,6 +21,7 @@ browser.jar:
content/browser/loop/shared/libs/sjcl-dev20140604.js (content/shared/libs/sjcl-dev20140604.js) content/browser/loop/shared/libs/sjcl-dev20140604.js (content/shared/libs/sjcl-dev20140604.js)
content/browser/loop/shared/libs/token.js (content/shared/libs/token.js) content/browser/loop/shared/libs/token.js (content/shared/libs/token.js)
content/browser/loop/shared/libs/hawk-browser-2.2.1.js (content/shared/libs/hawk-browser-2.2.1.js) content/browser/loop/shared/libs/hawk-browser-2.2.1.js (content/shared/libs/hawk-browser-2.2.1.js)
content/browser/loop/shared/sounds/Firefox-Long.ogg (content/shared/sounds/Firefox-Long.ogg)
content/browser/loop/libs/l10n.js (content/libs/l10n.js) content/browser/loop/libs/l10n.js (content/libs/l10n.js)
content/browser/loop/js/desktopRouter.js (content/js/desktopRouter.js) content/browser/loop/js/desktopRouter.js (content/js/desktopRouter.js)
content/browser/loop/js/conversation.js (content/js/conversation.js) content/browser/loop/js/conversation.js (content/js/conversation.js)

View File

@@ -26,6 +26,12 @@ describe("loop.conversation", function() {
window.navigator.mozLoop = { window.navigator.mozLoop = {
get serverUrl() { get serverUrl() {
return "http://example.com"; return "http://example.com";
},
startAlerting: function() {
},
stopAlerting: function() {
} }
}; };
}); });
@@ -119,6 +125,13 @@ describe("loop.conversation", function() {
sinon.assert.calledWithExactly(router.loadView, sinon.assert.calledWithExactly(router.loadView,
sinon.match.instanceOf(loop.conversation.IncomingCallView)); sinon.match.instanceOf(loop.conversation.IncomingCallView));
}); });
it("should start alerting", function() {
sandbox.stub(window.navigator.mozLoop, "startAlerting");
router.incoming("fakeVersion");
sinon.assert.calledOnce(window.navigator.mozLoop.startAlerting);
});
}); });
describe("#accept", function() { describe("#accept", function() {
@@ -131,6 +144,13 @@ describe("loop.conversation", function() {
outgoing: false outgoing: false
}); });
}); });
it("should stop alerting", function() {
sandbox.stub(window.navigator.mozLoop, "stopAlerting");
router.accept();
sinon.assert.calledOnce(window.navigator.mozLoop.stopAlerting);
});
}); });
describe("#conversation", function() { describe("#conversation", function() {
@@ -163,6 +183,25 @@ describe("loop.conversation", function() {
}); });
}); });
describe("#decline", function() {
beforeEach(function() {
sandbox.stub(window, "close");
});
it("should close the window", function() {
router.decline();
sinon.assert.calledOnce(window.close);
});
it("should stop alerting", function() {
sandbox.stub(window.navigator.mozLoop, "stopAlerting");
router.decline();
sinon.assert.calledOnce(window.navigator.mozLoop.stopAlerting);
});
});
describe("#ended", function() { describe("#ended", function() {
// XXX When the call is ended gracefully, we should check that we // XXX When the call is ended gracefully, we should check that we
// close connections nicely // close connections nicely
@@ -254,13 +293,14 @@ describe("loop.conversation", function() {
}); });
describe("#handleDecline", function() { describe("#handleDecline", function() {
it("should close the window", function() { it("should trigger an 'decline' conversation model event" ,
sandbox.stub(window, "close"); function(done) {
conversation.once("decline", function() {
done();
});
view.handleDecline({preventDefault: sandbox.spy()}); view.handleDecline({preventDefault: sandbox.spy()});
});
sinon.assert.calledOnce(window.close);
});
}); });
}); });
}); });