Skip to content

Commit

Permalink
chore: rename getOriginPolicy to getParentOriginPolicy as the method …
Browse files Browse the repository at this point in the history
…does not include subdomain, which is a parent of origin policy, as well as add documentation as to why we need this
  • Loading branch information
AtofStryker committed Sep 9, 2022
1 parent e7386a5 commit cdbdf21
Show file tree
Hide file tree
Showing 22 changed files with 204 additions and 119 deletions.
2 changes: 1 addition & 1 deletion packages/app/src/runner/aut-iframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export class AutIframe {
const locationTop = Cypress.Location.create(window.location.href)
const locationAUT = Cypress.Location.create(currentHref)

return locationTop.originPolicy === locationAUT.originPolicy || locationAUT.originPolicy === 'about://blank'
return locationTop.parentOriginPolicy === locationAUT.parentOriginPolicy || locationAUT.parentOriginPolicy === 'about://blank'
} catch (err) {
if (err.name === 'SecurityError') {
return false
Expand Down
18 changes: 9 additions & 9 deletions packages/app/src/runner/event-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -637,13 +637,13 @@ export class EventManager {
})
})

Cypress.primaryOriginCommunicator.on('window:load', ({ url }, originPolicy) => {
Cypress.primaryOriginCommunicator.on('window:load', ({ url }, parentOriginPolicy) => {
// Sync stable if the expected origin has loaded.
// Only listen to window load events from the most recent secondary origin, This prevents nondeterminism in the case where we redirect to an already
// established spec bridge, but one that is not the current or next cy.origin command.
if (cy.state('latestActiveOriginPolicy') === originPolicy) {
if (cy.state('latestActiveParentOriginPolicy') === parentOriginPolicy) {
// We remain in an anticipating state until either a load even happens or a timeout.
cy.state('autOrigin', cy.state('autOrigin', cors.getOriginPolicy(url)))
cy.state('autOrigin', cy.state('autOrigin', cors.getParentOriginPolicy(url)))
cy.isAnticipatingCrossOriginResponseFor(undefined)
cy.isStable(true, 'load')
// Prints out the newly loaded URL
Expand All @@ -665,18 +665,18 @@ export class EventManager {
this.localBus.emit('expect:origin', originPolicy)
})

Cypress.primaryOriginCommunicator.on('viewport:changed', (viewport, originPolicy) => {
Cypress.primaryOriginCommunicator.on('viewport:changed', (viewport, parentOriginPolicy) => {
const callback = () => {
Cypress.primaryOriginCommunicator.toSpecBridge(originPolicy, 'viewport:changed:end')
Cypress.primaryOriginCommunicator.toSpecBridge(parentOriginPolicy, 'viewport:changed:end')
}

Cypress.primaryOriginCommunicator.emit('sync:viewport', viewport)
this.localBus.emit('viewport:changed', viewport, callback)
})

Cypress.primaryOriginCommunicator.on('before:screenshot', (config, originPolicy) => {
Cypress.primaryOriginCommunicator.on('before:screenshot', (config, parentOriginPolicy) => {
const callback = () => {
Cypress.primaryOriginCommunicator.toSpecBridge(originPolicy, 'before:screenshot:end')
Cypress.primaryOriginCommunicator.toSpecBridge(parentOriginPolicy, 'before:screenshot:end')
}

handleBeforeScreenshot(config, callback)
Expand Down Expand Up @@ -842,9 +842,9 @@ export class EventManager {
this.ws.emit('spec:changed', specFile)
}

notifyCrossOriginBridgeReady (originPolicy) {
notifyCrossOriginBridgeReady (parentOriginPolicy) {
// Any multi-origin event appends the origin as the third parameter and we do the same here for this short circuit
Cypress.primaryOriginCommunicator.emit('bridge:ready', undefined, originPolicy)
Cypress.primaryOriginCommunicator.emit('bridge:ready', undefined, parentOriginPolicy)
}

snapshotUnpinned () {
Expand Down
6 changes: 3 additions & 3 deletions packages/app/src/runner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,11 @@ export async function teardown () {
* Add a cross origin iframe for cy.origin support
*/
export function addCrossOriginIframe (location) {
const id = `Spec Bridge: ${location.originPolicy}`
const id = `Spec Bridge: ${location.parentOriginPolicy}`

// if it already exists, don't add another one
if (document.getElementById(id)) {
getEventManager().notifyCrossOriginBridgeReady(location.originPolicy)
getEventManager().notifyCrossOriginBridgeReady(location.parentOriginPolicy)

return
}
Expand All @@ -216,7 +216,7 @@ export function addCrossOriginIframe (location) {
// container since it needs to match the size of the top window for screenshots
$container: document.body,
className: 'spec-bridge-iframe',
src: `${location.originPolicy}/${getRunnerConfigFromWindow().namespace}/spec-bridge-iframes`,
src: `${location.parentOriginPolicy}/${getRunnerConfigFromWindow().namespace}/spec-bridge-iframes`,
})
}

Expand Down
4 changes: 2 additions & 2 deletions packages/driver/cypress/e2e/commands/location.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ describe('src/cy/commands/location', () => {
context('#location', () => {
it('returns the location object', () => {
cy.location().then((loc) => {
expect(loc).to.have.keys(['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'origin', 'pathname', 'port', 'protocol', 'search', 'originPolicy', 'superDomain', 'toString'])
expect(loc).to.have.keys(['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'origin', 'pathname', 'port', 'protocol', 'search', 'originPolicy', 'parentOriginPolicy', 'superDomain', 'toString'])
})
})

Expand Down Expand Up @@ -529,7 +529,7 @@ describe('src/cy/commands/location', () => {

expect(_.keys(consoleProps)).to.deep.eq(['Command', 'Yielded'])
expect(consoleProps.Command).to.eq('location')
expect(_.keys(consoleProps.Yielded)).to.deep.eq(['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'origin', 'pathname', 'port', 'protocol', 'search', 'originPolicy', 'superDomain', 'toString'])
expect(_.keys(consoleProps.Yielded)).to.deep.eq(['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'origin', 'pathname', 'port', 'protocol', 'search', 'originPolicy', 'parentOriginPolicy', 'superDomain', 'toString'])
})
})
})
Expand Down
57 changes: 54 additions & 3 deletions packages/driver/cypress/e2e/cypress/location.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ describe('src/cypress/location', () => {
it('handles subdomains google', function () {
const str = this.setup('google').getOriginPolicy()

expect(str).to.eq('https://google.com')
expect(str).to.eq('https://www.google.com')
})

it('issue: #255 two domains in the url', function () {
Expand All @@ -243,20 +243,71 @@ describe('src/cypress/location', () => {
it('handles subdomains of private tlds in the public suffix', function () {
const str = this.setup('herokuSub').getOriginPolicy()

expect(str).to.eq('https://example.herokuapp.com')
expect(str).to.eq('https://foo.example.herokuapp.com')
})

it('falls back to dumb check when invalid tld', function () {
const str = this.setup('unknown').getOriginPolicy()

expect(str).to.eq('http://what.is.so.unknown')
})
})

// TODO: getParentOriginPolicy
context('#getParentOriginPolicy', () => {
it('handles ip addresses', function () {
const str = this.setup('local').getParentOriginPolicy()

expect(str).to.eq('http://127.0.0.1:8080')
})

it('handles 1 part localhost', function () {
const str = this.setup('users').getParentOriginPolicy()

expect(str).to.eq('http://localhost:2020')
})

it('handles 2 parts stack', function () {
const str = this.setup('stack').getParentOriginPolicy()

expect(str).to.eq('https://stackoverflow.com')
})

it('handles subdomains google', function () {
const str = this.setup('google').getParentOriginPolicy()

expect(str).to.eq('https://google.com')
})

it('issue: #255 two domains in the url', function () {
const str = this.setup('email').getParentOriginPolicy()

expect(str).to.eq('http://localhost:3500')
})

it('handles private tlds in the public suffix', function () {
const str = this.setup('heroku').getParentOriginPolicy()

expect(str).to.eq('https://example.herokuapp.com')
})

it('handles subdomains of private tlds in the public suffix', function () {
const str = this.setup('herokuSub').getParentOriginPolicy()

expect(str).to.eq('https://example.herokuapp.com')
})

it('falls back to dumb check when invalid tld', function () {
const str = this.setup('unknown').getParentOriginPolicy()

expect(str).to.eq('http://so.unknown')
})
})

context('.create', () => {
it('returns an object literal', () => {
const obj = Location.create(urls.cypress, urls.signin)
const keys = ['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'origin', 'pathname', 'port', 'protocol', 'search', 'toString', 'originPolicy', 'superDomain']
const keys = ['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'origin', 'pathname', 'port', 'protocol', 'search', 'toString', 'originPolicy', 'parentOriginPolicy', 'superDomain']

expect(obj).to.have.keys(keys)
})
Expand Down
16 changes: 8 additions & 8 deletions packages/driver/src/cross-origin/communicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class PrimaryOriginCommunicator extends EventEmitter {
// where we need to set the crossOriginDriverWindows to source to
// communicate back to the iframe
if (messageName === 'bridge:ready' && source) {
this.crossOriginDriverWindows[data.originPolicy] = source as Window
this.crossOriginDriverWindows[data.parentOriginPolicy] = source as Window
}

// reify any logs coming back from the cross-origin spec bridges to serialize snapshot/consoleProp DOM elements as well as select functions.
Expand All @@ -59,7 +59,7 @@ export class PrimaryOriginCommunicator extends EventEmitter {
data.data.err = reifySerializedError(data.data.err, this.userInvocationStack as string)
}

this.emit(messageName, data.data, data.originPolicy)
this.emit(messageName, data.data, data.parentOriginPolicy)

return
}
Expand Down Expand Up @@ -91,8 +91,8 @@ export class PrimaryOriginCommunicator extends EventEmitter {
})
}

toSpecBridge (originPolicy: string, event: string, data?: any) {
debug('=> to spec bridge', originPolicy, event, data)
toSpecBridge (parentOriginPolicy: string, event: string, data?: any) {
debug('=> to spec bridge', parentOriginPolicy, event, data)

const preprocessedData = preprocessForSerialization<any>(data)

Expand All @@ -102,7 +102,7 @@ export class PrimaryOriginCommunicator extends EventEmitter {
}

// If there is no crossOriginDriverWindows, there is no need to send the message.
this.crossOriginDriverWindows[originPolicy]?.postMessage({
this.crossOriginDriverWindows[parentOriginPolicy]?.postMessage({
event,
data: preprocessedData,
}, '*')
Expand Down Expand Up @@ -183,7 +183,7 @@ export class SpecBridgeCommunicator extends EventEmitter {
* @param {Cypress.ObjectLike} data - any meta data to be sent with the event.
*/
toPrimary (event: string, data?: Cypress.ObjectLike, options: { syncGlobals: boolean } = { syncGlobals: false }) {
const { originPolicy } = $Location.create(window.location.href)
const { parentOriginPolicy } = $Location.create(window.location.href)
const eventName = `${CROSS_ORIGIN_PREFIX}${event}`

// Preprocess logs before sending through postMessage() to attempt to serialize some DOM nodes and functions.
Expand All @@ -197,14 +197,14 @@ export class SpecBridgeCommunicator extends EventEmitter {
data = preprocessSnapshotForSerialization(data as any)
}

debug('<= to Primary ', event, data, originPolicy)
debug('<= to Primary ', event, data, parentOriginPolicy)
if (options.syncGlobals) this.syncGlobalsToPrimary()

this.handleSubjectAndErr(data, (data: Cypress.ObjectLike) => {
window.top?.postMessage({
event: eventName,
data,
originPolicy,
parentOriginPolicy,
}, '*')
})
}
Expand Down
8 changes: 4 additions & 4 deletions packages/driver/src/cross-origin/cypress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ const createCypress = () => {
})

Cypress.specBridgeCommunicator.on('generate:final:snapshot', (snapshotUrl: string) => {
const currentAutOriginPolicy = cy.state('autOrigin')
const currentAutParentOriginPolicy = cy.state('autParentOrigin')
const requestedSnapshotUrlLocation = $Location.create(snapshotUrl)

if (requestedSnapshotUrlLocation.originPolicy === currentAutOriginPolicy) {
if (requestedSnapshotUrlLocation.parentOriginPolicy === currentAutParentOriginPolicy) {
// if true, this is the correct specbridge to take the snapshot and send it back
const finalSnapshot = cy.createSnapshot(FINAL_SNAPSHOT_NAME)

Expand Down Expand Up @@ -144,7 +144,7 @@ const onBeforeAppWindowLoad = (Cypress: Cypress.Cypress, cy: $Cy) => (autWindow:
const onWindowLoadPrimary = ({ url }) => {
cy.isStable(true, 'primary onload')

cy.state('autOrigin', cors.getOriginPolicy(url))
cy.state('autOrigin', cors.getParentOriginPolicy(url))
Cypress.emit('internal:window:load', { type: 'cross:origin', url })
}

Expand Down Expand Up @@ -179,7 +179,7 @@ const onBeforeAppWindowLoad = (Cypress: Cypress.Cypress, cy: $Cy) => (autWindow:

const remoteLocation = cy.getRemoteLocation()

cy.state('autOrigin', remoteLocation.originPolicy)
cy.state('autParentOrigin', remoteLocation.parentOriginPolicy)

Cypress.specBridgeCommunicator.toPrimary('window:load', { url: remoteLocation.href })
cy.isStable(true, 'load')
Expand Down
14 changes: 7 additions & 7 deletions packages/driver/src/cy/commands/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ const timedOutWaitingForPageLoad = (ms, log) => {
cy.isAnticipatingCrossOriginResponseFor(undefined)

// By default origins is just this location.
let originPolicies = [$Location.create(location.href).originPolicy]
let originPolicies = [$Location.create(location.href).parentOriginPolicy]

const currentCommand = cy.queue.state('current')

if (currentCommand?.get('name') === 'origin') {
// If the current command is a cy.origin command, we should have gotten a request on the origin it expects.
originPolicies = [cy.state('latestActiveOriginPolicy')]
originPolicies = [cy.state('latestActiveParentOriginPolicy')]
} else if (Cypress.isCrossOriginSpecBridge && cy.queue.isOnLastCommand()) {
// If this is a cross origin spec bridge and we're on the last command, we should have gotten a request on the origin of one of the parents.
originPolicies = cy.state('parentOriginPolicies')
Expand Down Expand Up @@ -342,15 +342,15 @@ const stabilityChanged = (Cypress, state, config, stable) => {
const onPageLoadErr = (err) => {
state('onPageLoadErr', null)

const { originPolicy } = $Location.create(window.location.href)
const { parentOriginPolicy } = $Location.create(window.location.href)

try {
$errUtils.throwErrByPath('navigation.cross_origin', {
onFail: options._log,
args: {
configFile: Cypress.config('configFile'),
message: err.message,
originPolicy,
parentOriginPolicy,
},
})
} catch (error) {
Expand Down Expand Up @@ -1123,9 +1123,9 @@ export default (Commands, Cypress, cy, state, config) => {

remote = $Location.create(url)

// if the origin currently matches
// if the parent origin currently matches
// then go ahead and change the iframe's src
if (remote.originPolicy === existing.originPolicy) {
if (remote.parentOriginPolicy === existing.parentOriginPolicy) {
previouslyVisitedLocation = remote

url = $Location.fullyQualifyUrl(url)
Expand Down Expand Up @@ -1153,7 +1153,7 @@ export default (Commands, Cypress, cy, state, config) => {
// we need to throw an error since the user tried to visit a new
// origin which isn't allowed within a cy.origin block
if (Cypress.isCrossOriginSpecBridge) {
const existingAutOrigin = win ? $Location.create(win.location.href) : $Location.create(Cypress.state('currentActiveOriginPolicy'))
const existingAutOrigin = win ? $Location.create(win.location.href) : $Location.create(Cypress.state('currentActiveParentOriginPolicy'))
const params = { remote, existing, originalUrl, previouslyVisitedLocation: existingAutOrigin, log: options._log, isCrossOriginSpecBridge: true, isPrimaryOrigin }

return isPrimaryOrigin ? cannotVisitPreviousOrigin(params) : cannotVisitDifferentOrigin(params)
Expand Down
Loading

0 comments on commit cdbdf21

Please sign in to comment.