Closed keean closed 9 months ago
Can you take a video or give access to some pages where that's happening? Never saw something like that with normal web pages or Moodle.
Sorry, my iOS update hadn't completed. It seems to just zoom in slowly on iOS 16.7.1, and it seems to render incorrectly on iOS 17.0.3
Sorry for the confusion...
Ill try and find a URL for you. Can I email it to you directly?
@danschlet You can see the zoom effect on iOS 16.7.1 by going to any page, for example: https://www.w3schools.com/css/css_border.asp (as the start URL). Then pinch the page like zooming out and let it snap back. Then rotate the pad from portrait to landscape and back again a few times, and you should see it keep zooming in... Safari does not do this.
I'm just updating the iPad to 17.0.3 to see if can replicate the layout problems.
@danschlet 17.0.3 behaves the same as 16.7.1, which is just a slow zoom in on each rotation...
It looks like 15.x in the iPad Air-2 is the one with the issues
@danschlet It appears to happen only with a certain settings in the config file... I am not sure why that would be affecting page rendering and layout, but it does... I guess we will have to bisect the settings, and get down to which one(s) are causing the issue.
@danschlet It appears to only happen when the browser engine is forced to "classic", which we need because we use browser and/or config keys.
No, it actually seems to happen both with the modern and the classic browser engine (on iOS 16.7), if you play around a bit. With the https://www.w3schools.com/css/css_border.asp page you indicated before it actually seems worse with the modern WebView.
I'll look into it. The problem is that Apple doesn't really maintain the system-provided webkit framework as well as the one used in Safari. For example zooming didn't work correctly in the WKWebView API last time I checked it. On Mac they use their own embedded WebKit copy and it might be the same on iOS, or at least they use private APIs, which are not really available to third-party developers (or not documented and not allowed in the App Store).
Btw. this also happens with the Brave browser on iOS/iPad, also with Chrome and iCab (although it seems they attempt to mitigate it, so it's not as frequent).
I even had strange zoom levels happening in Safari on the https://www.w3schools.com/css/css_border.asp page, but I think there it was connected to the ad being displayed on the right edge of the page (and refreshed/replaced in intervals, when the ad or its div seems to shortly be removed).
So it's definitely something which needs to be reported to Apple while trying to mitigate it with some workarounds.
@danschlet Okay so I think the zoom issue is not really serious, as you can readjust the zoom.
I tracked down the disappearing content issue, and it was actually just down to the age of the 'classic' view really. Turns out that where I had used '-webkit-overflow-scrolling: touch' to get momentum scrolling, which works fine with the modern view, and modern browsers, it causes a problem with missing elements in the classic view (and very old browsers). There used to be mitigations in place for this in our CSS code (the direct child of the element with -webkit-overflow-scrolling: touch needs to have -webkit-transform: translate3d(0,0,0) set, however as these mitigations haven't been needed in up to date browsers for some time, this was not applied in newer UI elements.
The thing that stops us moving to the modern view is the support for browser and config keys. which are needed to deliver content securely.
The thing that stops us moving to the modern view is the support for browser and config keys. which are needed to deliver content securely.
And querying those keys using the SEB Javascript API doesn't work for you? It has been adopted in several systems as by now (Moodle 4.1, OpenOlat, Dugga, Ans and others).
Don't know if Apple will actually remove UIWebView (as they are threatening since years). But it's very unlikely that they will ever support custom request headers in WKWebView.
@danschlet Are there TypeScript type stubs for the SafeExamBrowser API?
We are only implementing the browser-side logic. There is only this very simple example http://safeexambrowser.org/exams/bek_ck_new.html You can look at existing open source implementations, for Moodle it can be found here: https://github.com/ethz-let/moodle-quiz_accessrule_seb_js_api
@danschlet if you call "updateKeys", is the callback always called even if the function call is unnecessary? Or can you tell from the API version whether to call this method?
@danschlet I have got the new API returning the keys, but the keys returned from the API do not match the keys displayed in SEB settings? Am I doing something wrong?
@danschlet if you call "updateKeys", is the callback always called even if the function call is unnecessary? Or can you tell from the API version whether to call this method?
If a callback is indicated, it is called, otherwise not. There was one SEB version where using updateKeys was necessary, but no one will still be using that version, so it's safe to use the simplified way for checking the keys.
@danschlet I have got the new API returning the keys, but the keys returned from the API do not match the keys displayed in SEB settings? Am I doing something wrong?
The keys are hashed with the URL of the webpage where you're reading the JS variables. Similar to the request header check.
@danschlet How do users configuring SEB know what keys to put in the backend? Currently users read the config keys from the settings when they setup SEB for the exam, and then enter those codes into our system.
The only way I can think of doing this would be to have our app display the keys somewhere on the login page so that exam admins can see the keys to add to the backend?
@danschlet okay just read your last comment. We have it working with the old version, the backend hashes the keys and checks them. These check pass with the keys as read from settings. When we use the new API to read the keys and send as headers, they do not match the keys calculated by the backend, even though this worked with the 'classic' version. Do I need to do the hashing after reading the keys from the API?
@danschlet It looks like the modern API uses the page load URL for hashing, but the classic mode uses the URL the POST request is being posted to...
What are the solutions for this?
@danschlet I have tried modifying the backend to test the hash with either the API call URL (for classic) and the app load URL (for modern). It's not working yet, I guess there's something not quite right about the URL I am using. How does the modern JS API determine the URL to use when hashing?
@danschlet I think I have it working with the modern option. It does hash with a different URL than the classic version. I solved this by checking with both URLs on the server. I think the classic version is more secure, as the POST URL can include a per-submission value (like a counter) preventing replay-attacks, whereas the modern JS API hashes the key with the same URL every time data is submitted from the same page.
For reference here is the TypeScript declaration for the SEB JS API:
declare global {
interface Window {
SafeExamBrowser: {
version: string;
security: {
configKey: string;
browserExamKey: string;
updateKeys(callback: () => void): void;
}
}
}
}
When rotating the iPad SEB seems to slowly zoom the page in on each rotation. On some versions of iOS this seems to cause rendering/layout issues cutting the borders/outlines off elements (iOS 17.0.3) on other iOS versions (iOS 17.1) it seems to actually zoom the whole page. This seems less of a problem on iOS 17.1, as it can be fixed with a pinch after each rotation, but the layout issues caused on iOS 17.0.3 can cause candidates to mis-interpret questions and answers where options are indicated by css borders.
Safari in iOS does not do this, the page is remains at the same zoom after each rotation, so starting at page width 100%, it remains aligned with the left and right hand sizes after each rotation.
We were testing with SEB 3.3 on the latest versions of iOS17.0.3 (on an iPad Air2) and iOS17.1 (on a sixth gen iPad mini)