Make file-picker modal in Chromium for Linux
When I started working on Chromium, I found a bug in Chromium for Linux: the file-picker was not modal. So, while a file-picker was open, the user could still control the main window. Sometimes this caused misbehavior — for example, you could send an email while still attaching a file.
There was already a bug filed and it seemed easy to fix, but it took two years to fully resolve.
The root cause is as follows.
Chromium for Linux uses GtkFileChooserDialog to open a file-picker, but it is
not modal to the X11 host window because GtkFileChooserDialog can only be modal
to its parent GtkWindow. So I tried to let the X11 host window disable input
event handling to make the file-picker modal. Here are the details.
Opening a file-picker
DisableEventListening() disables event listening for the host window using
aura::ScopedWindowTargeter, which temporarily replaces the event targeter with
ui::NullEventTargeter. It returns a scope handle that is used to call
destroy_callback when the file-picker closes.
class ScopedHandle {
public:
explicit ScopedHandle(const base::Closure& destroy_callback);
~ScopedHandle();
void CancelCallback();
private:
base::Closure destroy_callback_;
DISALLOW_COPY_AND_ASSIGN(ScopedHandle);
};In addition, we also set another destroy callback (OnFilePickerDestroy) on the
GtkFileChooserDialog that is called when the file-picker is closed.
Closing the file-picker
As you can see, OnFilePickerDestroy deletes scoped_handle.
void OnFilePickerDestroy(views::DesktopWindowTreeHostX11::ScopedHandle*
scoped_handle) {
delete scoped_handle;
}Then the destroy_callback of ScopedHandle below is automatically called.
void DesktopWindowTreeHostX11::EnableEventListening() {
DCHECK(modal_dialog_xid_);
modal_dialog_xid_ = 0;
targeter_for_modal_.reset();
}You can find more details and discussion in this design doc.
The first change list was reverted due to a UI-freezing problem that happened when the user opened a file-picker from a child window of the X11 host window. The second change list finally fixed this issue (BUG 408481, 579408). I also added a test case for the fix: BrowserSelectFileDialogTest.ModalTest.