Closed Bug 1025589 Opened 10 years ago Closed 8 years ago

LinkedIn pages are 404'ing in Firefox for Android after LinkedIn does a redirect

Categories

(Web Compatibility :: Site Reports, defect)

All
Android
defect
Not set
normal

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: u509263, Unassigned)

References

(Blocks 1 open bug, )

Details

(Whiteboard: [country-all][notcontactready])

User Agent: Mozilla/5.0 (Windows NT 5.1; rv:30.0) Gecko/20100101 Firefox/30.0 (Beta/Release)
Build ID: 20140605174243

Steps to reproduce:

Tried to display the following LinkedIn public profile page: http://linkedin.com/in/johnlilly


Actual results:

Received a 404 ('page doesn't exist') server response. Same thing happened when trying to display other profile pages in general ('http://linkedin.com/in/*')


Expected results:

Actual LinkedIn page with data (photo and text) should have appeared, as displayed/rendered by Chrome (Android) or same page data as retrieved by Firefox (Desktop).
OS: Windows XP → Android
Hardware: x86 → All
Component: General → Mobile
Product: Firefox for Android → Tech Evangelism
Version: Firefox 30 → unspecified
I was able to reproduce this on my phone but oddly not on desktop (w/mobile UA)

http://linkedin.com/in/johnlilly does a redirect to https://touch.www.linkedin.com/

HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Sun, 15 Jun 2014 21:01:38 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: https://www.linkedin.com/in/johnlilly

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
P3P: CP="CAO CUR ADM DEV PSA PSD OUR"
Content-Language: en-US
Content-Length: 0
Vary: Accept-Encoding
Date: Sun, 15 Jun 2014 21:01:38 GMT
X-FS-UUID: e91a70df48fb77131046d64ed62a0000
X-LI-UUID: 6Rpw30j7dxMQRtZO1ioAAA==
X-Frame-Options: sameorigin
X-Content-Type-Options: nosniff
X-Li-Fabric: PROD-ELA4
Set-Cookie: _lipt="delete me"; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
Set-Cookie: _lipt=deleteMe; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; domain=.www.linkedin.com
Set-Cookie: leo_auth_token="delete me"; Version=1; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
Set-Cookie: leo_auth_token="GST:9Ht95vpOCdWDdHmDPEh73Vv547hOupFOpVWRRovXC-hahhCtq_tKLs:1402866099:a12e89e7e47a6fab3bc8de4499a3a834ebdf2acb"; Version=1; Max-Age=1799; Expires=Sun, 15-Jun-2014 21:31:38 GMT; Path=/; domain=.www.linkedin.com
Set-Cookie: sl="delete me"; Version=1; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
Set-Cookie: sl="delete me"; Version=1; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; domain=.www.linkedin.com
Set-Cookie: sl="delete me"; Version=1; Domain=.www.linkedin.com; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
Set-Cookie: s_leo_auth_token="delete me"; Version=1; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
Set-Cookie: s_leo_auth_token="delete me"; Version=1; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; domain=.www.linkedin.com
Set-Cookie: JSESSIONID="ajax:9057019508263935868"; Version=1; Domain=.www.linkedin.com; Path=/
Set-Cookie: visit="delete me"; Version=1; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
Set-Cookie: visit="v=1&G"; Version=1; Max-Age=63072000; Expires=Tue, 14-Jun-2016 21:01:39 GMT; Path=/; domain=.www.linkedin.com
Set-Cookie: lang="delete me"; Version=1; Domain=linkedin.com; Path=/; Expires=Thu, 01-Jan-1970 00:00:10 GMT
Set-Cookie: lang="v=2&lang=en-us"; Version=1; Domain=.linkedin.com; Path=/
Set-Cookie: bcookie="v=2&83aa1332-03c2-40d6-891c-1b5a6c454280"; domain=.linkedin.com; Path=/; Expires=Wed, 15-Jun-2016 08:39:11 GMT
Set-Cookie: bscookie="v=1&201406152101391d9b1c8a-5b01-46b4-8489-726d0ab4966dAQE3vl-TYFieH6bILNiZRbcTlCr9argg"; domain=.www.linkedin.com; Path=/; Secure; Expires=Wed, 15-Jun-2016 08:39:11 GMT; HttpOnly
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: no-cache, no-store
Connection: keep-alive
X-Li-Pop: PROD-ELA4
Set-Cookie: lidc="b=LB11:g=82:u=1:i=1402866099:t=1402952499:s=3685604721"; Expires=Mon, 16 Jun 2014 21:01:39 GMT; domain=.linkedin.com; Path=/

Not sure why it fails on mobile but not desktop
Status: UNCONFIRMED → NEW
Ever confirmed: true
Summary: Fail to display LinkedIn public profile pages → LinkedIn pages are 404'ing in Firefox for Android after LinkedIn does a redirect
I can reproduce this on Desktop now, when spoofing as Fennec. But when spoofing as Fennec in Chrome, I land on the page as expected.

I get two errors in the console that need investigating:

TypeError: e.done is not a function
"[Q] Unhandled rejection reasons (should be empty):" Array [  ]

The first (that only pops up every once in a while) is coming from this boomerang library: https://github.com/lognormal/boomerang
The second from https://static.licdn.com/sc/h/9myi79vmyxovn2gx8ggdd6src
Whiteboard: [country-all][notcontactready]
Some dubious stuff going on in https://static.licdn.com/sc/h/9v049ynsobghsbk7jp3igr517

var k=this.loadUrl();if(!k){v=TLI.bundleForRoute(v);if(!v)window.location="/404";TLI.loadAdditionalBundle(v,a.bind(function(){k=this.loadUrl();if(!k)window.location="/404"}

but the code that's really failing is this one:

        initializeBackbone: function() {
            n.trigger("appInitialize");
            if (!a.History.started)
                if (!a.history.start()) window.location = "/404"
        }

Inside history.start() there's a mix of feature/API and browser detection that ends up somewhere we don't return 'true' - so so we're taken to the 404 URL. It seems we end up here:

        loadUrl: function (d) {
            var g = this.fragment = this.getFragment(d);
            return o.any(this.handlers, function (q) {
                if (q.route.test(g)) {
                    q.callback(g);
                    return true

Where the query string/hash is tested against various regexpes (q.route.test(g)) and it finds nothing that matches public-profile when g is this string:

public-profile/https%3A%2F%2Fwww.linkedin.com%2Fin%2Fjohnlilly
"Route" regular expressions when the code runs in Chrome:

/^(\?.+)?$/
/^home(\?.+)?$/
/^login(\?.+)?$/
/^rev(\?.+)?$/
/^cache(\?.+)?$/
/^you(\?.+)?$/
/^public\-profile/([^/]+)(\?.+)?$/

(possibly more but at this point navigation logic kicks in)

Logging the very same spot in the code Firefox runs gives this:

/^(\?.+)?$/
/^home(\?.+)?$/
/^login(\?.+)?$/
/^rev(\?.+)?$/
/^cache(\?.+)?$/
/^comment\/([^\/]+)(\?.+)?$/
/^reader\/([^\/]+)(\?.+)?$/
/^reader\/([^\/]+)\/(\?.+)?$/
/^influencer\-reader\/([^\/]+)(\?.+)?$/
/^stream\-detail\/([^\/]+)(\?.+)?$/
/^stream\-detail\/([^\/]+)\/([^\/]+)(\?.+)?$/
/^feed\-detail\/([^\/]+)(\?.+)?$/
/^like\-detail\/([^\/]+)(\?.+)?$/
/^multi\-actor\-detail\/([^\/]+)(\?.+)?$/
/^stream\/groups\/([^\/]+)\/posts\/popular(\?.+)?$/
/^profile\-update\-detail\/([^\/]+)(\?.+)?$/
/^new\-connections\-detail\/([^\/]+)(\?.+)?$/
/^job\-change\-detail\/([^\/]+)(\?.+)?$/
/^postdetail\/([^\/]+)(\?.+)?$/
/^postdetail\/([^\/]+)\/([^\/]+)(\?.+)?$/
/^image\-viewer\/([^\/]+)(\?.+)?$/
/^stream(\?.+)?$/
/^stream\/post\-onboard(\?.+)?$/

And at least two "routes" are indeed missing.
Still a mystery. This code in inline script

"bundles/profile":"//static.licdn.com/sc/h/6cif8wnlnyul7f9w3hnw8uyng"

should make require.js load https://static.licdn.com/sc/h/6cif8wnlnyul7f9w3hnw8uyng?noext=1 , and this should define the public-profile route. But it seems the dependency calculations require.js performs in Firefox do not conclude that bundles/profile is required..? 

If you find this code:

                    enable: function() {
                        ea[this.map.id] = this;
                        this.enabling = this.enabled = true;

and add

                        if(this.depMaps.indexOf("bundles/profile")>-1)debugger;

it will indeed break in Chrome but not in Firefox. 

Dependencies are resolved inside some recursing code that seems to run a lot, so I'm not yet sure why it fails.
OK - this is an old friend: decode location.hash or not?

In Chrome, reading location.hash returns
"#public-profile/https%3A%2F%2Fwww.linkedin.com%2Fin%2Fjohnlilly"

while in Firefox it returns

"#public-profile/https://www.linkedin.com/in/johnlilly"

when the bundleForRoute() method tries to parse this input with this regular expression:

/^public\-profile/([^/]+)$/

it certainly won't find any usage of public-profile followed by no forward slashes, so it doesn't discover that the bundles/profile module is required, and we end up at the 404 page.
Checking the spec and I see anything which says how it should be decoded.
http://url.spec.whatwg.org/#dom-url-hash

Maybe Anne has an idea about it.
Flags: needinfo?(annevk)
Hallvord, The automatic test says it's fixed, but it's not. The issue is still here. 
I have very low expectations to get anything fixed by linkedin. All my attempts have failed so far.
Flags: needinfo?(hsteen)
This test triggers a mysterious error I haven't seen anywhere else:

ERROR reported to slimertester.js: NS_ERROR_FACTORY_NOT_REGISTERED:  [{"file":"https://static.licdn.com/sc/h/4jxhjafm42wt5lvssjsrec1w1","line":21,"function":null}]

I don't know what that means at the moment, but I've changed the test a bit - it will now report a timeout rather than a pass.
Flags: needinfo?(hsteen)
test hopefully fixed
Per the URL Standard *parsing* a URL will percent-encode the fragment, see: http://url.spec.whatwg.org/#fragment-state

The hash property's getter will simply return that value, preceded by "#".

So per the URL Standard we are wrong here, it seems like. However, changing this is a can of worms :-(
Blocks: url
Flags: needinfo?(annevk)
TIL this is really a dup of bug 483304
fixed.
Status: NEW → RESOLVED
Closed: 8 years ago
Resolution: --- → FIXED
Product: Tech Evangelism → Web Compatibility
Component: Mobile → Site Reports
You need to log in before you can comment on or make changes to this bug.