Bug 972941: Landing page for non WebRTC-compliant browsers on supported devices. r=nperriault
authorRomain Gauthier <romain.gauthier@monkeypatch.me>
Thu, 29 May 2014 21:20:11 +0100
changeset 187763 d601d88a01a2e6af033213f0de9e7bec657ff9d3
parent 187762 1a6d884f153e10ada7be5507a9470182ae2f901b
child 187764 b0a81d18e4f9f815b330998a30f191ef014f5f92
push idunknown
push userunknown
push dateunknown
reviewersnperriault
bugs972941
milestone32.0a1
Bug 972941: Landing page for non WebRTC-compliant browsers on supported devices. r=nperriault
browser/components/loop/content/shared/js/views.js
browser/components/loop/standalone/content/js/webapp.js
browser/components/loop/standalone/content/l10n/data.ini
browser/components/loop/test/shared/sdk_mock.js
browser/components/loop/test/standalone/index.html
browser/components/loop/test/standalone/webapp_test.js
--- a/browser/components/loop/content/shared/js/views.js
+++ b/browser/components/loop/content/shared/js/views.js
@@ -325,16 +325,32 @@ loop.shared.views = (function(_, OT, l10
           model: notification,
           collection: this.collection
         }).render().$el;
       }.bind(this)));
       return this;
     }
   });
 
+  /**
+   * Unsupported Browsers view.
+   */
+  var UnsupportedView = BaseView.extend({
+    template: _.template([
+      '<div>',
+        '<h2 data-l10n-id="incompatible_browser"></h2>',
+        '<p data-l10n-id="powered_by_webrtc"></p>',
+        '<p data-l10n-id="use_latest_firefox" ',
+          'data-l10n-args=\'{"ff_url": "https://www.mozilla.org/firefox/"}\'>',
+        '</p>',
+      '</div>'
+    ].join(""))
+  });
+
   return {
     L10nView: L10nView,
     BaseView: BaseView,
     ConversationView: ConversationView,
     NotificationListView: NotificationListView,
-    NotificationView: NotificationView
+    NotificationView: NotificationView,
+    UnsupportedView: UnsupportedView
   };
 })(_, window.OT, document.webL10n || document.mozL10n);
