Skip to content

Commit

Permalink
fix: handle shortcuts by default if no WebPreferences object exists (e…
Browse files Browse the repository at this point in the history
…lectron#14766)

DevTools webcontents do not have webpreferences

Fixes electron#14685
  • Loading branch information
MarshallOfSound authored Sep 27, 2018
1 parent 0d2a0c7 commit 6be6904
Show file tree
Hide file tree
Showing 6 changed files with 582 additions and 44 deletions.
26 changes: 14 additions & 12 deletions atom/browser/common_web_contents_delegate_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,20 @@ - (void)redispatchKeyEvent:(NSEvent*)event;
if (event.windows_key_code == ui::VKEY_ESCAPE && is_html_fullscreen())
ExitFullscreenModeForTab(source);

if (auto* web_preferences = WebContentsPreferences::From(source)) {
if (!web_preferences->IsEnabled("ignoreMenuShortcuts", false)) {
// Send the event to the menu before sending it to the window
if (event.os_event.type == NSKeyDown &&
[[NSApp mainMenu] performKeyEquivalent:event.os_event])
return;

if (event.os_event.window &&
[event.os_event.window isKindOfClass:[EventDispatchingWindow class]])
[event.os_event.window redispatchKeyEvent:event.os_event];
}
}
// Check if the webContents has preferences and to ignore shortcuts
auto* web_preferences = WebContentsPreferences::From(source);
if (web_preferences &&
web_preferences->IsEnabled("ignoreMenuShortcuts", false))
return;

// Send the event to the menu before sending it to the window
if (event.os_event.type == NSKeyDown &&
[[NSApp mainMenu] performKeyEquivalent:event.os_event])
return;

if (event.os_event.window &&
[event.os_event.window isKindOfClass:[EventDispatchingWindow class]])
[event.os_event.window redispatchKeyEvent:event.os_event];
}

} // namespace atom
13 changes: 8 additions & 5 deletions atom/browser/common_web_contents_delegate_views.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ void CommonWebContentsDelegate::HandleKeyboardEvent(
if (event.windows_key_code == ui::VKEY_ESCAPE && is_html_fullscreen())
ExitFullscreenModeForTab(source);

// Check if the webContents has preferences and to ignore shortcuts
auto* web_preferences = WebContentsPreferences::From(source);
if (web_preferences &&
web_preferences->IsEnabled("ignoreMenuShortcuts", false))
return;

// Let the NativeWindow handle other parts.
if (auto* web_preferences = WebContentsPreferences::From(source)) {
if (owner_window() &&
!web_preferences->IsEnabled("ignoreMenuShortcuts", false)) {
owner_window()->HandleKeyboardEvent(source, event);
}
if (owner_window()) {
owner_window()->HandleKeyboardEvent(source, event);
}
}

Expand Down
57 changes: 56 additions & 1 deletion spec/api-web-contents-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const { emittedOnce } = require('./events-helpers')
const chai = require('chai')
const dirtyChai = require('dirty-chai')

const { ipcRenderer, remote } = require('electron')
const { ipcRenderer, remote, clipboard } = require('electron')
const { BrowserWindow, webContents, ipcMain, session } = remote
const { expect } = chai

Expand Down Expand Up @@ -255,6 +255,61 @@ describe('webContents module', () => {
})
})

describe('devtools window', () => {
let testFn = it
if (process.platform === 'darwin' && isCi) {
testFn = it.skip
}
try {
// We have other tests that check if native modules work, if we fail to require
// robotjs let's skip this test to avoid false negatives
require('robotjs')
} catch (err) {
testFn = it.skip
}

testFn('can receive and handle menu events', async function () {
this.timeout(5000)
w.show()
w.loadFile(path.join(fixtures, 'pages', 'key-events.html'))
// Ensure the devtools are loaded
w.webContents.closeDevTools()
const opened = emittedOnce(w.webContents, 'devtools-opened')
w.webContents.openDevTools()
await opened
await emittedOnce(w.webContents.devToolsWebContents, 'did-finish-load')
w.webContents.devToolsWebContents.focus()

// Focus an input field
await w.webContents.devToolsWebContents.executeJavaScript(
`const input = document.createElement('input');
document.body.innerHTML = '';
document.body.appendChild(input)
input.focus();`
)

// Write something to the clipboard
clipboard.writeText('test value')

// Fake a paste request using robotjs to emulate a REAL keyboard paste event
require('robotjs').keyTap('v', process.platform === 'darwin' ? ['command'] : ['control'])

const start = Date.now()
let val

// Check every now and again for the pasted value (paste is async)
while (val !== 'test value' && Date.now() - start <= 1000) {
val = await w.webContents.devToolsWebContents.executeJavaScript(
`document.querySelector('input').value`
)
await new Promise(resolve => setTimeout(resolve, 10))
}

// Once we're done expect the paste to have been successful
expect(val).to.equal('test value', 'value should eventually become the pasted value')
})
})

describe('sendInputEvent(event)', () => {
beforeEach((done) => {
w.loadFile(path.join(fixtures, 'pages', 'key-events.html'))
Expand Down
Loading

0 comments on commit 6be6904

Please sign in to comment.