6

In Chrome version 72.0.3626.96, I have a simple example where I set up an anchor <a> (styled as a button using bootstrap) and I also setup an <input type="file">. I hide the <input type="file"> using CSS and then use some JavaScript to trigger the file selection dialog when the anchor is clicked.

For example:

$('#upload-button').on('click', function(e) {
  if (confirm('Are you sure?')) {
    $('#upload-file').trigger('click');
  }
});
#upload-file {
  display: none;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@4.2.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div class="container">
  <div class="row">
    <div class="col">
      <a id="upload-button" class="btn btn-primary">
        <span>Upload Something!</span>
      </a>
      <input type="file" id="upload-file">
    </div>
  </div>  
</div>

The way it should work is that the user clicks on the <a> button, this launches a confirmation dialog, then, the user clicks "OK" and this opens the file selection dialog.

This works in Firefox and in earlier versions of Chrome, and oddly enough it even works in Chrome version 72.0.3626.96, as long as you click the "OK" button in the confirm message fast enough after it opens.

The bug is that if you wait 2-4 seconds after the confirm message opens and then click "OK" it will not open the file selection dialog.

Any ideas about how to make this work? Does it look like this is a legitimate bug in this release of Chrome that should be submitted?

UPDATE: I have come to the conclusion this is probably somehow related to security updates for User Activation (although I am not sure specifically why)... however it seems easier and cleaner in the long run anyway to just replace the old school confirm() with a more modern modal approach. Clicking an actual button within a bootstrap modal seems to always work correctly.

New Example Here:

$('#upload-button').on('click', function() {
  $('#upload-confirm-modal').modal();
});

$('#upload-confirm-button').on('click', function() {
  $('#upload-file').trigger('click');
  $('#upload-confirm-modal').modal('hide');
});
#upload-file {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>

<div class="container">
  <div class="row">
    <div class="col">
      <a id="upload-button" class="btn btn-primary">
        <span>Upload Something!</span>
      </a>
      <input type="file" id="upload-file">
    </div>
  </div>  
</div>

<!-- Modal -->
<div class="modal fade" id="upload-confirm-modal" role="dialog">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-body">
        <h4>Are you sure?</h4>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">No</button>
        <button type="button" class="btn btn-primary" id="upload-confirm-button">Yes</button>
      </div>
    </div>
  </div>
</div>
B. Humphries
  • 88
  • 1
  • 5
  • 1
    _"The bug is that if you wait 2-4 seconds after the confirm message opens and then click OK it will not open the file select dialog."_ Are you sure the implementation is a bug? Have you reviewed [Chrome Platform Status](https://www.chromestatus.com/features) for release updates and [bugs](https://bugs.chromium.org/p/chromium/issues/list) for similar bugs? See [Trigger click on input=file on asynchronous ajax done()](https://stackoverflow.com/q/29728705/) – guest271314 Feb 08 '19 at 22:27
  • your updated [fiddle](https://jsfiddle.net/aw87frhs/2/) – gaetanoM Feb 08 '19 at 22:39
  • @guest271314 Thank you for the feedback. The chain of events is triggered by a trusted user event (i.e. the click on the button) so I don't think it should be restricted based on the security implementation. I have not checked the release status or bugs pages for Chrome... going to start searching there now so thanks for the links. – B. Humphries Feb 08 '19 at 22:44
  • We just had a customer report something similar, though we were only doing the js click on a hidden to normalize the user experience across browser; we don't have any confirm dialogs or anything. Just an angular button with a click handler that does $timeout(function() { $scope.el.click(); }, 0, false); to pop up the file selector. It just stopped working in https, but still appears to work in http. – user1664043 Feb 13 '19 at 20:15
  • 1
    I'm not sure why someone put a $timeout around the click, but it seems like that may fill the role of "on asynchronous ajax done()" – user1664043 Feb 13 '19 at 20:22
  • Starting to suspect that there's an incompatibility with some version of jQuery, as the dropped events are in the jquery event model. – user1664043 Feb 13 '19 at 22:39
  • I also have this issue in one of my hidden input file implentation, and it worked before... the issue for me is that it works randomly.. – Miguel Feb 18 '19 at 12:30
  • @gaetanoM your fiddle works randomly, so its buggy. – Miguel Feb 18 '19 at 12:35
  • I've filed https://crbug.com/936505 – EricLaw Feb 27 '19 at 18:36

1 Answers1

2

The Chrome team has resolved this issue as By Design with the note that this was an intentional change made to prevent a user-activation flag from remaining set for too long. crbug.com/936505

I've asked them to consider adding a console warning for this scenario to aid future debuggers.

EricLaw
  • 56,563
  • 7
  • 151
  • 196