diff --git a/docs/state.md b/docs/state.md
index 3d9d7e4f87d..7a4e1e93459 100644
--- a/docs/state.md
+++ b/docs/state.md
@@ -74,7 +74,6 @@ WindowStore
activeMixedContent: boolean, // has active mixed content
passiveMixedContent: boolean, // has passive mixed content
},
- parentWindowKey: number, // the key of the window this frame was opened from
parentFrameKey: number, // the key of the frame this frame was opened from
contextMenuDetail: {...},
modalPromptDetail: {...},
diff --git a/js/components/frame.js b/js/components/frame.js
index 35eedcfe9e1..f25a7191fdb 100644
--- a/js/components/frame.js
+++ b/js/components/frame.js
@@ -27,19 +27,22 @@ class Frame extends ImmutableComponent {
}
createWebview () {
- while (this.webviewContainer.firstChild) {
- this.webviewContainer.removeChild(this.webviewContainer.firstChild)
- }
// Create the webview dynamically because React doesn't whitelist all
// of the attributes we need.
- this.webview = document.createElement('webview')
+ this.webview = this.webview || document.createElement('webview')
this.webview.setAttribute('preload', 'content/webviewPreload.js')
if (this.props.frame.get('isPrivate')) {
this.webview.setAttribute('partition', 'private-1')
}
+ if (this.props.frame.get('guestInstanceId')) {
+ this.webview.setAttribute('data-guest-instance-id', this.props.frame.get('guestInstanceId'))
+ }
this.webview.setAttribute('src', this.props.frame.get('src'))
- this.webviewContainer.appendChild(this.webview)
- this.addEventListeners()
+
+ if (!this.webviewContainer.firstChild) {
+ this.webviewContainer.appendChild(this.webview)
+ this.addEventListeners()
+ }
}
componentDidMount () {
@@ -51,8 +54,7 @@ class Frame extends ImmutableComponent {
if (didSrcChange) {
this.createWebview()
}
- if ((this.props.isActive && !prevProps.isActive && !this.props.frame.getIn(['navbar', 'urlbar', 'focused'])) ||
- (this.props.isActive && didSrcChange)) {
+ if (this.props.isActive && !prevProps.isActive) {
this.webview.focus()
}
const activeShortcut = this.props.frame.get('activeShortcut')
@@ -104,33 +106,35 @@ class Frame extends ImmutableComponent {
}
addEventListeners () {
- // @see new-window event
this.webview.addEventListener('focus', this.onFocus.bind(this))
- this.webview.addEventListener('new-window', (e) => {
- // TODO handle _top, _parent and named frames
- // also popup blocking and security restrictions!!
+ // @see new-window event
+ this.webview.addEventListener('new-window', (e, url, frameName, disposition, options) => {
+ e.preventDefault()
+
+ let guestInstanceId = e.options.webPreferences && e.options.webPreferences.guestInstanceId
+ let windowOptions = e.options.windowOptions || {}
+ windowOptions.parentWindowKey = remote.getCurrentWindow().id
+ windowOptions.disposition = e.disposition
- // @see dom open
- // @see browsing context name or keyword
- if (e.frameName.toLowerCase() === '_self') {
- WindowActions.loadUrl(this.props.frame, e.url)
- } else if (e.disposition === 'new-window' || e.frameName.toLowerCase() === '_blank') {
+ if (e.disposition === 'new-window' || e.disposition === 'new-popup') {
AppActions.newWindow({
location: e.url,
parentFrameKey: this.props.frame.get('key'),
- parentWindowKey: remote.getCurrentWindow().id
- }, e.options)
+ guestInstanceId
+ }, windowOptions)
} else {
WindowActions.newFrame({
location: e.url,
parentFrameKey: this.props.frame.get('key'),
- parentWindowKey: remote.getCurrentWindow().id,
- openInForeground: e.disposition !== 'background-tab'
+ openInForeground: e.disposition !== 'background-tab',
+ guestInstanceId
})
}
})
+ this.webview.addEventListener('destroyed', (e) => {
+ WindowActions.closeFrame(this.props.frames, this.props.frame)
+ })
this.webview.addEventListener('close', () => {
- // security restrictions here?
AppActions.closeWindow(remote.getCurrentWindow().id)
})
this.webview.addEventListener('enter-html-full-screen', () => {
@@ -162,6 +166,11 @@ class Frame extends ImmutableComponent {
this.webview.canGoBack(),
this.webview.canGoForward())
})
+ this.webview.addEventListener('did-navigate', (e) => {
+ if (this.props.isActive && this.webview.getURL() !== Config.defaultUrl) {
+ this.webview.focus()
+ }
+ })
this.webview.addEventListener('did-start-loading', () => {
WindowActions.onWebviewLoadStart(
this.props.frame)
diff --git a/js/components/main.js b/js/components/main.js
index dfc516c1dae..e506aa8cb13 100644
--- a/js/components/main.js
+++ b/js/components/main.js
@@ -30,12 +30,6 @@ const FrameStateUtil = require('../state/frameStateUtil')
class Main extends ImmutableComponent {
componentDidMount () {
- if (this.props.windowState.get('frames').isEmpty()) {
- WindowActions.newFrame({
- location: Config.defaultUrl
- })
- }
-
ipc.on(messages.STOP_LOAD, () => {
electron.remote.getCurrentWebContents().send(messages.SHORTCUT_ACTIVE_FRAME_STOP)
})
@@ -173,6 +167,7 @@ class Main extends ImmutableComponent {
sortedFrames.map(frame =>
{
- WindowActions.newFrame(frame)
- })
+ if (this.props.frames.length === 0) {
+ WindowActions.newFrame({
+ location: Config.defaultUrl
+ })
+ } else {
+ WindowStore.suspend()
+ this.props.frames.forEach(frame => {
+ WindowActions.newFrame(frame)
+ })
+ WindowStore.resume()
+ }
}
render () {
diff --git a/js/state/frameStateUtil.js b/js/state/frameStateUtil.js
index f465449046d..6be1437db93 100644
--- a/js/state/frameStateUtil.js
+++ b/js/state/frameStateUtil.js
@@ -135,7 +135,7 @@ export function addFrame (frames, frameOpts, newKey, activeFrameKey) {
isPinned: frameOpts.isPinned,
key: newKey,
parentFrameKey: frameOpts.parentFrameKey,
- parentWindowKey: frameOpts.parentWindowKey,
+ guestInstanceId: frameOpts.guestInstanceId,
navbar: {
searchSuggestions: true,
focused: true,
diff --git a/js/stores/appStore.js b/js/stores/appStore.js
index 12e89285734..3e92259d5ae 100644
--- a/js/stores/appStore.js
+++ b/js/stores/appStore.js
@@ -31,10 +31,8 @@ function navbarHeight () {
return 75
}
-const createWindow = (browserOpts, defaults, parentWindowKey) => {
- browserOpts = browserOpts || {}
- // clean up properties
- delete browserOpts.webPreferences
+const createWindow = (browserOpts, defaults) => {
+ let parentWindowKey = browserOpts.parentWindowKey
browserOpts.width = firstDefinedValue(browserOpts.width, browserOpts.innerWidth, defaults.width)
// height and innerHeight are the frame webview size
@@ -156,6 +154,7 @@ function windowDefaults () {
setDefaultWindowSize()
return {
+ show: false,
width: appState.get('defaultWindowWidth'),
height: appState.get('defaultWindowHeight'),
minWidth: 500,
@@ -191,9 +190,10 @@ const handleAppAction = (action) => {
appStore.emitChange()
break
case AppConstants.APP_NEW_WINDOW:
- const frameOpts = action.frameOpts && action.frameOpts.toJS() || undefined
- const browserOpts = action.browserOpts && action.browserOpts.toJS() || undefined
- let mainWindow = createWindow(browserOpts, windowDefaults(), frameOpts && frameOpts.parentWindowKey)
+ const frameOpts = action.frameOpts && action.frameOpts.toJS()
+ const browserOpts = (action.browserOpts && action.browserOpts.toJS()) || {}
+
+ let mainWindow = createWindow(browserOpts, windowDefaults())
if (action.restoredState) {
mainWindow.webContents.once('dom-ready', () => {
mainWindow.webContents.send('restore-state', action.restoredState)
@@ -226,6 +226,8 @@ const handleAppAction = (action) => {
mainWindow.loadURL('file://' + __dirname + '/../../app/index.html?' + queryString)
}
appStore.emitChange()
+
+ mainWindow.show()
break
case AppConstants.APP_CLOSE_WINDOW:
let appWindow = BrowserWindow.fromId(action.appWindowId)
diff --git a/js/stores/windowStore.js b/js/stores/windowStore.js
index 2addd55894c..5d91f00d0c7 100644
--- a/js/stores/windowStore.js
+++ b/js/stores/windowStore.js
@@ -58,6 +58,7 @@ let currentKey = 0
const incrementNextKey = () => ++currentKey
class WindowStore extends EventEmitter {
+
getState () {
return windowState
}
@@ -67,7 +68,11 @@ class WindowStore extends EventEmitter {
}
emitChange () {
- this.emit(CHANGE_EVENT)
+ if (!this.suspended) {
+ this.emit(CHANGE_EVENT)
+ } else {
+ this.emitOnResume = true
+ }
}
addChangeListener (callback) {
@@ -77,6 +82,26 @@ class WindowStore extends EventEmitter {
removeChangeListener (callback) {
this.removeListener(CHANGE_EVENT, callback)
}
+
+ /**
+ * Temporarily suspend the emitting of change events for this store
+ * You can use this when you have multiple actions that can/should be accomplished in a single render
+ */
+ suspend () {
+ this.suspended = true
+ }
+
+ /**
+ * Resume the emitting of change events
+ * A change event will be emitted if any updates were made while the store was suspended
+ */
+ resume () {
+ this.suspended = false
+ if (this.emitOnResume) {
+ this.emitOnResume = false
+ this.emitChange()
+ }
+ }
}
const windowStore = new WindowStore()
diff --git a/package.json b/package.json
index 290081c8f60..5e6b041f2c0 100644
--- a/package.json
+++ b/package.json
@@ -4,8 +4,8 @@
"description": "Brave laptop and desktop browser",
"main": "./app/index.js",
"scripts": {
- "start": "node ./tools/start.js --debug=5858",
- "start-brk": "node ./tools/start.js --debug-brk=5858",
+ "start": "node ./tools/start.js --debug=5858 -enable-logging --v=0 --enable-dcheck",
+ "start-brk": "node ./tools/start.js --debug-brk=5858 -enable-logging --v=0 --enable-dcheck",
"watch-all": "npm run watch & npm run watch-test",
"watch-test": "NODE_ENV=test webpack --watch",
"watch": "webpack-dev-server",
@@ -38,6 +38,10 @@
{
"name": "Aubrey Keus",
"email": "aubrey@brave.com"
+ },
+ {
+ "name": "Brian Johnson",
+ "email": "bjohnson@brave.com"
}
],
"license": "MPL-2.0",
@@ -89,7 +93,7 @@
"node-static": "^0.7.7",
"node-uuid": "^1.4.7",
"pre-commit": "^1.1.2",
- "spectron": "^0.35.3",
+ "spectron": "^0.36.0",
"standard": "^5.4.1",
"style-loader": "^0.13.0",
"webdriverio": "^3.3.0",
diff --git a/test/fixtures/click_with_target.html b/test/fixtures/click_with_target.html
new file mode 100644
index 00000000000..b8588abb793
--- /dev/null
+++ b/test/fixtures/click_with_target.html
@@ -0,0 +1,13 @@
+
+
+
+ click.with.target
+
+
+ none
+ name
+ name2
+ self
+
+
+
diff --git a/test/fixtures/iframe_target_parent.html b/test/fixtures/iframe_target_parent.html
new file mode 100644
index 00000000000..3ef879ff2bf
--- /dev/null
+++ b/test/fixtures/iframe_target_parent.html
@@ -0,0 +1,10 @@
+
+
+
+ iframe.target.parent
+
+
+ parent
+
+
+
diff --git a/test/fixtures/iframe_target_top.html b/test/fixtures/iframe_target_top.html
new file mode 100644
index 00000000000..9c81da90c0e
--- /dev/null
+++ b/test/fixtures/iframe_target_top.html
@@ -0,0 +1,9 @@
+
+
+
+ iframe.target.top
+
+
+ top
+
+
diff --git a/test/lib/brave.js b/test/lib/brave.js
index bece27e2862..c1d9dd6c076 100644
--- a/test/lib/brave.js
+++ b/test/lib/brave.js
@@ -8,6 +8,19 @@ chai.use(chaiAsPromised)
const Server = require('./server')
+var promiseMapSeries = function (array, iterator) {
+ var length = array.length
+ var current = Promise.resolve()
+ var results = new Array(length)
+
+ for (var i = 0; i < length; ++i) {
+ current = results[i] = current.then(function (i) {
+ return iterator(array[i])
+ }.bind(undefined, i))
+ }
+ return Promise.all(results)
+}
+
var exports = {
keys: {
@@ -127,6 +140,38 @@ var exports = {
return require('electron').remote.getCurrentWindow().setSize(width, height)
}, width, height).then((response) => response.value)
})
+
+ this.app.client.addCommand('windowParentByUrl', function (url, childSelector = 'webview') {
+ var context = this
+ return this.windowHandles().then(response => response.value).then(function (handles) {
+ return promiseMapSeries(handles, function (handle) {
+ return context.window(handle).getAttribute(childSelector, 'src').catch(() => '')
+ })
+ }).then(function (response) {
+ let index = response.indexOf(url)
+ if (index !== -1) {
+ return context.windowByIndex(index)
+ } else {
+ return undefined
+ }
+ })
+ })
+
+ this.app.client.addCommand('windowByUrl', function (url) {
+ var context = this
+ return this.windowHandles().then(response => response.value).then(function (handles) {
+ return promiseMapSeries(handles, function (handle) {
+ return context.window(handle).getUrl()
+ })
+ }).then(function (response) {
+ let index = response.indexOf(url)
+ if (index !== -1) {
+ return context.windowByIndex(index)
+ } else {
+ return undefined
+ }
+ })
+ })
},
startApp: function () {
diff --git a/test/lib/server.js b/test/lib/server.js
index a62f3d60221..04255ba4cc3 100644
--- a/test/lib/server.js
+++ b/test/lib/server.js
@@ -15,6 +15,14 @@ Server.prototype = {
return 'http://localhost:' + this.port + '/' + path
},
+ urlWithIpAddress: function (path) {
+ return 'http://127.0.0.1:' + this.port + '/' + path
+ },
+
+ urlOrigin: function () {
+ return 'http://localhost:' + this.port
+ },
+
/**
* Sends signal to stop child process and stop server.
*/
diff --git a/test/navigationBarTest.js b/test/navigationBarTest.js
index 6e27ac87549..160c1ff3568 100644
--- a/test/navigationBarTest.js
+++ b/test/navigationBarTest.js
@@ -72,8 +72,9 @@ describe('urlbar', function () {
yield navigate(this.app.client, page1Url)
return yield this.app.client.waitForValue(urlInput)
// Should have title mode
- .getValue(urlInput)
- .should.eventually.be.equal('Page 1')
+ .waitUntil(function () {
+ return this.getValue(urlInput).then(val => val === 'Page 1')
+ })
// Check for exiting title mode
.isExisting(navigatorLoadTime).then(isExisting =>
assert(!isExisting))
@@ -87,24 +88,27 @@ describe('urlbar', function () {
const page1Url = Brave.server.url('page1.html')
yield navigate(this.app.client, page1Url)
return yield this.app.client.ipcSend('shortcut-focus-url', false)
- .getValue(urlInput)
- .should.eventually.be.equal(page1Url)
+ .waitUntil(function () {
+ return this.getValue(urlInput).then(val => val === page1Url)
+ })
})
it('exits title mode when focused for search hmode', function *() {
const page1Url = Brave.server.url('page1.html')
yield navigate(this.app.client, page1Url)
return yield this.app.client.ipcSend('shortcut-focus-url', true)
- .getValue(urlInput)
- .should.eventually.be.equal(page1Url)
+ .waitUntil(function () {
+ return this.getValue(urlInput).then(val => val === page1Url)
+ })
})
it('loads a page with no title', function *() {
- const page1Url = Brave.server.url('page_no_title.html')
- yield navigate(this.app.client, page1Url)
- return yield this.app.client.waitForValue(urlInput)
- .getValue(urlInput)
- .should.eventually.be.equal(page1Url)
+ const pageNoTitleUrl = Brave.server.url('page_no_title.html')
+ yield navigate(this.app.client, pageNoTitleUrl)
+ return yield this.app.client
+ .waitUntil(function () {
+ return this.getValue(urlInput).then(val => val === pageNoTitleUrl)
+ })
})
})
@@ -123,6 +127,7 @@ describe('urlbar', function () {
backgroundImage.value === `url("${Brave.server.url('favicon.ico')}")`
))
})
+
it('Parses favicon when one is present', function *() {
const pageWithFavicon = Brave.server.url('favicon.html')
yield navigate(this.app.client, pageWithFavicon)
@@ -262,6 +267,10 @@ describe('urlbar', function () {
describe('non-url input value', function () {
})
+
+ describe('page with focused form input', function () {
+ it('loads the url without submitting the form')
+ })
})
describe('typing', function () {
@@ -296,6 +305,7 @@ describe('urlbar', function () {
it('selects the text', function *() {
yield selectsText(this.app.client, 'a')
})
+
it('has the file icon', function *() {
yield this.app.client.waitForExist('.urlbarIcon.fa-file-o')
})
@@ -341,7 +351,14 @@ describe('urlbar', function () {
yield setup(this.app.client)
// tab with typing
yield newFrame(this.app.client, 2)
- yield this.app.client.keys('a').waitForValue(urlInput, 'a')
+ yield defaultUrl(this.app.client)
+ yield hasFocus(this.app.client)
+ yield selectsText(this.app.client)
+ yield this.app.client
+ .keys('a')
+ .waitUntil(function () {
+ return this.getValue(urlInput).then(val => val === 'a')
+ })
// tab with loaded url
yield newFrame(this.app.client, 3)
yield navigate(this.app.client, Brave.server.url('page1.html'))
@@ -352,13 +369,10 @@ describe('urlbar', function () {
yield this.app.client
.ipcSend('shortcut-set-active-frame-by-index', 0)
.waitForVisible('div[id="navigator"][data-frame-key="1"] ' + urlInput)
- // wait for selection??
})
it('preserves focused state', function *() {
yield defaultUrl(this.app.client)
- yield hasFocus(this.app.client)
- yield selectsText(this.app.client)
})
})
@@ -370,7 +384,10 @@ describe('urlbar', function () {
})
it('preserves typing state', function *() {
- yield this.app.client.getValue(urlInput).should.eventually.be.equal('a')
+ yield this.app.client
+ .waitUntil(function () {
+ return this.getValue(urlInput).then(val => val === 'a')
+ })
yield selectsText(this.app.client, '')
})
})
diff --git a/test/windowTest.js b/test/windowTest.js
index f84c3b1665b..764d56a05ce 100644
--- a/test/windowTest.js
+++ b/test/windowTest.js
@@ -122,12 +122,12 @@ describe('application window', function () {
})
})
- describe('onClick windw.open', function () {
+ describe('windw.open with click', function () {
describe('with features', function () {
Brave.beforeAll(this)
before(function *() {
- var page1 = Brave.server.url('page1.html')
+ this.page1 = Brave.server.url('page1.html')
yield this.app.client
.waitUntilWindowLoaded()
@@ -136,48 +136,41 @@ describe('application window', function () {
.url(Brave.server.url('window_open.html'))
.execute(function (page1) {
global.triggerFunction = function () {
- return window.open(page1, '_blank', 'height=300, width=500, top=100, left=0')
+ return window.open(page1, 'page1', 'height=300, width=500, top=100, left=0')
}
- }, page1)
+ }, this.page1)
.click('#trigger')
})
it('opens in a new window', function *() {
- yield this.app.client.waitUntil(function () {
- return this.getWindowCount().then((count) => {
- return count === 4 // two windows with two views each
+ yield this.app.client
+ .waitUntil(function () {
+ return this.getWindowCount().then((count) => {
+ return count === 4 // two windows with two views each
+ })
})
- })
- .windowByIndex(2) // window 2
- .waitUntilWindowLoaded()
- .waitForVisible(Selectors.activeWebview)
})
it('set the url', function *() {
- var page1 = Brave.server.url('page1.html')
-
yield this.app.client
- .windowByIndex(3) // inner webview of window 2
- .waitUntil(function () {
- return this.getUrl().then(url => url === page1)
- })
+ .windowByUrl(this.page1)
})
it('sets the width and height', function *() {
yield this.app.client
- .windowByIndex(2)
+ .windowParentByUrl(this.page1)
.getWindowHeight().should.eventually.be.equal(375) // height plus navbar
yield this.app.client
- .windowByIndex(2)
+ .windowParentByUrl(this.page1)
.getWindowWidth().should.eventually.be.equal(500)
})
it('sets the window position', function *() {
yield this.app.client
- .windowByIndex(2)
+ .windowParentByUrl(this.page1)
.getWindowBounds().then((res) => res.x).should.eventually.be.equal(0)
yield this.app.client
- .windowByIndex(2)
+ .windowParentByUrl(this.page1)
.getWindowBounds().then((res) => res.y).should.eventually.be.equal(100)
})
})
@@ -186,7 +179,7 @@ describe('application window', function () {
Brave.beforeAll(this)
before(function *() {
- var page1 = Brave.server.url('page1.html')
+ this.page1 = Brave.server.url('page1.html')
yield this.app.client
.waitForVisible(Selectors.activeWebview)
@@ -196,39 +189,42 @@ describe('application window', function () {
global.triggerFunction = function () {
return window.open(page1, '', 'height=100, width=100')
}
- }, page1)
+ }, this.page1)
.click('#trigger')
})
it('opens in a new window', function *() {
- yield this.app.client.waitUntil(function () {
- return this.getWindowCount().then((count) => {
- return count === 4 // two windows with two views each
+ yield this.app.client
+ .waitUntil(function () {
+ return this.getWindowCount().then((count) => {
+ return count === 4 // two windows with two views each
+ })
})
- })
- .windowByIndex(2) // window 2
- .waitUntilWindowLoaded()
- .waitForVisible(Selectors.activeWebview)
+ yield this.app.client
+ .windowParentByUrl(this.page1)
+ .waitUntilWindowLoaded()
+ .waitForVisible(Selectors.activeWebview)
})
it('has a min width of 500 and height of 300', function *() {
yield this.app.client
- .windowByIndex(2) // window 2
+ .windowParentByUrl(this.page1)
.getWindowHeight().should.eventually.equal(300)
yield this.app.client
- .windowByIndex(2) // window 2
+ .windowParentByUrl(this.page1)
.getWindowWidth().should.eventually.equal(500)
})
})
// requires https://github.com/brave/browser-electron/issues/98
- describe.skip('without features', function () {
+ describe('without features', function () {
Brave.beforeAll(this)
before(function *() {
var page1 = Brave.server.url('page1.html')
yield this.app.client
+ .windowByIndex(0)
.waitUntilWindowLoaded()
.waitForVisible(Selectors.activeWebview)
.windowByIndex(1)
@@ -239,10 +235,11 @@ describe('application window', function () {
}
}, page1)
.click('#trigger')
+ .windowByIndex(0)
})
it('opens in a new tab', function *() {
- var selector = 'frameWrapper:nth-child(2) webview'
+ var selector = '.frameWrapper:nth-child(2) webview'
var page1 = Brave.server.url('page1.html')
yield this.app.client
@@ -250,56 +247,510 @@ describe('application window', function () {
.waitUntil(function () {
return this.getAttribute(selector, 'src').then(src => src === page1)
})
- .getWindowCount().should.eventually.equal(2) // still just one window
+ .getWindowCount().should.eventually.equal(3) // one window with 2 tabs
})
})
- describe('with target _self', function () {
+ // http://www.w3.org/TR/html51/browsers.html#security-window
+ describe('window.opener', function () {
+ describe('different document.domain', function () {
+ Brave.beforeAll(this)
+
+ before(function *() {
+ this.window_open_page = Brave.server.url('window_open.html')
+ this.page1 = Brave.server.urlWithIpAddress('page1.html')
+ var page1 = this.page1 // for wait closure
+
+ yield this.app.client
+ .waitUntilWindowLoaded()
+ .waitForVisible(Selectors.activeWebview)
+ .windowByIndex(1)
+ .url(this.window_open_page)
+ .execute(function (page1) {
+ global.triggerFunction = function () {
+ return window.open(page1, 'page1', 'height=300, width=500, top=100, left=0')
+ }
+ }, this.page1)
+ .click('#trigger')
+ .waitUntil(function () {
+ return this.getWindowCount().then((count) => {
+ return count === 4 // two windows with two views each
+ })
+ })
+ // page1 loaded
+ .waitUntil(function () {
+ return this.windowByUrl(page1).getUrl().then((response) => {
+ return response === page1
+ })
+ })
+ })
+
+ it('has parent document.domain set to localhost', function *() {
+ yield this.app.client
+ .windowByUrl(this.window_open_page)
+ .execute(function () {
+ return document.domain
+ }).then(response => response.value).should.eventually.be.equal('localhost')
+ })
+
+ it('has document.domain set to 127.0.0.1', function *() {
+ yield this.app.client
+ .windowByUrl(this.page1)
+ .execute(function () {
+ return document.domain
+ }).then(response => response.value).should.eventually.be.equal('127.0.0.1')
+ })
+
+ it('can communicate with the opener through postMessage', function *() {
+ yield this.app.client
+ // make sure the child window has focus
+ .windowByUrl(this.window_open_page)
+ .execute(function () {
+ global.events = []
+ window.addEventListener('message', function (event) {
+ global.events.push(event.data)
+ })
+ })
+ .windowByUrl(this.page1)
+ .execute(function () {
+ window.opener.postMessage('any origin', '*')
+ })
+ .execute(function (origin) {
+ window.opener.postMessage('target origin', origin)
+ }, Brave.server.urlOrigin())
+ .execute(function () {
+ window.opener.postMessage('other origin', 'https://somedomain.com')
+ })
+ .windowByUrl(this.window_open_page)
+ .execute(function () {
+ return global.events
+ }).then(response => response.value).should.eventually.be.deep.equal(['any origin', 'target origin'])
+ })
+
+ it('focuses the opener', function *() {
+ yield this.app.client
+ // make sure the child window has focus
+ .windowByUrl(this.page1)
+ .waitUntil(function () {
+ return this.execute(function () {
+ return document.hasFocus() === true
+ })
+ })
+ .execute(function () {
+ window.opener.focus()
+ })
+ // wait for focus
+ .windowParentByUrl(this.window_open_page)
+ .waitUntil(function () {
+ return this.execute(function () {
+ return (document.hasFocus() === true)
+ })
+ })
+ .windowParentByUrl(this.window_open_page)
+ .execute(function () {
+ return document.hasFocus()
+ }).then(response => response.value).should.eventually.be.equal(true, 'expected opener to be focused, but was blurred')
+ })
+
+ it('blurs the opener', function *() {
+ yield this.app.client
+ // make sure parent window has focus
+ .windowByUrl(this.page1)
+ .execute(function () {
+ window.opener.focus()
+ })
+ .waitUntil(function () {
+ return this.execute(function () {
+ return document.hasFocus() === false
+ })
+ })
+ // blur parent window
+ .windowByUrl(this.page1)
+ .execute(function () {
+ window.opener.blur()
+ })
+ .windowParentByUrl(this.window_open_page)
+ .waitUntil(function () {
+ return this.execute(function () {
+ return document.hasFocus() === false
+ })
+ })
+ .execute(function () {
+ return document.hasFocus()
+ }).then(response => response.value).should.eventually.be.equal(false, 'expected opener to be blurred, but was focused')
+ })
+
+ it('has restricted access in parent to child window', function *() {
+ yield this.app.client
+ .windowByUrl(this.window_open_page)
+ .execute(function () {
+ return window.WINDOW_REF.eval('1+2')
+ }).should.be.rejectedWith(Error)
+ })
+
+ it('has restricted access to parent window through the opener', function *() {
+ yield this.app.client
+ .windowByUrl(this.page1)
+ .execute(function () {
+ return window.opener.eval('1+2')
+ }).should.be.rejectedWith(Error)
+ })
+
+ // https://github.com/brave/browser-laptop/issues/137
+ it('can be focused/blurred/closed by the opener')
+ })
+
+ describe('same document.domain', function () {
+ Brave.beforeAll(this)
+
+ before(function *() {
+ this.window_open_page = Brave.server.url('window_open.html')
+ this.page1 = Brave.server.url('page1.html')
+ var page1 = this.page1 // for wait closure
+
+ yield this.app.client
+ .waitUntilWindowLoaded()
+ .waitForVisible(Selectors.activeWebview)
+ .windowByIndex(1)
+ .url(this.window_open_page)
+ .execute(function (page1) {
+ global.triggerFunction = function () {
+ return window.open(page1, 'page1', 'height=300, width=500, top=100, left=0')
+ }
+ }, this.page1)
+ .click('#trigger')
+ .waitUntil(function () {
+ return this.getWindowCount().then((count) => {
+ return count === 4 // two windows with two views each
+ })
+ })
+ // page1 loaded
+ .waitUntil(function () {
+ return this.windowByUrl(page1).getUrl().then((response) => {
+ return response === page1
+ })
+ })
+ })
+
+ it('has parent document.domain set to localhost', function *() {
+ yield this.app.client
+ .windowByUrl(this.window_open_page)
+ .execute(function () {
+ return document.domain
+ }).then(response => response.value).should.eventually.be.equal('localhost')
+ })
+
+ it('has document.domain set to localhost', function *() {
+ yield this.app.client
+ .windowByUrl(this.page1)
+ .execute(function () {
+ return document.domain
+ }).then(response => response.value).should.eventually.be.equal('localhost')
+ })
+
+ // https://github.com/brave/browser-laptop/issues/137
+ it.skip('has urestricted access in parent to child window', function *() {
+ yield this.app.client
+ .windowByUrl(this.window_open_page)
+ .execute(function () {
+ return window.WINDOW_REF.eval('1+2')
+ }).then(response => response.value).should.eventually.be.equal(3)
+ })
+
+ // https://github.com/brave/browser-laptop/issues/137
+ it.skip('has urestricted access to parent window through the opener', function *() {
+ yield this.app.client
+ .windowByUrl(this.page1)
+ .execute(function () {
+ return window.opener.eval('1+2')
+ })
+ .then(response => response.value)
+ .should.eventually.be.equal(3)
+ })
+ })
+ })
+ })
+
+ describe('window.open with faked click', function () {
+ Brave.beforeAll(this)
+
+ before(function *() {
+ this.window_open_page = Brave.server.url('window_open.html')
+ this.page1 = Brave.server.urlWithIpAddress('page1.html')
+
+ yield this.app.client
+ .waitUntilWindowLoaded()
+ .waitForVisible(Selectors.activeWebview)
+ .windowByIndex(1)
+ .url(this.window_open_page)
+ .execute(function (page1) {
+ global.triggerFunction = function () {
+ return window.open(page1, 'page1', 'height=300, width=500, top=100, left=0')
+ }
+ document.getElementById('trigger').click()
+ }, this.page1)
+ })
+
+ it('does not open a new window or tab', function *() {
+ // this isn't a very good test because it could evaluate before the new
+ // tab/window opens. Is there something else we can check?
+ yield this.app.client
+ .getWindowCount().should.eventually.equal(2) // still just one window
+
+ // still just one frame
+ yield this.app.client.isExisting('.frameWrapper:nth-child(2) webview').should.eventually.be.false
+ })
+
+ // https://app.asana.com/0/79517354322876/79040692096404
+ it('triggers a popup warning messages')
+ })
+
+ // https://github.com/brave/browser-laptop/issues/98
+ describe('window.open without click', function () {
+ describe('default', function () {
Brave.beforeAll(this)
- it('should set current frame url', function *() {
+ before(function *() {
var page1 = Brave.server.url('page1.html')
yield this.app.client
+ .windowByIndex(0)
+ .waitUntilWindowLoaded()
.waitForVisible(Selectors.activeWebview)
.windowByIndex(1)
.url(Brave.server.url('window_open.html'))
.execute(function (page1) {
- global.triggerFunction = function () {
- return window.open(page1, '_self')
- }
+ window.open(page1, '_blank')
}, page1)
- .click('#trigger')
- .windowByIndex(0)
+ })
+
+ // https://app.asana.com/0/41575558488236/45343396929071
+ it('does not open a new window or tab', function *() {
+ // this isn't a very good test because it could evaluate before the new
+ // tab/window opens. Is there something else we can check?
+ yield this.app.client
+ .getWindowCount().should.eventually.equal(2) // still just one window
+ yield this.app.client.isExisting('.frameWrapper:nth-child(2) webview').should.eventually.be.false // still just one frame
+ })
+
+ // https://app.asana.com/0/79517354322876/79040692096404
+ it('triggers a popup warning messages')
+ })
+
+ // https://app.asana.com/0/63968741000775/79040692096405
+ describe('domain allowed by preferences', function () {
+ it('opens in a new tab')
+
+ // https://app.asana.com/0/63968741000775/79040692096404
+ it('does not trigger a popup warning messages')
+ })
+ })
+
+ describe('click link', function () {
+ describe('with target', function () {
+ Brave.beforeAll(this)
+
+ before(function *() {
+ this.click_with_target_page = Brave.server.url('click_with_target.html')
+ this.page1 = Brave.server.url('page1.html')
+ this.page2 = Brave.server.url('page2.html')
+
+ yield this.app.client
+ .waitUntilWindowLoaded()
.waitForVisible(Selectors.activeWebview)
.windowByIndex(1)
+ .url(this.click_with_target_page)
+ .waitForVisible('#name')
+ .click('#name')
+ })
+
+ it('opens in a new tab', function *() {
+ let click_with_target_page = this.click_with_target_page
+ let page1 = this.page1
+
+ yield this.app.client
+ .windowByIndex(0)
+ .waitForVisible('.frameWrapper:nth-child(1) webview')
+ .waitUntil(function () {
+ return this.getAttribute('.frameWrapper:nth-child(1) webview', 'src').then(src => src === click_with_target_page)
+ })
+ yield this.app.client
+ .windowByIndex(0)
+ .waitForVisible('.frameWrapper:nth-child(2) webview')
.waitUntil(function () {
- return this.getUrl().then(url => url === page1)
+ return this.getAttribute('.frameWrapper:nth-child(2) webview', 'src').then(src => src === page1)
})
})
+
+ // https://github.com/brave/browser-laptop/issues/143
+ it.skip('loads in the tab with the target name', function *() {
+ let click_with_target_page = this.click_with_target_page
+ let page2 = this.page2
+
+ yield this.app.client
+ .windowByIndex(0)
+ .click('.tabArea:nth-child(1)')
+ .windowByIndex(1)
+ .waitForVisible('#name2')
+ .click('#name2')
+ .windowByIndex(0)
+
+ yield this.app.client
+ .waitForVisible('.frameWrapper:nth-child(1) webview')
+ .waitUntil(function () {
+ return this.getAttribute('.frameWrapper:nth-child(1) webview', 'src').then(src => src === click_with_target_page)
+ })
+ yield this.app.client
+ .waitForVisible('.frameWrapper:nth-child(2) webview')
+ .waitUntil(function () {
+ return this.getAttribute('.frameWrapper:nth-child(2) webview', 'src').then(src => src === page2)
+ })
+ yield this.app.client
+ .isExisting('.frameWrapper:nth-child(3) webview').should.eventually.be.false // same tab
+ })
})
- })
- // requires https://github.com/brave/browser-electron/issues/97
- // also see https://app.asana.com/0/41575558488236/45343396929071
- describe('window.open without onClick', function () {
- describe('domain blocked by preferences', function () {
- it('should trigger a popup warning messages')
+ describe('without target', function () {
+ Brave.beforeAll(this)
+
+ before(function *() {
+ this.click_with_target_page = Brave.server.url('click_with_target.html')
+ this.page1 = Brave.server.url('page1.html')
+
+ yield this.app.client
+ .waitUntilWindowLoaded()
+ .waitForVisible(Selectors.activeWebview)
+ .windowByIndex(1)
+ .url(this.click_with_target_page)
+ .waitForVisible('#none')
+ .click('#none')
+ })
+
+ it('loads in the current tab', function *() {
+ var page1 = this.page1 // for wait closure
+ yield this.app.client
+ // page1 loaded
+ .waitUntil(function () {
+ return this.windowByUrl(page1).getUrl().then((response) => {
+ return response === page1
+ })
+ })
+
+ // this isn't a very good test because it could evaluate before the new
+ // tab/window opens. Is there something else we can check?
+ yield this.app.client
+ .getWindowCount().should.eventually.equal(2) // still just one window
+
+ yield this.app.client.isExisting('.frameWrapper:nth-child(2) webview').should.eventually.be.false // still just one frame
+ })
})
- describe('domain not blocked by preferences', function () {
- it('should open in a new window')
+ describe('with target _self', function () {
+ Brave.beforeAll(this)
+
+ before(function *() {
+ this.click_with_target_page = Brave.server.url('click_with_target.html')
+ this.page1 = Brave.server.url('page1.html')
+
+ yield this.app.client
+ .waitUntilWindowLoaded()
+ .waitForVisible(Selectors.activeWebview)
+ .windowByIndex(1)
+ .url(this.click_with_target_page)
+ .waitForVisible('#_self')
+ .click('#_self')
+ })
+
+ it('loads in the current tab', function *() {
+ var page1 = this.page1 // for wait closure
+ yield this.app.client
+ // page1 loaded
+ .waitUntil(function () {
+ return this.windowByUrl(page1).getUrl().then((response) => {
+ return response === page1
+ })
+ })
+
+ // this isn't a very good test because it could evaluate before the new
+ // tab/window opens. Is there something else we can check?
+ yield this.app.client
+ .getWindowCount().should.eventually.equal(2) // still just one window
+
+ yield this.app.client.isExisting('.frameWrapper:nth-child(2) webview').should.eventually.be.false // still just one frame
+ })
})
- })
- // requires https://github.com/brave/browser-electron/issues/98
- describe('click link', function () {
- describe('with target', function () {
- it('should open in a new tab')
+ describe('with target _parent', function () {
+ Brave.beforeAll(this)
+
+ before(function *() {
+ this.click_with_target_page = Brave.server.url('click_with_target.html')
+ this.page1 = Brave.server.url('page1.html')
+
+ yield this.app.client
+ .waitUntilWindowLoaded()
+ .waitForVisible(Selectors.activeWebview)
+ .windowByIndex(1)
+ .url(this.click_with_target_page)
+ .frame('parent')
+ .waitForVisible('#_parent')
+ .click('#_parent')
+ })
+
+ it('sets the url of the parent frame in the same domain', function *() {
+ var page1 = this.page1 // for wait closure
+ yield this.app.client
+ // page1 loaded
+ .waitUntil(function () {
+ return this.windowByUrl(page1).getUrl().then((response) => {
+ return response === page1
+ })
+ })
+
+ // this isn't a very good test because it could evaluate before the new
+ // tab/window opens. Is there something else we can check?
+ yield this.app.client
+ .getWindowCount().should.eventually.equal(2) // still just one window
+
+ yield this.app.client.isExisting('.frameWrapper:nth-child(2) webview').should.eventually.be.false // still just one frame
+ })
})
- describe('without target', function () {
- it('should open in the current tab')
+ describe('with target _top', function () {
+ Brave.beforeAll(this)
+
+ before(function *() {
+ this.click_with_target_page = Brave.server.url('click_with_target.html')
+ this.page1 = Brave.server.url('page1.html')
+
+ yield this.app.client
+ .waitUntilWindowLoaded()
+ .waitForVisible(Selectors.activeWebview)
+ .windowByIndex(1)
+ .url(this.click_with_target_page)
+ .frame('parent')
+ .frame('top')
+ .waitForVisible('#_top')
+ .click('#_top')
+ })
+
+ it('sets the url of the top-level frame in the same domain', function *() {
+ var page1 = this.page1 // for wait closure
+ yield this.app.client
+ // page1 loaded
+ .waitUntil(function () {
+ return this.windowByUrl(page1).getUrl().then((response) => {
+ return response === page1
+ })
+ })
+
+ // this isn't a very good test because it could evaluate before the new
+ // tab/window opens. Is there something else we can check?
+ yield this.app.client
+ .getWindowCount().should.eventually.equal(2) // still just one window
+
+ yield this.app.client.isExisting('.frameWrapper:nth-child(2) webview').should.eventually.be.false // still just one frame
+ })
})
})