Testing MouseLock FullScreen

After a lot of tries and fails I got the navigatorPointer and mozFullScreen tests working.

I didn’t think that the process of getting the tests to work would be so tricky.

1. Running navigatorPointer test

I tried to run the navigatorPointer test, but nothing would appear on the browser screen. However, on the terminal, I could see the output for all the tests. Browsing through the Mochitest wiki I found this page that lets you run mochitests without building firefox. I ran the navigatorPointer test there and the output appeared on the screen.
So I knew the test was working, but for some unknown reason it only worked on the mochitester page, not when building the mochitest-plain suite.

My first thought was to run other tests from the mochitest-plain suite and see if they worked, I found and ran the outerWindow test, and the output was successfully displayed on the browser.
I then opened side by side the outerWindow and the navigatorPointer tests and started inspecting them to see what was different. The only major difference was that on the outterWindow, the test started with:

SimpleTest.waitForExplicitFinish()and ended with SimpleTest.finish();

I added those two lines in the navigatorPointer.html and the mochitest worked :)
I’m not sure why the test needs to explicity call the SimpleTest.finisht() since the test itself doesn’t have any asynchronous calls.

2. mozFullScreen API

Before writing the mochitest to check if the mouse was being locked when the element was in fullscreen mode, I started hacking around the mozFullScreen api to see how I could implement the tests.
The first problem I noticed, was that the mozfullscreenchange event was only fired when there was some sort of user interaction, for example:


wouldn’t work, and:

  document.getElementById("test").addEventListener("click", function () {  
 }, false);  


I first thought that the mozRequestFullScreen() could only be invoked if some sort of event was fired, and because in the mochitest, there is no user interaction, and all the tests are automated, I needed to find a way to create and fire an event in javascript. I asked that question on the #seneca channel and James(jboelen) pointed me in the right direction: document.createEvent

However, even creating and firing a synthetic event still didn’t trigger the mozfullscreenchange, I believe that for security reasons, to request a fullscreen change on the browser, the user must give some sort of acknowledgement by clicking the mouse or pressing a key.

I then started thinking of different ways to test the fullscreen status for the mouselock, but then I realized that when they wrote the mochitests for the mozfullscreen api they must have faced the same problems. So I did a quick search on mxr and found these two files: file_fullscreen-esc-exit.html file_fullscreen-denied.html
Inspecting the mochitests, I saw how they requested a fullscreen change without user interaction:

 SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);  

3. MouseLock fullscreen tests

When the browser goes fullscreen, the mozfullscrenchange event is sent to the document and the element that requested the fullscreen change, but when the window looses the fullscreen mode, the mozfullscreenchange event is only sent to the document, so to listen for both the entering and exiting of fullscreen mode, the mozfullscreenchange event needs to be attached to the document.

The solution I came up for the test, was to add the event listener to the document, and inside the event listener check if the screen was entering, or existing the fullscreen mode. If the screen was entering, I would check if the element in fullscreen mode was the one with the mouse locked and if the screen was exiting, I would test to make sure the mouse wasn’t locked.
The problem with that, was that because the test was asynchronous, and inside the event listener the SimpleTest.finish() needed to be invoked. But because the event was fired more than once, I didn’t know where to place it.
To make sure the test was only finished when all the test cases were completed, I created two variables to keep track of how many tests needed to be performed, and how many were completed.

 document.addEventListener("mozfullscreenchange", function (e) {  
 if (document.mozFullScreen) {  
 if (document.mozFullScreenElement === canvas) {  
 // Mouse should be lock if the element is in fullscreen mode  
 is(pointer.islocked(), true, "Mouse should be locked");  
 nTests += 1;  
 else {  
 // Mouse shoudn’t lock if element isn’t in fullscreen mode  
 isnot(pointer.islocked(), true, "Mouse should only be locked if the locked element is in fullscreen mode");  
 nTests += 1;  
 else {  
 // Mouse should be unlocked if winodw is not in fullscreen mode  
 is(pointer.islocked(), false, "Mouse should be unlocked if winodw is not in fullscreen mode");

 if (nTests === totalTests) {  
 // Finish test  

 }, false);

So every time the screen lost the fullscreen status, a test would run to check if the mouse was unlocked. If all the tests were completed, the SimpleTest.finish() would be invoked.

I then ran the mochitest. It didn’t work. The screen just stayed blank.
I started debugging, login some messages to the console, and I found out that the mozfullscreenchange event was being fired only once, even though two elements were requesting fullscreen mode. I thought that maybe because the requests were being made one after another, the events were getting mixed up. I added a setTimeout for the second request and then all the tests ran successfully.

Some tests are failing because the functionality still needs to be implemented in the MouseLock.

  • The MouseLock needs to unlock the mouse when the element looses the fullscreen mode
  • The mouse should only be locked if the element is in fullscreen mode

I committed the changes here.