--- a/browser/components/loop/standalone/content/js/webapp.js
+++ b/browser/components/loop/standalone/content/js/webapp.js
@@ -106,16 +106,17 @@ loop.webapp = (function($, _, OT) {
   });
 
   /**
    * Webapp Router.
    */
   var WebappRouter = loop.shared.router.BaseConversationRouter.extend({
     routes: {
       "":                    "home",
+      "unsupported":         "unsupported",
       "call/ongoing/:token": "loadConversation",
       "call/:token":         "initiate"
     },
 
     initialize: function() {
       // Load default view
       this.loadView(new HomeView());
     },
@@ -147,16 +148,20 @@ loop.webapp = (function($, _, OT) {
 
     /**
      * Default entry point.
      */
     home: function() {
       this.loadView(new HomeView());
     },
 
+    unsupported: function() {
+      this.loadView(new sharedViews.UnsupportedView());
+    },
+
     /**
      * Loads conversation launcher view, setting the received conversation token
      * to the current conversation model. If a session is currently established,
      * terminates it first.
      *
      * @param  {String} loopToken Loop conversation token.
      */
     initiate: function(loopToken) {
@@ -191,16 +196,18 @@ loop.webapp = (function($, _, OT) {
    * App initialization.
    */
   function init() {
     router = new WebappRouter({
       conversation: new sharedModels.ConversationModel({}, {sdk: OT}),
       notifier: new sharedViews.NotificationListView({el: "#messages"})
     });
     Backbone.history.start();
+    if (!OT.checkSystemRequirements())
+      router.navigate("unsupported", {trigger: true});
   }
 
   return {
     baseServerUrl: baseServerUrl,
     ConversationFormView: ConversationFormView,
     HomeView: HomeView,
     init: init,
     WebappRouter: WebappRouter
--- a/browser/components/loop/standalone/content/l10n/data.ini
+++ b/browser/components/loop/standalone/content/l10n/data.ini
@@ -2,18 +2,25 @@
 call_has_ended=Your call has ended.
 missing_conversation_info=Missing conversation information.
 network_disconnected=The network connection terminated abruptly.
 peer_ended_conversation=Your peer ended the conversation.
 unable_retrieve_call_info=Unable to retrieve conversation information.
 stop=Stop
 start_call=Start the call
 welcome=Welcome to the Loop web client.
+incompatible_browser=Incompatible Browser
+powered_by_webrtc=The audio and video components of Loop are powered by WebRTC.
+use_latest_firefox.innerHTML=To use Loop, please use the latest version of <a href="{{ff_url}}">Firefox</a>.
 
 [fr]
 call_has_ended=L'appel est terminé.
 missing_conversation_info=Informations de communication manquantes.
 network_disconnected=La connexion réseau semble avoir été interrompue.
 peer_ended_conversation=Votre correspondant a mis fin à la communication.
 unable_retrieve_call_info=Impossible de récupérer les informations liées à cet appel.
 stop=Arrêter
 start_call=Démarrer l'appel
 welcome=Bienvenue sur Loop.
+incompatible_browser=Navigateur non supporté
+powered_by_webrtc=Les fonctionnalités audio et vidéo de Loop utilisent WebRTC.
+use_latest_firefox.innerHTML=Pour utiliser Loop, merci d'utiliser la dernière version de <a href="{{ff_url}}">Firefox</a>.
+
new file mode 100644
--- /dev/null
+++ b/browser/components/loop/test/shared/sdk_mock.js
@@ -0,0 +1,22 @@
+/* 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/. */
+
+/**
+ * This file mocks the functions from the OT sdk that we use. This is to provide
+ * an interface that tests can mock out, without needing to maintain a copy of
+ * the sdk or load one from the network.
+ */
+(function (window) {
+  "use strict";
+
+  if (!window.OT) {
+    window.OT = {};
+  }
+
+  window.OT.checkSystemRequirements = function() {
+    return true;
+  };
+
+})(window);
+
--- a/browser/components/loop/test/standalone/index.html
+++ b/browser/components/loop/test/standalone/index.html
@@ -20,16 +20,17 @@
   <script src="../../content/shared/libs/webl10n-20130617.js"></script>
   <script src="../../content/shared/libs/jquery-2.1.0.js"></script>
   <script src="../../content/shared/libs/lodash-2.4.1.js"></script>
   <script src="../../content/shared/libs/backbone-1.1.2.js"></script>
   <!-- test dependencies -->
   <script src="../shared/vendor/mocha-1.17.1.js"></script>
   <script src="../shared/vendor/chai-1.9.0.js"></script>
   <script src="../shared/vendor/sinon-1.9.0.js"></script>
+  <script src="../shared/sdk_mock.js"></script>
   <script>
     chai.Assertion.includeStack = true;
     mocha.setup('bdd');
   </script>
   <!-- App scripts -->
   <script src="../../content/shared/js/models.js"></script>
   <script src="../../content/shared/js/views.js"></script>
   <script src="../../content/shared/js/router.js"></script>
--- a/browser/components/loop/test/standalone/webapp_test.js
+++ b/browser/components/loop/test/standalone/webapp_test.js
@@ -24,16 +24,32 @@ describe("loop.webapp", function() {
       errorL10n: sandbox.spy(),
     };
   });
 
   afterEach(function() {
     sandbox.restore();
   });
 
+  describe("#init", function() {
+    it("should navigate to the unsupported route if the sdk detects the" +
+       "browser is unsupported", function() {
+         var WebappRouter = loop.webapp.WebappRouter;
+         sandbox.stub(window.OT, "checkSystemRequirements").returns(false);
+         sandbox.stub(WebappRouter.prototype, "navigate");
+
+         loop.webapp.init();
+
+         sinon.assert.calledOnce(WebappRouter.prototype.navigate);
+         sinon.assert.calledWithExactly(WebappRouter.prototype.navigate,
+                                        "unsupported", {trigger: true});
+       });
+
+  });
+
   describe("WebappRouter", function() {
     var router, conversation;
 
     beforeEach(function() {
       conversation = new sharedModels.ConversationModel({}, {sdk: {}});
       router = new loop.webapp.WebappRouter({
         conversation: conversation,
         notifier: notifier
@@ -139,16 +155,26 @@ describe("loop.webapp", function() {
         it("should navigate to #call/{token} if session isn't ready",
           function() {
             router.loadConversation("fakeToken");
 
             sinon.assert.calledOnce(router.navigate);
             sinon.assert.calledWithMatch(router.navigate, "call/fakeToken");
           });
       });
+
+      describe("#unsupported", function() {
+        it("should load the UnsupportedView", function() {
+          router.unsupported();
+
+          sinon.assert.calledOnce(router.loadView);
+          sinon.assert.calledWith(router.loadView,
+            sinon.match.instanceOf(sharedViews.UnsupportedView));
+        });
+      });
     });
 
     describe("Events", function() {
       var fakeSessionData;
 
       beforeEach(function() {
         fakeSessionData = {
           sessionId:    "sessionId",