Last modified: 2012-12-12 21:56:22 UTC
JavaScript on all Wikimedia sites currently fails on Opera due to faulty browser detection code. I've pinpointed the error to the following lines in jquery.client.js: // Expose Opera 10's lies about being Opera 9.8 if ( name === 'opera' && version >= 9.8) { version = ua.match( /version\/([0-9\.]*)/i )[1] || 10; } Unfortunately, for me, `ua` (== `navigator.userAgent`) at this point is "Opera/9.80 (Windows NT 5.1)", so the match fails and attempting to retrieve the first matching groups throws an error such as "Uncaught exception: TypeError: Cannot convert 'ua.match( /version\/([0-9\.]*)/i )' to object". To detect Opera's version properly, we should use `window.opera.version()`, which returns version number like "12.11". However, it looks like $.client doesn't take this into account at all, relying on User-Agent strings; I'm making a stopgap patch right now.
Gerrit change #36350 submitted.
Opera 10+ expose their version in the Version/* clause of the user-agent, just like Safari. There are many issues with jquery.client's primitive approach to ua-parsing. We'll be switching to Tobie's ua-parser soon which is much more reliable in this. I think we should avoid non-standard API's like opera.version() as those are only available if the current browser is Opera, not when given a User-Agent string in general (and as such is not testable nor usable outside current-browser context). And besides, the version in the User-Agent "Version/" clause string is exactly the same as the one Opera returns from that API.
Created attachment 11446 [details] jquery.client in current MediaWiki 1.21alpha master working on Opera 12.x It seems to be working fine for me. Can you provide an example of a (full) User-Agent for Opera 9.8+ that doesn't have a Version/* clause?
My user-agent, as sent in HTTP headers, includes Version/: "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.11". However, the one available via navigator.userAgent in JS doesn't: "Opera/9.80 (Windows NT 5.1)". I was unable to determina what causes this. I didn't find any options which could change this in opera:config, apart from "Spoof UserAgent ID" (which is set to 1, 'do not spoof'), and "Custom User-Agent" (which is not set). Anyway, it clearly happens to me, and has to at least sometimes happen to others. The original code isn't too robust anyway (relying on the match being made), so I believe my version is an improvement.
(In reply to comment #2) > I think we should avoid non-standard API's like opera.version() as those are > only available if the current browser is Opera, not when given a User-Agent > string in general (and as such is not testable nor usable outside > current-browser context). And besides, the version in the User-Agent "Version/" > clause string is exactly the same as the one Opera returns from that API. This is a documented[1] API that, unlike user-agent, can't be spoofed (except for under some circumstances that are irrelevant here). One can easily detect Opera by checking if window.opera is undefined, without mucking with user-agent. [1] http://my.opera.com/community/openweb/idopera/ , near the end
So, I found it. My "Script Spoof" preference[1] was set to -4, and apparently negative values cause the behavior described above. Setting it to 0 restored the "expected" user-agent. I still believe my fix is worth applying. [1] opera:config#UserPrefs|ScriptSpoof
Change merged.