diff --git a/app/extensions.js b/app/extensions.js index d964b030334..b11427b801b 100644 --- a/app/extensions.js +++ b/app/extensions.js @@ -111,7 +111,7 @@ let generateBraveManifest = () => { 'form-action': '\'none\'', 'referrer': 'no-referrer', 'style-src': '\'self\' \'unsafe-inline\'', - 'img-src': '\'self\' data:' + 'img-src': '* data:' } if (process.env.NODE_ENV === 'development') { diff --git a/app/extensions/brave/locales/en-US/preferences.properties b/app/extensions/brave/locales/en-US/preferences.properties index 6e40a9b4654..46ed631e8e6 100644 --- a/app/extensions/brave/locales/en-US/preferences.properties +++ b/app/extensions/brave/locales/en-US/preferences.properties @@ -43,7 +43,9 @@ startsWithOptionLastTime=my windows / tabs from last time startsWithOptionHomePage=my home page startsWithOptionNewTabPage=the new tab page myHomepage=My homepage is -defaultSearchEngine=Default search engine: +default=Default +searchEngine=Search Engine +engineGoKey=Engine Go Key (Type First) switchToNewTabs=Switch to new tabs immediately paintTabs=Show tabs in page theme color tabsPerTabPage=Number of tabs per tab set: diff --git a/app/sessionStore.js b/app/sessionStore.js index 198f50c4d31..7898deffbc8 100644 --- a/app/sessionStore.js +++ b/app/sessionStore.js @@ -301,6 +301,13 @@ module.exports.loadAppState = () => { try { data = Object.assign(module.exports.defaultAppState(), JSON.parse(data)) + // xml migration + if (data.settings['search.default-search-engine'] === 'content/search/google.xml') { + data.settings['search.default-search-engine'] = 'Google' + } + if (data.settings['search.default-search-engine'] === 'contnt/search/duckduckgo.xml') { + data.settings['search.default-search-engine'] = 'DuckDuckGo' + } } catch (e) { // TODO: Session state is corrupted, maybe we should backup this // corrupted value for people to report into support. diff --git a/docs/state.md b/docs/state.md index 04181771a24..5860f47bde9 100644 --- a/docs/state.md +++ b/docs/state.md @@ -134,7 +134,7 @@ AppStore 'general.downloads.default-save-path': string, // default path for saving files 'general.autohide-menu': boolean, // true if the Windows menu should be autohidden 'general.disable-title-mode': boolean, // true if title mode should always be disabled - 'search.default-search-engine': string, // path to the open search XML + 'search.default-search-engine': string, // name of search engine, from js/data/searchProviders.js 'search.offer-search-suggestions': boolean, // true if suggestions should be offered from the default search engine when available. 'tabs.switch-to-new-tabs': boolean, // true if newly opened tabs should be focused immediately 'tabs.paint-tabs': boolean, // true if the page theme color and favicon color should be used for tabs diff --git a/js/about/preferences.js b/js/about/preferences.js index bfd3449ebe5..0350d94d3cb 100644 --- a/js/about/preferences.js +++ b/js/about/preferences.js @@ -16,6 +16,8 @@ const messages = require('../constants/messages') const settings = require('../constants/settings') const aboutActions = require('./aboutActions') const getSetting = require('../settings').getSetting +const SortableTable = require('../components/sortableTable') +const searchProviders = require('../data/searchProviders') const adblock = appConfig.resourceNames.ADBLOCK const cookieblock = appConfig.resourceNames.COOKIEBLOCK @@ -173,19 +175,68 @@ class GeneralTab extends ImmutableComponent { } } +class SearchSelectEntry extends ImmutableComponent { + shouldComponentUpdate (nextProps, nextState) { + return this.props.settings.get('search.default-search-engine') !== nextProps.settings.get('search.default-search-engine') + } + render () { + return
+ {this.props.settings.get('search.default-search-engine') === this.props.name + ? : null} +
+ } +} + +class SearchEntry extends ImmutableComponent { + render () { + return
+ + + {this.props.name} +
+ } +} + +class SearchShortcutEntry extends ImmutableComponent { + render () { + return
+ {this.props.shortcut} +
+ } +} + class SearchTab extends ImmutableComponent { + get searchProviders () { + let entries = searchProviders.providers + let array = [] + const iconSize = 16 + entries.forEach((entry) => { + let iconStyle = { + backgroundImage: `url(${entry.image})`, + minWidth: iconSize, + width: iconSize, + backgroundSize: iconSize, + height: iconSize, + display: 'inline-block', + verticalAlign: 'middle' + } + array.push([, + , + ]) + }) + return array + } + + hoverCallback (rows) { + this.props.onChangeSetting(settings.DEFAULT_SEARCH_ENGINE, rows[1].props.children.props.name) + } + render () { return
- - - - - +
diff --git a/js/components/main.js b/js/components/main.js index 158844121e9..ed8cc28ffc2 100644 --- a/js/components/main.js +++ b/js/components/main.js @@ -11,7 +11,6 @@ const ipc = electron.ipcRenderer // Actions const windowActions = require('../actions/windowActions') const webviewActions = require('../actions/webviewActions') -const loadOpenSearch = require('../lib/openSearch').loadOpenSearch const contextMenus = require('../contextMenus') const getSetting = require('../settings').getSetting const getOrigin = require('../state/siteUtil').getOrigin @@ -48,6 +47,8 @@ const keyCodes = require('../constants/keyCodes') // State handling const FrameStateUtil = require('../state/frameStateUtil') +const searchProviders = require('../data/searchProviders') + // Util const cx = require('../lib/classSet.js') const eventUtil = require('../lib/eventUtil') @@ -201,16 +202,25 @@ class Main extends ImmutableComponent { ipc.on(messages.LEAVE_FULL_SCREEN, this.exitFullScreen.bind(this)) } - loadOpenSearch () { + loadSearchProviders () { + let entries = searchProviders.providers let engine = getSetting(settings.DEFAULT_SEARCH_ENGINE) - if (this.lastLoadedOpenSearch === undefined || engine !== this.lastLoadedOpenSearch) { - loadOpenSearch(engine).then((searchDetail) => windowActions.setSearchDetail(searchDetail)) - this.lastLoadedOpenSearch = engine + if (this.lastLoadedSearchProviders === undefined || engine !== this.lastLoadedSearchProviders) { + entries.forEach((entry) => { + if (entry.name === engine) { + windowActions.setSearchDetail(Immutable.fromJS({ + searchURL: entry.search, + autocompleteURL: entry.autocomplete + })) + this.lastLoadedSearchProviders = engine + return false + } + }) } } componentDidUpdate (prevProps) { - this.loadOpenSearch() + this.loadSearchProviders() const activeFrame = FrameStateUtil.getActiveFrame(this.props.windowState) const activeFramePrev = FrameStateUtil.getActiveFrame(prevProps.windowState) const activeFrameTitle = activeFrame && (activeFrame.get('title') || activeFrame.get('location')) || '' @@ -369,7 +379,7 @@ class Main extends ImmutableComponent { windowActions.setContextMenuDetail() }) - this.loadOpenSearch() + this.loadSearchProviders() window.addEventListener('mousemove', (e) => { if (e.pageY !== this.pageY) { diff --git a/js/components/sortableTable.js b/js/components/sortableTable.js index 2018186f0e3..3bdaf93ae7c 100644 --- a/js/components/sortableTable.js +++ b/js/components/sortableTable.js @@ -14,6 +14,7 @@ class SortableTable extends ImmutableComponent { componentDidMount (event) { return tableSort(document.getElementsByClassName('sortableTable')[0]) } + render () { var headings = [] var rows = [] @@ -26,7 +27,8 @@ class SortableTable extends ImmutableComponent { headings[j] = headings[j] || rows[i][j] = {this.props.rows[i][j] === true ? '✕' : this.props.rows[i][j]} } - rows[i] = {rows[i]} + rows[i] = {rows[i]} } return @@ -43,7 +45,9 @@ class SortableTable extends ImmutableComponent { SortableTable.defaultProps = { headings: React.PropTypes.array.isRequired, - rows: React.PropTypes.array.isRequired + rows: React.PropTypes.array.isRequired, + isHover: React.PropTypes.bool, + hoverCallback: React.PropTypes.func } module.exports = SortableTable diff --git a/js/components/urlBar.js b/js/components/urlBar.js index 117a828b525..c070fd9a2eb 100644 --- a/js/components/urlBar.js +++ b/js/components/urlBar.js @@ -21,6 +21,8 @@ const contextMenus = require('../contextMenus') const dndData = require('../dndData') const pdfjsExtensionId = require('../constants/config').PDFJSExtensionId const windowStore = require('../stores/windowStore') +var searchProviders = require('../data/searchProviders') +const searchIconSize = 16 const { isUrl, isIntermediateAboutPage } = require('../lib/appUrlUtil') @@ -35,6 +37,8 @@ class UrlBar extends ImmutableComponent { this.onChange = this.onChange.bind(this) this.onClick = this.onClick.bind(this) this.onContextMenu = this.onContextMenu.bind(this) + this.activateSearchEngine = false + this.searchSelectEntry = null } get activeFrame () { @@ -121,6 +125,11 @@ class UrlBar extends ImmutableComponent { this.urlBarSuggestions.clickSelected(e) } else { let searchUrl = this.props.searchDetail.get('searchURL').replace('{searchTerms}', encodeURIComponent(location)) + if (this.activateSearchEngine && this.searchSelectEntry !== null && !isLocationUrl) { + const replaceRE = new RegExp('^' + this.searchSelectEntry.shortcut + ' ', 'g') + location = location.replace(replaceRE, '') + searchUrl = this.searchSelectEntry.search.replace('{searchTerms}', encodeURIComponent(location)) + } location = isLocationUrl ? location : searchUrl // do search. if (e.altKey) { @@ -134,6 +143,7 @@ class UrlBar extends ImmutableComponent { // this can't go through appActions for some reason // or the whole window will reload on the first page request this.updateDOMInputFocus(false) + this.clearSearchEngine() } break case KeyCodes.UP: @@ -156,6 +166,7 @@ class UrlBar extends ImmutableComponent { case KeyCodes.ESC: e.preventDefault() ipc.emit(messages.SHORTCUT_ACTIVE_FRAME_STOP) + this.clearSearchEngine() break case KeyCodes.DELETE: if (e.shiftKey) { @@ -193,6 +204,7 @@ class UrlBar extends ImmutableComponent { // On blur, a user expects the text shown from the last autocomplete suffix // to be auto entered as the new location. this.updateLocationToSuggestion() + this.clearSearchEngine() } updateLocationToSuggestion () { @@ -201,14 +213,40 @@ class UrlBar extends ImmutableComponent { } } + detectSearchEngine (input) { + let location = input || this.props.urlbar.get('location') + if (location !== null && location.length !== 0) { + const isLocationUrl = isUrl(location) + if (!isLocationUrl && + !(this.searchSelectEntry && location.startsWith(this.searchSelectEntry.shortcut + ' '))) { + let entries = searchProviders.providers + entries.forEach((entry) => { + if (location.startsWith(entry.shortcut + ' ')) { + this.activateSearchEngine = true + this.searchSelectEntry = entry + return false + } + }) + } + } + } + + clearSearchEngine () { + this.activateSearchEngine = false + this.searchSelectEntry = null + } + onChange (e) { windowActions.setUrlBarSelected(false) windowActions.setUrlBarActive(true) windowActions.setNavBarUserInput(e.target.value) + this.clearSearchEngine() + this.detectSearchEngine(e.target.value) } onFocus (e) { windowActions.setUrlBarSelected(true) + this.detectSearchEngine() } onActiveFrameStop () { @@ -337,12 +375,24 @@ class UrlBar extends ImmutableComponent { onClick={this.onSiteInfo} className={cx({ urlbarIcon: true, - 'fa': true, - 'fa-lock': this.isHTTPPage && this.props.isSecure && !this.props.urlbar.get('active'), - 'fa-unlock-alt': this.isHTTPPage && !this.props.isSecure && !this.props.urlbar.get('active') && !this.props.titleMode, - 'fa fa-file': this.props.urlbar.get('active') && this.props.loading === false, + 'fa': !this.activateSearchEngine, + 'fa-lock': !this.activateSearchEngine && this.isHTTPPage && this.isSecure && !this.props.urlbar.get('active'), + 'fa-unlock-alt': !this.activateSearchEngine && this.isHTTPPage && !this.isSecure && !this.props.urlbar.get('active') && !this.props.titleMode, + 'fa fa-file': !this.activateSearchEngine && this.props.urlbar.get('active') && this.props.loading === false, extendedValidation: this.extendedValidationSSL - })} /> + })} + style={ + this.activateSearchEngine + ? { + backgroundImage: `url(${this.searchSelectEntry.image})`, + minWidth: searchIconSize, + width: searchIconSize, + backgroundSize: searchIconSize, + height: searchIconSize, + marginTop: '3px', + marginRight: '3px' + } : {} + } /> { this.props.titleMode ?
diff --git a/js/constants/appConfig.js b/js/constants/appConfig.js index 702bfe8e917..69d8a122c87 100644 --- a/js/constants/appConfig.js +++ b/js/constants/appConfig.js @@ -86,7 +86,7 @@ module.exports = { 'general.show-home-button': false, 'general.useragent.value': null, // Set at runtime 'general.autohide-menu': true, - 'search.default-search-engine': 'content/search/google.xml', + 'search.default-search-engine': 'Google', 'search.offer-search-suggestions': false, // false by default for privacy reasons 'tabs.switch-to-new-tabs': false, 'tabs.paint-tabs': true, diff --git a/js/contextMenus.js b/js/contextMenus.js index b9685bfe562..9d3cf714eb4 100644 --- a/js/contextMenus.js +++ b/js/contextMenus.js @@ -788,7 +788,7 @@ function mainTemplateInit (nodeProps, frame) { }, copyAddressMenuItem('copyImageAddress', nodeProps.srcURL) ) - if (getSetting(settings.DEFAULT_SEARCH_ENGINE) === 'content/search/google.xml' && + if (getSetting(settings.DEFAULT_SEARCH_ENGINE) === 'Google' && nodeProps.srcURL && urlParse(nodeProps.srcURL).protocol !== 'data:') { template.push( { diff --git a/js/data/searchProviders.js b/js/data/searchProviders.js new file mode 100644 index 00000000000..9c41193617b --- /dev/null +++ b/js/data/searchProviders.js @@ -0,0 +1,65 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +module.exports = { "providers" : + [ + { + "name" : "Amazon", + "image" : "http://www.amazon.com/favicon.ico", + "search" : "http://www.amazon.com/exec/obidos/external-search/?field-keywords={searchTerms}&mode=blended", + "autocomplete" : "http://completion.amazon.com/search/complete?method=completion&q={searchTerms}&search-alias=aps&client=amazon-search-ui&mkt=1", + "shortcut" : "a" + }, + { + "name" : "Bing", + "image" : "https://www.bing.com/favicon.ico", + "search" : "https://www.bing.com/search?q={searchTerms}", + "autocomplete" : "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}&form=OSDJAS", + "shortcut" : "b" + }, + { + "name" : "DuckDuckGo", + "image" : "https://duckduckgo.com/favicon.ico", + "search" : "https://duckduckgo.com/?q={searchTerms}&t=brave", + "autocomplete" : "https://ac.duckduckgo.com/ac/?q={searchTerms}&type=list", + "shortcut" : "d" + }, + { + "name" : "Google", + "image" : "https://www.google.com/favicon.ico", + "search" : "https://www.google.com/search?q={searchTerms}", + "autocomplete" : "https://suggestqueries.google.com/complete/search?client=chrome&q={searchTerms}", + "shortcut" : "g" + }, + { + "name" : "Twitter", + "image" : "https://twitter.com/favicon.ico", + "search" : "https://twitter.com/search?q={searchTerms}&source=desktop-search", + "autocomplete" : "https://api.twitter.com/1.1/search/tweets.json?q={searchTerms}", + "shortcut" : "t" + }, + { + "name" : "Wikipedia", + "image" : "https://en.wikipedia.org/favicon.ico", + "search" : "http://en.wikipedia.org/wiki/Special:Search?search={searchTerms}", + "autocomplete": "http://en.wikipedia.org/w/api.php?search={searchTerms}", + "shortcut" : "w" + }, + { + "name" : "Yahoo", + "image" : "https://search.yahoo.com/favicon.ico", + "search" : "https://search.yahoo.com/search?p={searchTerms}&fr=opensearch", + "autocomplete": "https://search.yahoo.com/sugg/os?command={searchTerms}&output=fxjson&fr=opensearch", + "shortcut" : "y" + }, + { + "name" : "Youtube", + "image" : "https://www.youtube.com/favicon.ico", + "search" : "https://www.youtube.com/results?search_type=search_videos&search_query={searchTerms}&search_sort=relevance&search_category=0&page=", + "autocomplete": "http://suggestqueries.google.com/complete/search?output=chrome&client=chrome&hl=it&q={searchTerms}&ds=yt", + "shortcut" : "yt" + } + ] +} + diff --git a/less/about/preferences.less b/less/about/preferences.less index 51eab1616f0..37bbf03b1e7 100644 --- a/less/about/preferences.less +++ b/less/about/preferences.less @@ -434,6 +434,12 @@ table.sortableTable { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACWCAIAAACzY+a1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+1pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxNCAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMTYtMDYtMjFUMTY6MjM6MjEtMDc6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDE2LTA2LTIxVDIzOjIzOjMwLTA3OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDE2LTA2LTIxVDIzOjIzOjMwLTA3OjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4MUMwQzUwMzMwMkIxMUU2QjRFREQ0MEVEQkI1MzUzMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4MUMwQzUwNDMwMkIxMUU2QjRFREQ0MEVEQkI1MzUzMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjgxQzBDNTAxMzAyQjExRTZCNEVERDQwRURCQjUzNTMwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjgxQzBDNTAyMzAyQjExRTZCNEVERDQwRURCQjUzNTMwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+dmddrQAAHspJREFUeNrkXWmwHFd1vud2z/JGb5O1b7ZlLbaMJAtwDBjHOEAlcQXbOGDWpAhJfqQqPwgUCSkoqqiQ5YepVCWpSqqAIrgqkISkgkNIUSRgZONYtjHgVQZJliVLwtqe9PS2eTO9nHTP9no5d52eeY9kkJHeTL+e7vv1Pec73z3nXLjx/sdZ9EJkmRdmf8Dsm9RvLR2DyR8x8zHmf0X7K9Lnx9x1ps6AuZvBxJXlLx8xPwJIX3P6azD/Ye5U+dsT3jjKhij9F2fka9j4saHhx+zwY1L8mAZ+jMSP0fgxGj/ic2QuMVI6+MmAF12OBD/qcTDDj2nih3b4oRQ/1MCPHmTUn385IDpHuvRkEk8M2RQUmizB45XBQucp6W/+rRT8mAg/GQIosCJcDAEK5pXchAqti+gadb8CNZ4fNfho92s6nyJqn194JDKUWDD6J1dyueb42VAYZm5CFdBQrAElkGi6QETJcMusOmq7QFRYNfJ+XZELNMCP2bnAgVJQVjwFZRbDXYALRKGbz0CIoudEAz/sI4Rgg8Bv8BRUJ4QwwE9laVGGtNsXBdVixOIQQsYUViwFVXESi/kndgSofApbjLQPCopyCmpiHPqkoDISpZpVQ6agrDj8Wkdw8W8PiIIyXSttYArkLtCQh5pRUANbhcpxQ2ZwyShRZyyi+EG5QDZsFU3bBSKaUhiKc1g7coqRiuNrnSie6UTxqOsC+47i7fHDAeGHRiEEauGHCTojmXfGLlClgvZFYQzxK9YFFhtCmKswolt2zVwgDlhFM6KgTGp55LeznCoos6cwSFy9a0ZhlATQCD9EE/xQoe8g8X/y2ykAP1YIBWX6IUT+6eMFq2iq422FTi2+qktBbb9ZzypYUFA98o30YPIBUlA2aBWmCBVN2wUaUhgcHAVNjwe61iqzPQU1c4FaKjYbBH79hRB6spUNBc2cy9W2b6YqzEApqNKhFeECC6eghVCYHBKuWQhhkEiBQ1NBVyIFZQOkoJmDuZmKZuUyrVRQpl7QYVIKOmgVTUUXVS6Qwo9pUdDMD7xfCirhVyYL8TYUtJCFXLkLVIaepO+XuECU+nM9+VS6al8gBe1rIZf9nFJQhQuUOQKmTWGQWvI1pqA/zwu52i6wGAqKVhRU30ugLIPNQkVbYSp2gSrMcqloKEUChXGh5MeBUlDD+aec7riM+GE/C/GSECJ/Tm7oAlXswyo9UEpwClLRCqCgqHnFYmBkuYRkCIca5+T9Uphic9HYwCiMHgUVukCU8ja9hSRlLhpDo2cOc4x0xZdDDJqCMrNyCA0Kysxy0YQUVHpOV+X3/h9RUEMXaFCO1AcFVT8TXPSBPQU1U2F+3sohrHJBNXPR1HE8dZFcw/MPuBxCg2hYamf9l0PoLuSqVDQ1hWFqCiP4VbffcgiLXA0jFY0Zu0BmmYuW+0p5XmQR5RDSj9TnxIQvtKgIXNnlEMl3kIVhiMja/2MQ/wfRf5EJiv9WzJpCXSAzozBMZkKTS77/18ohIrg8P/oT41YCKLmwquzUXF52uAssQBZ90gxwwQ/rzcD3Qg/DCFDXgZLDnR6qQ3CBwoVAM1rrGjjBwnJBNaJ4cwoTAbboBX4QjpXdXetqN24c27N5bMe62tqJyvrRcq3sRAhxDojoB+j74VwzmFrwpmcbpy/Xj52bO3Ju/vj5+fMzjUYQRmCXSxzU+PVbDiG0HqqJmxwZV/AVfZdD4PAoaBDiQtMfLfNbt0++fc+6N+9as3PDaKXsyC9wHWPb0+9MzTQOn5l55KcXDr544cjZCGKslh2nA2V/5RAGKox6/mVGBvb8+aP6JtSEgqKufi+M4gVkNPF1QWQPG/6G8cpd+zfcd/Pm/ddMsiJeTS/4wbGprz155tvPnZte8GpVN8JR4QLznShQy1nKFpL09A3Y82ePGrvAgoVstKAw0V/zdf+qWum9t2z58Ju3bV1TYwN4/fTMzBceOv5vPzzTCHCk5KAxfloUVN8FkiMTQ2hgQleAihbZtWYQNpvhXfvXf/xXdu7cNMYG/HriyMXPfP3F58/MlF3erwvsAz+Rc3HNyiGGhp/46yLLuaZW+tS9e+57w1Y2lNcbdq/ds37kRyemWxAOKBdNZZzE5MDVUNH6byqiRUFl61vd083WvZu2Tfz1e/fu3jzGhvV66cz0fxw6WilVWb4oejkoaGZkXEsKKqcwpuUQCkvQxW/Be8fedfe/b9/kqjIb4usfDx69ONeYGGehz7hbFWZF6augWMz8a4+MqzW/is9FE0MsOFWE33teu/H+9+8rl5xh4nd5pv7g4y+PVFv1Q14junVoo2himgyVOb3PuyjwlaDCKClMZD/v2bf+cx8YNn7R68HHXj5+cb4URZkQjRWEXiP06i1StTREei6Q9aOiSWQ/d4WHENFQzS36t1wz+bn37yu5w8av2fS/+vDRUsUB1tVqANBvhsh4qaKlBUrLIfpYHF46F1eo2MtdDrHoBZvHy3/1gX2jIyU29Nf3nj79zKnLlUqJMUi8DSxohs2F1nVDP+UQli4wPbZck05KuGc/KqicwmC8yoB/cu+ea9etGj5+0dc/8L0jyCGWvhNLGp1/hn6MYiyR6+GnvxCICX1KI8uS64YQBvlbuhRUnugKsQv0P3jL1jv3b2TL8Xr62PlHf3KuWiklrxiWbgYw8MNGXaupGSrXgPXaLyFhtlytSN6iqUg/FLR1uoYXXHvVyMfu3FkgKr4fXJ5t1BteGGLJ4bWR0nit7Ahc7D987+icF4xFELYWoICoGIkmQIDeQsxRwREGGdop3npuNXtCd2WqaC0Iw4+8bfvasUr/yE3P1g8+ffrgc2cOn54+P73oNf3I/LkA5aq7brx6zdrRAzvWvmnPxpt2rAPeMUunzs9880enatUSdE1CbvDa1hUQIxQX43iRO6LbR03jpKCgtMVyhx9CMA38FpvBga3jv/4LW/oEb3a+8aX/OvyVg0dePj8XApRKjuNGrq1tDjGcb56+0njqxKWvPXFitOzctG31u2/fed/tu1aNlP/lkWPnZxbHx0ZY++gsQ+95x+guon+FoV8HdwQiFBE1vIQ5fkhPX8REle9wKjo1K3I9P/yd266u9BcFPvniq3/85UM/PnmpOlKujUXj25k3rW/vOrVyNAqlGM4gfPLk5f/50uNfOXj099+x99+ffKVSLXeQyuOXvZ+Yl2IUL7pVSM9FIwpqgV/83Td89vsFVeSiwUKu1FxHXnDH6to3P/rGWtW1xu+fHznyiQceX/DC2kiEBAfOlixiG8R43BEzBBix0fQhZKWyy12eYqIS/JJ8xy2DU2LdTB39wVFTUCTwY73WQaYqtp4QZFmR22iEd792Qz/4/eujx/7gi49ByanVKhChB+m4rqet9DSWVtgAGIMaR4EYm8/YgmYoTPod0jCi34gP5CVM0g9diV8Xv6wvtKjIHQQF7YRbAV414t59wD6QeObouT/68qEIv3LZbeEHWRqS4W6QRLaDXOKX8vj13obsLbcJjt9kkTV13AJcoHT+deLClbY7RERkXnfNxHUbLNeS5uvNj3/50JwfSvFjBH4JHCGX+ZTGDyX4tf8dBk0MPLULNKYwBDR8OBRUO5cJgwDffuO6/Mhqvj7/rRcihlmrlqX4IY0fMiDGOrKvUvzStrn3axihGBlVTfyYJoXJVxUgX1HlEFHEPVbhb9p5lR1+Z6fm/v6hn0T8RY0f08ePKfBDAr/OJ4HXdo0KFVtbCyOrstJNS/L5r9hXCME0Wyv3Vgb8cMfa2o4No3YQfvXho6enF0ulEuMq/JgGftDCL4uVAD+aogCGfnYu5lVsNKOgmdHm1hrwACpyMYJw/9Zx17W5qoVF78EnTlQqZQDSxsm+nTgCIPdMAqGtAFMxxgjFoDUXC6OgmTe5vQvUoqBokE4fH4v7r56we6ae+um5o2dn4zVhSF5QQpcWtFKAPF0EEJsZ6tmQ5aJBW4QLeyjKVFAhfij2qXzAFNSgqU/0p+rw6zdactHvPHumGSLnkB1jadwL+bvOCmpaQTONHySdZBhGwQaikBwgs8Av+owvNwVdOi7ioqtrpavXjFjgFwThUy9dLC0JcpDGD5EMHvI3AswYP1EuE+QMbxiGXhNRukODBgXNHMCXjYLmRiCCcM2q8uSoTXbaq1PzJ8/Plkq8q4IyJX7ZG4E8fmCIH1L49Z7T9he05Jsw0BkZEQXN/BaX6T6mFbn6Oh1Bo5kf4obJil2C08vnZi7Xmy0rKogVUIof8U9QmV1xLhqhw0Fq4H0vsdxvQ2GSvyVtWsKUFAYL3B0iCgq32q4OHn91xvOxJ2YnDSOq8YP0CCciqnRgopWLRpSd5pWBiN80OyiiOJ9NKzmKSrwwMaGsGPw6/h7HbXN8z16eDwGyJhRQgV97xCGfjp0zoTL8klp53pdS+VHQkW9Y4AvmH8opTHIQ3eJVUGaDX/s1VrNMU3v1yiJwDfwIy5gVs4mnEORhVFqyQZoPdw7LCAOhF7/BXUETRtrjZF6uisIwGX3qj4JmmHT04E1ULdd4L881nXaemRw/tMJPSWGycSTq4NcJMKKJGPEt7ipVGNHI88w8zc2/nNCOtiqaQp+Lf6iVLdcI/Ya/RCIg+xACwS3zghpFe4AYQHP8SCqUMKlhgB2LqsKPGk+uzSA1qKVufQFNlxxgI67dCgU2wxC6elbmYjpzk8BPMNeQUF7EFBSYRDNVEJWEm8QgMqoqa0fbM9fQBdpU5CpdYOvI+GHmtg8RJvBDE/ywE7ERdIPEL3X1ALnBAY3nGmnFNQzizhuOK4niycHkKwO/+I5CjDuK2LyAucDziXiQ4SGQVrzs8RNMXB38sJe2k4/iISblsWskR1uYqsQLCCGYmQojSLLCgOG8F9hhWHI5IiZSlBLcZkn5hHQuGujiR7AI0NAyROE1UAPWgz9sLfejLqVor9oPdoMy3da8MQupN0M7U1qruSHLpnhmlOv0HQjDNQ3vDTLGj2mXzHIygsYES6Go2vOb21XkFr1BWefT6bpnB+GGyWoQZoQWpPBDGr+MMCeioJLD0g+jbE6ihjgaz8Yguwgv8FtcT0UTRBmFNTFEFkaXAnPzTTsIN43XeMggbwdJ/BjTDnWkNFbzF5MeN2t3JGfDdsionA/czAX205dQ3hq05ZguLVhCuGX9GOcJcRlZKmLLxAqY/WoJDJiUAZSiSXsFCwUakEBYED8QiKGfzINC4eZ32iraoPbIbb3hOHB6umEH4e5NE6MVN0yKh6mIG9Mxhyl+OSeJQOPHKPyQxk9VxdkFIPQxFDcEQ0Lm1sCvGAqaPZXL+YXLi4sN3wLCbevHNk3W/CBYUpx18FP6kA5+GYmKmkAEfkDhBxR++ayq9HyIUIwIu6CwjROzyniDMmZFQbOniizh+fnGhRmbibhqpLTvmslmM4jHl8h8UeGX45lLsQmBX+5+afzyTzYQKlrex5L2LAxaKBIzhxeRi4ZaHl4lHjk87kzyyoV5O1v6S6/ZRAVdmCOIVMIa5vADEAIjDjHS+JGBPw2qlj8K4+a4+SO5etCHtjsEsEaIh8/M2EF4+97NG8arvh+m4jMGxPo5TRdRPdyYtYmJKsM8pPQJEfXwy1oEaNMbxGzozJd9d4hu8NPKLQF45uS0ZVyxdvQtr9lYb3qy6Z6nizn8kCXmH0rxY2L8sG/8MI3f0pwOOyEjERf2U85iSmEEdrpc4s+eumLHaKLXh9+6u8p5GCAR1grpfho/ANowUm1V0QC/9DCAKsZU8OEw6Re5HD/dXLRCNriCuDv2K1P1F09fsYPw5us33Hlgy/yiR+BH0/30cwpAT6yc7wNh5J+5X0gE6gn89EPq9sG5VZ34AsMwEVT0WQ5R3AZlESmd98KDhy8w29fH771pdbXkBaEUv6zk3aqYJ8t3s7lokLljFOCHQOEHdJEp6Y+AAhtTNQAxipgJ7XUpqEqk0KOg5KvswkMvnAsCS737+m2rP/HOffW6hyrlOk1apeXXUpJDzEmhdqq7EC+o3cnn3sQqHC+SgqIhBaX8bqXkPH965jlbUhO9fvdX93zwtutmZxsCugjZvmiQW+nvRQUowq+3ZJ9DOj3/lqYgvScG6uqxBH6d8ztr3vJbhW1wxbQoKJNtUBZf5lzdHyvxO/bZ1moDvHXf5pM/m/nRyUutvQqACteWHHCmHCJsVRrHG1YkKhSBeMYpPSWXN97pRQ1Uoj/JB0E02QXqPLAIwg/ZUBiDEIIpXWA2VgU4PTX/rlu2WndMcF3+y6/bNjffeOrohYifug6nDCNkMm2i7683Ao7s1167dWqmseAFHKj5xzTxQ8SeRCBNpGDpdU2le8KURpGAcIVsUAYQkZoL041N4+XX71xjbU4j2N5+YOuuDWNHXrl8+tJCiOCk0xR7Xx7vLhOEC3Wfh+xNO9f+xW/e/NF37nvupQvPnLgcWXXi4UdSzxTgJxRMMI8fKvXLHH7R310IzStyC5h/gt9qP/onzs6++41bq2X71iXR64Ztq9916/arV9fmF5pTVxqz9eaiFzRb2wHVvdBrhn4QVh3YsXb07puv/vR9B/7wXTft2BwXOK6qOA8eOtFrFYVK/FCJH5rjByL8koEl7P70QwNUYYjLzu+xSqEehtMzi5+8+4aP3XMjK+IVRcNHfzb9/IlLpy/On5ttNEOcqLrrV1XWX1XbvWX8uo0T1UrqWfG84J2f+fYPT12O3k9GHjr4ZXVY1MGPaaYstfFLntIdDn4SCkoLE8BqtdIXvnv8nlu27tg03j+EwGH31tXRH83jSyXn3b+4/YkHLrKKK8CPUYkwJH6SwYRUnrk+fgKNdID4me7RGT2YruNMLXif/drziMiW43X3G6+9es0qr6Ob6+YoU/ghfbMt14xESAZEPJvRSjOr9gOhoH3g16t3H62V//PZsw9856VlgXDN5MhdN2+rL4p1c8y31QCZ5kwHCTn8kB4Z6BWKpOc9L5rCIOUCNfDLvxsRCQ4j1dKffv3wD49cXBYU33fHjrGKG2akIsGCsUE5BCU6CPUfbOcwi3afBW6jojHdgw1MINlGF5hb4gtB+JEv/uDU+bnhQ7jn2jW337ixvhhQj6Aw7FYNBAjmA5CWKdmRmIz3+TJQUKa9zXjL2Y9U3CNT9d/+uyemZhaHj+Jv3LGDI4pT7qmRRwlxA4EETSZqtHPQxR1/6U0OhkBBdfdY7XpwDqOryj8+eeVDf/P4hSvDRvGOA1tes22y4bWycvK5aJ3FdLnFoivu1fglHwdxvisvUoXpm8LQd9hqDTq+qvz4san3/+WjJ16dHSaElbL7ntu2NxsBtUQBBhWBqfaK9JqwmO3IpgZfHhVNgV/eWMWN8SZGy8+duvKe+x95+NlXh4nivbdu3zJZ9YMwNe4G+C0tE6bJHtALxZB7Vyq5OWtu/9CyqGiKcwma+rgl59KC940nTqEfvn7nGsfhQ4Awim1OnJt98sjFTq/wbnKbFn6QKZFLLumSNFyCH5BwJiBkTDumYSoKo8FmhTs5CK8EW3ql68bVEw89d/bQC+euXVfbtn500BB+69DLX33k+Oyi33liQGMdGTF/JKrw69pm8pTCng2w61PfLcqEGlJQ0lHL6qp6zfDaGwEtLDRLjN3z+o2/d+fufTvWDwK8x54987ffeOG/n/kZlJ1KucTabb4ZUzQVad9vWuZGjfknHhmQDE4LwmVS0ey3iceQhfEoRkF3BOSoE75t7/oPvGXnrXs3VasF7M51abr+8NOn/+ngse8fPtcIcaRWdrjDeD/4MWKhg8YvPzIgfbgBdn3yO5QnWhYKg2Z7rLbreuPqH5yfX3D9xvWbxt9605bb92/au33NutVmO3U1Gt6p83M/Pnr+4WfPPvbiuZMX55kDI1WX89bOdzL8cgORWyZE2UIVhR/L5XuIGU0CwiFTUKbcJl5zj2Nszcgw9P3F+kKz4UdTZtPEyK7N4zdsmdi9dXLLVbWJierkqkq8O1Oror8RhPVmcGW+OTuzeH5m8fjZmRNnZ46dmXllan56wQs5r5bdVke+9tYHkEx7WR78mGwRIwuhHgVFBQWVLATquEBigyuxetA+oiWgRDiGfjMMgigA8Dw/8ONOJpV40wheKTsjDkRGNooMFsMwCvOiA+P961plChzAdZ3oT0xYepscdNae+8cPROOZTonSxy9FbVxzFRQtBVUJfkyMn6Ye2x7yCAFejcApOX7cmzRsra6F8dA3Q2y0kkuhsxUF4xU3OrYEvSTE9idJApiu2lfWAwHohWSMwo/S2zTww8xGsBblEMVTUNEJNfdYhWjOVdDnGHjgtPcOYYlFml6UBthbbu/134PEki0C1TFYTGGEfAI05l/GlknaaRChhTtEFVQ1/4xcIE34urQ98noA3c0+2okN0FNJELpDi0BLlyyLn7I1ryCSo18A1JOdvxKigoeYQu7yqaBMN4Qw2+O4e3DEJOOtk72W+8v3LRHnEpK5aJrTAqXSCCIAEx8sbaZBZ6h2NdIBqmiy3SGkFJTpzT8mwK97d/EmZsCzTfMkFBF08ENaSjHCL+uLQBofZ5eCE1eFXE1D9FU0VLZwUHMiVCp8kj1WibLTiGuWmcOzn4vw0+NZLOFjMzREVA4BILkLCX4gx4+1tt2yqsjVzUVDoQqT/AnF01Be16+3R2fEcACcxFIB1WObwg9FxUIZ/KSWgZrbyf9A5VzE+EHXkBpRUEMXyNQqmh0FzX6JYoOyuPNuu20rOWRUzZ+QwgCZoSvMBQUmGRmQBmzSSlLItpTVUmEMKSjSIYQdhclcEop2ZxE2vY0T/XmZ2nQJRHusZk+4pNTk0kGF809CDiT4AV1aTFWcc52mPmYUVMV4LPGTtB3RwK+HQavhJzAZ8xdQUKCWZ7v4Id3uUoqfeJsn2nwl8UtyNrn8YENB0UrFlrtWZIJiONTrOJZO44hQBBD6CtIVGeIHYvyYCD/Uxg8liRfFUlA9WQ4FoZ7UvevyLHraxii2gw3N1WbRLlzAlJ17iSdRhZ/kRRFedwAU1GwhV4+C5rmCRtNGmVlG4A6GwJZaRwgoqHT+kY8dCEcGpCEu0C4DFeSGF63CsCJdoIyCartAcZZlnC6+tLsANQzCAkFIkSpM2k+RZwDpEhsohg+E98L7rMhVU1DrhcAcalL8mBl+mHaNNH70mkiqHXRW30TGpE823WNfiB8utbtFnW23iiiHsEukMKMw5DlRuFTAmIqyAeNONkQGmkuIrkickg/C2yOiEQo/piCSvN/5xyQU1AQ/tFLRZLuXivHLUtBWbBjXcXNqFy4xfpjpaYokfuIwSNajPYuf0DeBq2SMCp6FehTUunmNnMJoUlAm26AsQQyclpGkimBS+DFq/qFIPhE83LIdSdT4YXbVXruchZnkoknCB8uFJDWFkZ6TKVUY4PFmCdlt6ch9C1EaBCCI2QlmemdSoo582qQuzNV5tM0pTBELgbIpJu3br9sxlY7iY3MK8TbYOa0kZUJlTdq7awuiikC9+5W786XJ79q7wEHjp6/CaFJQDfySwT9GFhUpi6CPn3z+KaNsDfyyGqkNhWFK/Fh/IQRT9502bLeiWQ4RoZhWwAWdoCj85NZVSEE1xKwMfphkpCj0Hyin+yoKigqHakNBkaagmtvEa29QBox390gnl3SF+OnpGyJFHMU6dT5WRS6kMKrv1stFE9EIGfBoQkH1ZD/xG6oNytquUY0fU+EneW4guxAvMKF0J2JeJIUR6KWmFFQnslS4QNQ3ocoNytrVjRxkjzeIHzpQRL06zlEYYmJy2y39XFAzCsPY8lFQVC4k6WxQ1s2VihUcMnsXxIUGoJD4sx1KUD19MdFTuj0LDSmoum54SBQUTVU0VFTEI1IPQPo4ztNZa+nWvyR+koEC1fPNtFrqcV0ih0y7nGVlUFCdhVyd+cdyLSs6nV5AOjIgNk5LogCqx0cQOzEUtEswrsgtohxCLwzXUtFkgqQWBSW+hC544FI+BQq2BRIzR5NUyZ242hRm8OUQwiMN983Qz0UTPumq3Oh2GUZcFKVdkSsU5chrhjwKohvnhVNQ1lc5ROH4oaKpj3SPVYUVAS4QNwUPItHhQhc/ybBzK/z6ozDIFOUQiunSp4qmsBkareITI9PO9k+t3ArMH0isQuYhQNmjjjJD2k85hBWFYSa5aDgQFU1GqpTnXyI44ug2t7WvlMKAYA8QJllV5XQuGkooWd8VuUoKygpQ0frCT10elKvIBTDGLzv5QCE5C+w8b61zoswR6VeK6FNQbbdqpaIVTkGZ1sVkssKV+GlEtKgQCVsOOWwsAHfI1Fh1Oj1jQ8hFQ7OFJFRQULPdigzbdWTqX0CzkpRuY6lK92qvUnjOyDU3x5UCpZF0pnp/6fQqgVx3IV4xrVH9dvG7FanIAXQzuYVbu6IigmTSxKLOZiTQKn2dR5x22LW3Oc25cGEGw2a7RwcQTbzbLSVANf+QepqApVdO01MMaPEic7OSTEnUnn/MerciVbuVvGOLbytcSoCRuUDaziO9Dze2Tuu1wLuCuDC36P2vAAMAt4+866Gti10AAAAASUVORK5CYII=') 0 0 / contain no-repeat; } +#searchSelectIcon { + width: 16px; + height: 16px; + color: @braveOrange; +} + .prefTabContainer .switchControl { display: inline-block; vertical-align: middle; diff --git a/less/sortableTable.less b/less/sortableTable.less index 5ee95f1388c..546545e4772 100644 --- a/less/sortableTable.less +++ b/less/sortableTable.less @@ -23,10 +23,6 @@ table.sortableTable { font-weight: 300; padding: 8px; box-sizing: border-box; - - &:hover { - text-decoration: underline; - } } td { @@ -73,3 +69,7 @@ table.sortableTable { } } } +tr.rowHover:hover { + background: #ffcc99; + cursor: pointer; +} diff --git a/test/components/navigationBarTest.js b/test/components/navigationBarTest.js index 8a221b0f191..6d2c828d683 100644 --- a/test/components/navigationBarTest.js +++ b/test/components/navigationBarTest.js @@ -6,6 +6,7 @@ const {urlInput, activeWebview, activeTabFavicon, activeTab, navigatorLoadTime, const urlParse = require('url').parse const assert = require('assert') const settings = require('../../js/constants/settings') +const searchProviders = require('../../js/data/searchProviders') describe('navigationBar', function () { function * setup (client) { @@ -459,6 +460,49 @@ describe('navigationBar', function () { }) }) + describe('search engine go key', function () { + Brave.beforeAll(this) + const entries = searchProviders.providers + + before(function * () { + yield setup(this.app.client) + yield this.app.client.waitForExist(urlInput) + yield this.app.client.waitForElementFocus(urlInput) + yield this.app.client.waitUntil(function () { + return this.getValue(urlInput).then((val) => val === '') + }) + }) + + entries.forEach((entry) => { + describe('each entry', function () { + before(function * () { + // escape + yield this.app.client.ipcSend('shortcut-active-frame-stop') + // type go key + yield this.app.client.keys(entry.shortcut + ' ') + }) + + it('sets the value', function * () { + yield this.app.client.waitUntil(function () { + return this.getValue(urlInput).then((val) => val === entry.shortcut) + }) + }) + + it('has focus', function * () { + yield this.app.client.waitForElementFocus(urlInput) + }) + + it('has the icon', function * () { + yield this.app.client + .waitForExist(urlbarIcon) + .getCssProperty(urlbarIcon, 'background-image').then((backgroundImage) => + backgroundImage.value === `url("${entry.image}")` + ) + }) + }) + }) + }) + // need to move urlbar state to frame before enabling these describe('change tabs', function () { Brave.beforeAll(this)