Problem/Motivation
In the latest Chrome (83), jquery.form doesn't work properly on https pages.
For D7 see #3143016: [D7] Chrome 83 cancels jquery.form ajax requests over https.
D7 example: try to upload an image at /node/add/article over https.
The POST request to upload the image shows as (cancelled) in red in dev tools, and the upload fails.
D8's jquery.form appears to have the same code which is causing the problem, so is likely also affected.
Proposed resolution
Per https://github.com/jquery-form/form/issues/571 it looks like the problem is:
a = b.extend(true, {
url: d,
type: this.attr('method') || 'GET',
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
}, a);
When iframeSrc is set to javascript:false on https pages, Chrome now seems to cancel the request. Changing this so that it's always set to about:blank seems to resolve the issue, but what other consequences might this have?
Remaining tasks
* Decide whether to patch existing jquery.form plugin or update to a newer version.
* Test affected modules on Chrome 83
* Test jquery-form functionality on all browsers
Release notes snippet
(none yet)
original report by arcataroger
When Chrome updated to 83, I can no longer add or remove paragraphs to any node. Another user (@brocakun) has indicated this also affects images/media widgets. The inspector's Network tab shows that an ajax request is attempted to /system/ajax but then is immediately (canceled) before a response can be made. That same request exported into Postman for testing works just fine, to the same endpoint.
This issue does not happen in Chrome 81 (tested side-by-side in Browserstack), Firefox, Safari, or Edge. It also does not happen on my local dev machine, accessed through http://localhost. I have been able to replicate it 100% of the time online, though, through our https:// test site. Local dev server: PHP-FPM 7.3 + nginx. Remote server: PHP 7.3 + nginx on Pantheon (not sure of the rest of their stack). This seems to be a clientside issue anyhow, something in how Chrome 83 in particular handles this kind of AJAX request.
Not sure if this is an HTTPS, XSS, jQuery, or other issue. I have not been able to find anything useful in the Inspector or chrome://net-internals logs.
My temporary workaround is to just use another browser for adding/removing paragraphs =/
This seems to be caused by an old version of jquery-form (thank you, @ljames28), possibly related to this jquery-forms iframe issue also caused by Chrome 83?.
Temporary confirmed fix from @Collins405 is to use jquery_update with an newer jquery-form override.
| Comment | File | Size | Author |
|---|---|---|---|
| #75 | 3138421-75.patch | 2.59 KB | mcdruid |
| #75 | interdiff-3138421-74-75.txt | 666 bytes | mcdruid |
Comments
Comment #2
arcataroger commentedComment #3
bennybobw commentedI can confirm we're seeing this issue on our sites. It's not all requests, because we can load views. Attaching a file via the media browser fails as well as editing paragraphs.
We're using Apache 2.4 on our sites. I looked in the chrome://net-export log but didn't get any relevant info from that either.
Comment #4
arcataroger commentedI've attached a Chrome netlog, which can be viewed at https://netlog-viewer.appspot.com/ (after renaming extension to .json)
The end of the relevant event:
Comment #5
bennybobw commentedI'm looking at it in firefox and see this, so wonder if that's part of the issue:
> Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user’s experience.
Comment #6
arcataroger commentedThat warning has been around for years, though. I don't know if Chrome 83 maybe finally acted on the deprecation and imposed hard timeouts...? But if that's the case, the cancelation shouldn't happen so quickly. It seems to cancel out in less than a second (83 milliseconds, according to the netlog). That's way too short, no?
Comment #7
bennybobw commentedYeah it didn't work. I tried just changing async to always true and it's still getting canceled.
Comment #8
arcataroger commentedUnfortunately, updating to core 7.70 does NOT fix the issue, with or without the jquery_update module enabled.
Comment #9
cilefen commentedHello. I can't reproduce this on Chrome 83. Ajax involved with adding Paragraphs works.
Comment #10
bennybobw commentedI just tested this in Browserstack to be sure. They don't have Chrome 83 final yet but the have 83 beta and I tested in Windows 10. I can see multiple types of ajax requests getting canceled. I have a client who tested on MacOS Chrome 83 and had the same problem, and I tested in Chrome 83 on Linux.
Both of the sites tested have Drupal 7.69 installed and jquery_update to 1.8. One has paragraphs 7.x-1.0-rc5+36-dev and one has 7.x-1.0-rc5 (although you don't need paragraphs to reproduce this issue).
Perhaps it would be useful to make a minimal setup/test case?
Comment #11
Anonymous (not verified) commentedI believe this is related to forms having a file input, and how the jQuery Form Plugin submits the form using an iFrame rather than the normal xmlHttpRequest process. In my case, updating the jQuery Form Plugin to the latest version fixed the issue in Chrome 83. I have the jQuery update module so replaced the file in jquery_update\replace\misc and that resolved it.
Comment #12
cilefen commentedHere is the Chromium 83 for desktop release announcement, with links to all changes.
Comment #13
Collins405 commentedJust ran into this too.
All 6 servers, some of them multisites with hundreds of clients - all ajax file uploads are broken... BUT uploading a file on the profile (no ajax, image added in php WORKS)
Tested in Edge and a laptop with Chrome 81, and it works fine - so something in todays release has broken it.
Also looking into this now and will pitch in if I can help
Comment #14
Collins405 commentedComment #15
Collins405 commentedConfirmed Solution
Thanks to @ljames28 for his suggestion regarding jquery.form.js
The solution for me was to download jquery.form.js from https://github.com/jquery-form/form
Then replace jquery.form.js in the following locations....
/misc/jquery.form.js
/sites/all/modules/jquery_update/replace/misc/jquery.form.js
/sites/all/modules/jquery_update/replace/misc/jquery.form.min.js
I suggest the next version of Core is released with the new version included.
Comment #16
cilefen commentedComment #17
arcataroger commentedComment #18
arcataroger commentedThank you, @ljames28, for figuring that out! May I ask how you were able to locate the issue so quickly?
Linking to related jQuery-forms issue on Github: https://github.com/jquery-form/form/issues/571
Comment #19
arcataroger commentedComment #20
cilefen commentedIs Drupal 8 affected? It contains some version of jquery.form.min.js.
Comment #21
arcataroger commentedComment #22
mondrakeI tend to think it's connected... I presently cannot uplaod patches to drupal.org using Chrome.
EDIT - wrong... I can upload as the attached file demonstrates :) but it looks like I do not get the usual behaviour where the uploaded file get listed before I save the issue form.
Comment #23
chrisguindon commentedI am experiencing the same issue!
Comment #15 seems to be working for me so far.
I am attaching the two patches that I am currently using to address this problem.
drupal-update_jquery_form_js-3138421-23.patch will update /misc/jquery.form.js to the latest version from https://raw.githubusercontent.com/jquery-form/form/master/dist/jquery.fo...
I am not the author for jQuery Form Plugin.
Comment #24
chrisguindon commentedjquery_update-update_jquery_form_js-3138421-23.patch update the following files as defined in comment #15:
/sites/all/modules/jquery_update/replace/misc/jquery.form.js
/sites/all/modules/jquery_update/replace/misc/jquery.form.min.js
with :
https://raw.githubusercontent.com/jquery-form/form/master/dist/jquery.fo...
https://raw.githubusercontent.com/jquery-form/form/master/src/jquery.for...
Comment #25
beckydev commentedTo help promote the googleability of this issue... This can show in Watchdog logs as a file type error (for file uploads) with the message "The file upload failed. field_field_name"
Comment #26
mcdruid commentedCan anyone provide clear steps to reproduce this problem (ideally with just core, but if contrib modules are necessary, which ones etc..)?
I've tried testing with uploading images to a default article node (
node/add/article) and am not seeing a problem in Chrome 83. In that case, the upload results in a POST request tofile/ajax/field_image/und/0/form-BLAHdeBLAH.Also, anyone been able to verify whether D8 is also affected?
Comment #27
mcdruid commentedIt looks like this depends on whether the request is over https or http.
Testing the basic file upload on a node (e.g.
node/add/article) fails over https on Chrome 83.The POST request to
file/ajax/field_image/und/0/form-BLAHdeBLAHshows as(cancelled)in the network tab of dev tools.The same thing works okay on Chrome 81.
It looks like the code that's being discussed over in https://github.com/jquery-form/form/issues/571 behaves differently depending on the scheme (i.e. https or not).
Comment #28
george.karaivanov commented@mcdruid Yes, for me it looks that problem appear if site is invoked under https.
I couldn't reproduce problem locally and on stage. But I was able to reproduce on prod. Difference between those environments is only http and https connections.
Patches 24 and 24 solved issue.
Comment #29
Andrew.Dmytriv commentedFor me, the #24 patch didn't work until I added it
- $javascript['jquery.form']['version'] = '2.69';
+ $javascript['jquery.form']['version'] = '4.2.2';
Comment #30
mcdruid commentedThe same test as #26 / #27 doesn't have the same problem in D8, but ajax works quite differently in general; the POST request to upload an image goes to a path like
/node/add/article?element_parents=field_image/widget/0&ajax_form=1&_wrapper_format=drupal_ajax(where the form itself is/node/add/article) so that may account for a difference in behaviour.AFAICS jquery.form in D8 has the same code which seems to be causing the problem here, so I suspect D8 is affected but we likely need to find a different test.
Using FF's dev tools to pretty print D7's jquery.form.js this is the code that seems to be problematic:
Per the discussion in https://github.com/jquery-form/form/issues/571 it looks like the problem goes away if we change that so that
iframeSrcis always set toabout:blank.I don't understand the context of what's going on here well enough to know why we would have sometimes set this to
javascript:falseinstead, and what the consequences of making this change might be.Here's a patch which just makes that one change to D7's jquery.form.js (which is minified so not very diff friendly and fiddly to edit!) plus adds something silly to the version number in order to try to avoid caching in the browser just for testing.
AFAICS this fixes the problem in Chrome 83, but it may need some extra cache clearing (esp. the browser) to ensure the edited file is loaded for testing.
I'm not yet sure what the best approach to fixing this in core will be; I don't think we want to just update core to the newest version, but hacking around in a 10 year old minified JS file doesn't seem ideal either.
Some manual testing of this patch in different browsers would be good to verify the specific fix, but I doubt we'll commit this patch as is.
Comment #31
mcdruid commentedEdited IS now that we know a bit more.
Comment #32
longwavehttps://github.com/jquery-form/form/commit/ce4324159ecd44cab4779bef6f6d4... changed the default from about:blank to javascript:false for https URLs, but the commit doesn't explain why this was necessary.
Comment #33
kevster commentedJust tried patch in #30 and didnt work for me - Drupal 7.70, flushed caches, tried to add commerce product and adding variation does nothing.
EDIT: #15 worked for me - I had to stop using jquery CDN and switched to local with the files updated.
Comment #34
longwave@kevster I guess you have jquery_update installed? Seems like that will also need a similar fix.
Comment #35
mcdruid commentedhttps://stackoverflow.com/questions/4284605/iframe-without-an-src-attribute
...led me to:
https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-ifra...
...which says:
...which suggests that setting it to
about:blankshould be safe (that's how it always works for port 80).It's certainly a shame there's no comment to explain the conditional logic for https though.
Comment #36
alexpottI've tried to reproduce this on Drupal 8. I've use layout builder and settings tray and quick edit - all of which make copious use of the AJAX system but nothing was obviously broken. I've not yet had time to understand why Drupal 8 is apparently not affected but that would be a next step.
Comment #37
catchCould we override the method from jquery.form in a shim that we load alongside it, instead of patching the file? This would also mean that the fix will work for jquery_update (since it'll override that too).
Looks like even though Drupal 8 image uploads aren't affected, other things might be, so moving there for now.
Comment #38
drummThis did affect Drupal.org, for now I’ve deployed #30 across all our D7 sites. I double checked Chrome Canary, where this is also an issue, I don’t think this is something Chrome might back out.
Agreed a shim would be ideal.
Comment #39
arcataroger commented(Please forgive me if this is an ignorant question; I'm new here and not sure how Drupal core development likes to works for things like this...)
But: Might it be worth rewriting this ajax functionality in ES6, async/await, fetch, or some newer polyfill? Can we assume that more and more jQuery functions will break over time as third-party plugins are replaced by more modern JS?
Comment #40
catchWe do have issues open to refactor core JavaScript away from jQuery (see #3052002: [meta] Replace JQuery with vanilla Javascript in core and related issues), however major refactoring like that can only happen in minor releases - i.e. 9.1.x or later. At the moment, most of our focus is on replacing jQuery UI, since that is unsupported at this point, but work on reducing our reliance on jQuery itself is also welcome.
Comment #41
arcataroger commentedGot it, thanks @catch.
Comment #42
mcdruid commentedHere's an attempt at a shim patch which adds another new jquery file to D7.
This hopefully overrides only the one option we need to change.
It seems to work for me with vanilla D7. I've not tested it with jquery_update yet; it'd be great if people could do that.
A similar approach could probably be taken with the affected D8 branch(es), but focussing on D7 for now as that's much more obviously broken.
Comments etc... could be improved.
Comment #43
mcdruid commentedOops, sorry I didn't mean to change this back to 7.x (although that's handy for the testing of the last patch).
Comment #44
mcdruid commented#42 (which is named 40) seems to fix the problem with jquery_update 7.x-2.7 providing the defaults of jQuery 1.10.2 and jquery.form 2.69 AFAICS.
I'm not sure the automated tests will tell us much as there's not a lot of JS test coverage in D7.
Comment #45
CalamityJenI'm encountering this issue in version 83.0.478.37 of Microsoft Edge on Mac (version released 5/22/20) (Edge is based on Chromium, so this isn't too surprising)
Can the patch be tested against this version of Edge, as well?
Comment #46
mcdruid commentedGood idea to test in Edge (and any other chromium-based browsers) too.
Here's a tweak to the patch to include some logic which checks whether the
optionsparameter is a function before merging/extending it as an object, which happens in all of the versions of jquery.form I've looked at.Version 2.52 which ships with D7 core is pretty much what you get if you checkout commit df9cb10 from the github repo, FWIW.
In version 4.2.2 (which D8 ships with)
ajaxSubmitaccepts more parameters than the earlier versions, so we'll likely need to account for that too. I think there's also more parameter-processing logic before theiframeSrcthat we're trying to fix.Comment #47
timlie commentedPatch from #46 works with Chrome 83 over https. Tested with jquery_update 2.7 and jquery 1.7.2
Thanks!
Comment #48
mcdruid commentedPatch should now work with jQuery Form up to the newest releases (like v4.2.2 that D8 ships with).
Also added the empty hook_update_N for rebuilding JS libraries and cache.
I've manually tested file uploads in Chrome 83 with this patch and it works. It also doesn't seem to break e.g. Firefox.
I'd hope that this JS code could pretty much be lifted into D8.8 as well; I'll look at that in due course.
Appreciate more manual testing in the meantime, thanks!
Comment #49
mcdruid commentedOops I messed up that last patch, please ignore #48 and test this one instead.
Comment #50
mcdruid commentedPatch for 8.8.x with the same JS as the D7 patch in #49
As we've yet to find anything obviously broken in D8 it's hard to know exactly what to test, but some general regression testing of ajax-y functionality would be good. File uploads on a (https) node form seem to work fine AFAICS.
Comment #51
alexpott@mcdruid++ the d8 patch looks solid and it's great to see all the js tests pass. One problem is that we only run the JS tests under http and https so we've still not got any assurances that the original change in jQuery was not for a good reason.
Comment #52
steve hanson commentedI installed #48 and confirm that it seems to be working fine both in Chrome 83 and Edge. This is using jquery update with jquery 1.10.
Comment #53
alexpottThere are some reports that this fix breaks IE11 - see https://github.com/jquery-form/form/pull/572#issuecomment-632910005
So this fixes Edge but (potentially) breaks IE11. fun.
Comment #54
mcdruid commentedHmm, gotta love IE :)
Doing a quick test of the file upload in D7 with IE11 (and "legacy" EdgeHTML 13.x) I didn't actually see a problem with or without the fix, but FWIW here are a couple of patches which do a crude check of the UA and skip the override for MSIE/Trident.
Comment #55
swentel commentedI can confirm the problem. The interesting part though is that the actual upload does happen, you just don't see the feedback. When I then reload the page, the file field is populated. Hitting remove then removes the file, but you don't get the feedback. Reload again and the file field will be empty.
Saw this happening on a D7 project, but on a custom form using a file field, so not /node/add/type.
Comment #56
mcdruid commented@swentel that is interesting; I think I read in one of the jQuery Form github issues that the problem is with the "success" callback. If so, that would fit with your observation. Thanks!
Comment #57
swentel commentedAlso, I can confirm the patch for D7 solves the problem. File is still uploaded or removed, and you get feedback now, so great!
Tested with Chromium Version 85.0.4155.0 (Developer Build) (64-bit)
I don't have access to IE11, so can't help with that to confirm.
Side note: I think a PSA to announce this 'bug' would be great for the community :)
Comment #58
drummOld IE VMs are available at https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/
Comment #59
antonio.bertolini commentedHi all,
Same problem after updating to Drupal7.70, but not in all sites. I find different reaction on similar scenario, digging differences site by site, I solve installing jquery_update 7.x-3.0-alpha5 and update drupal.
Comment #60
hoporr commentedConfirmed: 3138421-54_d7.patch solved D7 problem on Chrome 83
Not tested on other browses, like IE.
Comment #61
beckydev commentedTested D7 patch in #54 successfully in Chrome 83 and IE11.
This was also a site with jquery_update enabled and unpatched, applying the core patch in #54 only and was able to successfully upload a file to a file field in both browsers.
Comment #62
paulrooney commentedConfirming that the D7 patch in #54 resolved the issue for us in Chrome 83.
Comment #63
jeremyr commentedAlso confirming the D7 patch in #54 resolves the problem. Have not yet tested in D8.
Comment #64
cferthorneyTested on Mac 10.15.4 with Chrome Version 83.0.4103.61 (Official Build) (64-bit), Works with D7 patch. Not tested D8 yet.
Comment #65
arcataroger commented#54 fixed it for me too in Chrome 83.0.4103.61 and Edge 83.0.478.37 on OSX. Thank you!Edit: Wait, maybe not... I spoke too soon. I tested it on the wrong environment (http). It still does not work on https for me. Investigating more...Edit 2: Fixed now. It was because I was using a nested docroot.
Had to replace `a/` and `b/` with `/a/docroot/` and `/b/docroot`/ in the patch before applying. Works now! (This probably depends on how you apply the patch. I was using PHPStorm's Apply Patch dialog, which doesn't let you specify a directory.)
Thanks again!
Comment #66
cferthorneyThe D8 patch in #54 Tested on Mac 10.15.4 with Chrome Version 83.0.4103.61 (Official Build) (64-bit). Works for me. Marking as RTBC as there have been several clarifications this is working now
Comment #67
stefan.kornHi, tested patch from #54 on Windows 10 and Ubuntu 18.04 with Chrome Version 83.0.4103.61 on Drupal 7.70. Working for me.
Comment #68
mcdruid commentedThanks for all the reviews.
I feel pretty comfortable saying #54 is ready for final review before commit for D7.
The situation with D8 is a bit less clear, as we've yet to identify anything that's obviously broken without this patch (which is probably also a reason why we've had fewer reviews of the D8 patch).
According to the backport policy we should have separate issues for D7 and D8 and the D7 child issue should be postponed until the D8 parent is resolved. With the next release for D7 due in about a week (2020-06-03), we don't want the D7 fix to be delayed though.
Comment #69
catchPosted a separate 7.x issue at #3143016: [D7] Chrome 83 cancels jquery.form ajax requests over https since the review and commit order can be independent for 7.x and 8.x/9.x.
Comment #70
nielsaers commentedTested the D7 patch from #54 on 7.69. All tests done over HTTPS.
Case 1: Unpatched
OSX Chrome 83: Ajax call got cancelled
Windows 10 IE11: Ajax call worked
Case 2: Patched
OSX Chrome 83: Ajax call worked
Windows 10 IE11: Ajax call worked
Did not test any other browsers.
Comment #71
dsnopekI found a small issue in the D7 patch:
The
log()function is undefined. This looks like it was copy-pasted from the jquery.form source code. This could probably be switched toconsole.log()?Anyway, in it's current form, if I run
jQuery().ajaxSubmit()in the dev console, I get a fatal error:Comment #72
cferthorney@dsnopek - The D7 patch is now at https://www.drupal.org/project/drupal/issues/3143016 (In case like me you hadn't noticed this, apologies if you knew)
Comment #73
dsnopekI didn't notice that, thanks! Here's an updated D8 patch that fixes the issue I pointed out in #71, just switching
log()toconsole.log(). I'll go post the same fix on the D7 issue in a moment.Comment #74
dsnopekHere's an updated patch to match the changes in the D7 patch on #3143016-8: [D7] Chrome 83 cancels jquery.form ajax requests over https based on review there. I haven't done the kind of extensive browser testing on this patch that I've done on the D7 version.
Comment #75
mcdruid commentedTweaks to the patch from #3143016-19: [D7] Chrome 83 cancels jquery.form ajax requests over https
Also removing "affects Drupal.org" as that applies to the D7 issue only, IIUC.
Comment #76
norman.lolComment #77
mastap commentedThanks, for #75 !
Comment #78
lauriiiDiscussed with @mcdruid whether this is needed or not, and based on his testing this is not needed for IE 11. Maybe we could leave this out from Drupal 8 at least, given that we don't support older IE versions than IE 11.
I'm still a bit concerned about this change because I'm not sure we know what was the reason for using
javascript:false, or why it broke with the latest version of Chrome. For example, I tested<iframe src="javascript:alert('alert')"></iframe>on Chrome and it seems to work fine, suggesting that inline JavaScript is still working.It seems like Chrome 83 has 38 security fixes so I'm wondering if they have something to do with this: https://chromereleases.googleblog.com/2020/05/stable-channel-update-for-....
Comment #79
longwaveThis has been reported to the Chromium bug tracker so worth keeping an eye on what's going on over there: https://bugs.chromium.org/p/chromium/issues/detail?id=1086008
Comment #80
arcataroger commentedFYI, a Chromium bugfix is on the way: https://bugs.chromium.org/p/chromium/issues/detail?id=1084874 (merged from 1086008)
Comment #81
effulgentsia commentedGiven that it's a bug with Chromium 83 only, and a fix is on the way for Chromium 84, would it be better to expand this to early return for all browsers that aren't Chromium 83? Is there a reliable way to test for that?
Comment #82
cilefen commentedHmmm: https://www.zdnet.com/article/google-to-phase-out-user-agent-strings-in-...
Comment #83
effulgentsia commentedI don't believe that Drupal 8 or 9 are affected. From reading the issue comments, I don't see any evidence that anyone reproduced it on 8.x or 9.x, so closing it, but please re-open if it is reproducible on 8 or 9.
The reason I don't think it's an issue on 8 or 9 is that jQuery Form 4.2.2 doesn't use the iframe if the browser supports file upload over XHR, which Chrome 83 does.
#3143016: [D7] Chrome 83 cancels jquery.form ajax requests over https is still an issue for D7 though, since jQuery Form 2.52 does not check for that ability.
Comment #84
amccune commentedPatch from #54 also resolved the issue for me on 7.70 with Chrome 83,. I was experiencing it on multiple sites. Thanks mcdruid.
Comment #85
justinmello32 commented#Patch 54 solved our problems across 4 sites, all 7.70 with Chrome 83, really appreciate the quick response!
Comment #86
google01 commentedPatches don't apply work on 10.3