Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Add feature window.prompt #13563

Merged
merged 3 commits into from
May 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions app/browser/tabMessageBox.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const appActions = require('../../js/actions/appActions')
const tabMessageBoxState = require('../common/state/tabMessageBoxState')
const {makeImmutable} = require('../common/state/immutableUtil')
const locale = require('../../app/locale')

// callbacks for alert, confirm, etc.
let messageBoxCallbacks = {}
Expand All @@ -13,6 +14,23 @@ const cleanupCallback = (tabId) => {
return false
}

const onWindowPrompt = show => (webContents, extraData, title, message, defaultPromptText,
shouldDisplaySuppressCheckbox, isBeforeUnloadDialog, isReload, muonCb) => {
const tabId = webContents.getId()
const detail = {
message,
title,
buttons: [locale.translation('messageBoxOk'), locale.translation('messageBoxCancel')],
cancelId: 1,
suppress: false,
allowInput: true,
defaultPromptText,
showSuppress: shouldDisplaySuppressCheckbox
}

show(tabId, detail, muonCb)
}

const tabMessageBox = {
init: (state, action) => {
process.on('window-alert', (webContents, extraData, title, message, defaultPromptText,
Expand All @@ -21,7 +39,7 @@ const tabMessageBox = {
const detail = {
message,
title,
buttons: ['ok'],
buttons: [locale.translation('messageBoxOk')],
suppress: false,
showSuppress: shouldDisplaySuppressCheckbox
}
Expand All @@ -35,7 +53,7 @@ const tabMessageBox = {
const detail = {
message,
title,
buttons: ['ok', 'cancel'],
buttons: [locale.translation('messageBoxOk'), locale.translation('messageBoxCancel')],
cancelId: 1,
suppress: false,
showSuppress: shouldDisplaySuppressCheckbox
Expand All @@ -44,12 +62,7 @@ const tabMessageBox = {
tabMessageBox.show(tabId, detail, muonCb)
})

process.on('window-prompt', (webContents, extraData, title, message, defaultPromptText,
shouldDisplaySuppressCheckbox, isBeforeUnloadDialog, isReload, muonCb) => {
console.warn('window.prompt is not supported yet')
let suppress = false
muonCb(null, '', suppress)
})
process.on('window-prompt', onWindowPrompt(tabMessageBox.show))

return state
},
Expand All @@ -70,6 +83,7 @@ const tabMessageBox = {
const muonCb = messageBoxCallbacks[tabId]
let suppress = false
let result = true
let input = ''
state = tabMessageBoxState.removeDetail(state, action)
if (muonCb) {
cleanupCallback(tabId)
Expand All @@ -80,7 +94,10 @@ const tabMessageBox = {
if (detail.has('result')) {
result = detail.get('result')
}
muonCb(result, '', suppress)
if (detail.has('input')) {
input = detail.get('input')
}
muonCb(result, input, suppress)
} else {
muonCb(false, '', false)
}
Expand Down Expand Up @@ -130,3 +147,4 @@ const tabMessageBox = {
}

module.exports = tabMessageBox
module.exports.onWindowPrompt = onWindowPrompt
2 changes: 2 additions & 0 deletions app/extensions/brave/locales/en-US/menu.properties
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ learnSpelling=Learn Spelling
licenseText=This software uses libraries from the FFmpeg project under the LGPLv2.1
lookupSelection=Look Up “{{selectedVariable}}”
mergeAllWindows=Merge All Windows
messageBoxOk=ok
messageBoxCancel=cancel
minimize=Minimize
moveTabToNewWindow=Move to New Window
muteOtherTabs=Mute other Tabs
Expand Down
2 changes: 2 additions & 0 deletions app/locale.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ var rendererIdentifiers = function () {
'dappDismiss',
'dappEnableExtension',
'banSiteConfirmation',
'messageBoxOk',
'messageBoxCancel',
// other
'passwordsManager',
'extensionsManager',
Expand Down
31 changes: 31 additions & 0 deletions app/renderer/components/common/messageBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const Dialog = require('./dialog')
const FlyoutDialog = require('./flyoutDialog')
const BrowserButton = require('../common/browserButton')
const SwitchControl = require('./switchControl')
const {PromptTextBox} = require('./textbox')

// Actions
const appActions = require('../../../../js/actions/appActions')
Expand All @@ -36,12 +37,21 @@ class MessageBox extends React.Component {
super(props)
this.onKeyDown = this.onKeyDown.bind(this)
this.onSuppressChanged = this.onSuppressChanged.bind(this)
this.state = {
textInput: props.defaultPromptText
}
}

componentWillMount () {
document.addEventListener('keydown', this.onKeyDown)
}

componentDidMount () {
if (this.props.allowInput) {
this.inputRef.select()
}
}

componentWillUnmount () {
document.removeEventListener('keydown', this.onKeyDown)
}
Expand Down Expand Up @@ -82,6 +92,10 @@ class MessageBox extends React.Component {
response.result = buttonId !== this.props.cancelId
}

if (this.props.allowInput) {
response.input = this.state.textInput
}

appActions.tabMessageBoxDismissed(tabId, response)
}

Expand Down Expand Up @@ -112,6 +126,8 @@ class MessageBox extends React.Component {
// used in renderer
props.tabId = tabId
props.message = messageBoxDetail.get('message')
props.allowInput = messageBoxDetail.get('allowInput')
props.defaultPromptText = messageBoxDetail.get('defaultPromptText')
props.suppress = tabMessageBoxState.getSuppress(state, tabId)
props.title = tabMessageBoxState.getTitle(state, tabId)
props.showSuppress = tabMessageBoxState.getShowSuppress(state, tabId)
Expand Down Expand Up @@ -151,6 +167,21 @@ class MessageBox extends React.Component {
/>
: null
}
{
this.props.allowInput && (
<PromptTextBox
value={this.state.textInput}
inputRef={ref => {
this.inputRef = ref
}}
onChange={e => {
this.setState({
textInput: e.target.value
})
}}
/>
)
}
<div className={css(styles.buttons)} data-test-id='msgBoxButtons'>
{this.messageBoxButtons}
</div>
Expand Down
16 changes: 15 additions & 1 deletion app/renderer/components/common/textbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ class Textbox extends ImmutableComponent {
(this.props.readonly || this.props.readOnly) ? styles.readOnly : styles.outlineable,
this.props['data-isCommonForm'] && commonStyles.isCommonForm,
this.props['data-isSettings'] && styles.isSettings,
this.props['data-isPrompt'] && styles.isPrompt,
this.props.customClass && this.props.customClass
)

const props = Object.assign({}, this.props)
const ref = this.props.inputRef
delete props.customClass
delete props.inputRef

return <input type='text' className={className} {...props} />
return <input type='text' className={className} {...props} ref={ref} />
}
}

Expand Down Expand Up @@ -66,6 +69,12 @@ class SettingTextbox extends ImmutableComponent {
}
}

class PromptTextBox extends ImmutableComponent {
render () {
return <FormTextbox data-isPrompt='true' {...this.props} />
}
}

// TextArea
class TextArea extends ImmutableComponent {
render () {
Expand Down Expand Up @@ -160,6 +169,10 @@ const styles = StyleSheet.create({
isSettings: {
width: '280px'
},
isPrompt: {
width: '100%',
marginBottom: '20px'
},
readOnly: {
background: globalStyles.color.lightGray,
boxShadow: 'none',
Expand Down Expand Up @@ -248,6 +261,7 @@ module.exports = {
FormTextbox,
GroupedFormTextbox,
SettingTextbox,
PromptTextBox,
TextArea,
DefaultTextArea,
WordCountTextArea
Expand Down
48 changes: 48 additions & 0 deletions test/unit/app/browser/tabMessageBoxTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,13 @@ describe('tabMessageBox unit tests', function () {
useCleanCache: true
})

const fakeLocale = {
translation: (token) => { return token }
}

mockery.registerMock('electron', require('../../lib/fakeElectron'))
mockery.registerMock('../common/state/tabMessageBoxState', fakeMessageBoxState)
mockery.registerMock('../../../js/l10n', fakeLocale)
tabMessageBox = require('../../../../app/browser/tabMessageBox')
appActions = require('../../../../js/actions/appActions')

Expand Down Expand Up @@ -224,4 +229,47 @@ describe('tabMessageBox unit tests', function () {
})
})
})

describe('onWindowPrompt', () => {
const tabId = '123'
const webContents = {
getId: () => tabId
}
const extraData = undefined
const title = 'some title'
const message = 'some message'
const defaultPromptText = 'some prompt text'
const shouldDisplaySuppressCheckbox = true
const isBeforeUnloadDialog = undefined
const isReload = undefined
const muonCb = 'muonCb'

it('calls tabMessageBox.show', () => {
const mockShow = sinon.stub()
const expectecDetail = {
message,
title,
buttons: ['MESSAGEBOXOK', 'MESSAGEBOXCANCEL'],
cancelId: 1,
suppress: false,
allowInput: true,
defaultPromptText,
showSuppress: shouldDisplaySuppressCheckbox
}

tabMessageBox.onWindowPrompt(mockShow)(
webContents,
extraData,
title,
message,
defaultPromptText,
shouldDisplaySuppressCheckbox,
isBeforeUnloadDialog,
isReload,
muonCb
)

assert.equal(mockShow.withArgs(tabId, expectecDetail, muonCb).calledOnce, true)
})
})
})
56 changes: 55 additions & 1 deletion test/unit/app/renderer/components/common/messageBoxTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,25 @@ let appState = Immutable.fromJS({
}
})

const createAppState = detail => Immutable.fromJS({
windows: [{
windowId: 1,
windowUUID: 'uuid'
}],
tabs: [{
tabId: tabId,
windowId: 1,
windowUUID: 'uuid',
url: 'https://brave.com',
messageBoxDetail: detail
}],
tabsInternal: {
index: {
1: 0
}
}
})

describe('MessageBox component unit tests', function () {
before(function () {
mockery.enable({
Expand All @@ -60,7 +79,7 @@ describe('MessageBox component unit tests', function () {

describe('Rendering', function () {
before(function () {
appStoreRenderer.state = Immutable.fromJS(appState)
appStoreRenderer.state = createAppState(detail1)
})
it('renders itself inside a dialog component', function () {
const wrapper = mount(
Expand Down Expand Up @@ -98,6 +117,19 @@ describe('MessageBox component unit tests', function () {
assert.equal(wrapper.find('button[data-l10n-id="Cancel"][data-test-id="secondaryColor"]').length, 1)
})

it('renders the PromptTextBox when input is allowed', function () {
appStoreRenderer.state = createAppState(Object.assign({}, detail1, {
allowInput: true
}))
const wrapper = mount(
<MessageBox
tabId={tabId}
allowInput
/>
)
assert.equal(wrapper.find('PromptTextBox').length, 1)
})

it('hides the suppress checkbox if showSuppress is false', function () {
const appState2 = appState.setIn(['tabs', 0, 'messageBoxDetail', 'showSuppress'], false)
appStoreRenderer.state = Immutable.fromJS(appState2)
Expand Down Expand Up @@ -158,5 +190,27 @@ describe('MessageBox component unit tests', function () {
assert.equal(spy.withArgs(tabId, response).calledOnce, true)
appActions.tabMessageBoxDismissed.restore()
})

it('calls appActions.tabMessageBoxDismissed with input input is allowed', function () {
const expectedInput = 'some input'
appStoreRenderer.state = createAppState(Object.assign({}, detail1, {
allowInput: true,
defaultPromptText: expectedInput
}))
const spy = sinon.spy(appActions, 'tabMessageBoxDismissed')
const wrapper = mount(
<MessageBox
tabId={tabId}
/>
)
const response = {
suppress: detail1.suppress,
result: false,
input: expectedInput
}
wrapper.find('button[data-l10n-id="Cancel"][data-test-id="secondaryColor"]').simulate('click')
assert.equal(spy.withArgs(tabId, response).calledOnce, true)
appActions.tabMessageBoxDismissed.restore()
})
})
})