fix(server): Fix EACCES on extension installation if copied from read-only location (#17800)

Co-authored-by: Jennifer Shehane <jennifer@cypress.io>
Co-authored-by: Zach Bloomquist <github@chary.us>
Co-authored-by: Chris Breiding <chrisbreiding@users.noreply.github.com>
This commit is contained in:
Hernawan Faïz Abdillah
2021-09-08 01:40:59 +07:00
committed by GitHub
parent a6a2c49c35
commit d8796bc11b
4 changed files with 81 additions and 0 deletions

View File

@@ -375,6 +375,7 @@ export = {
// copy the extension src to the extension dist
await utils.copyExtension(pathToExtension, extensionDest)
await fs.chmod(extensionBg, 0o0644)
await fs.writeFileAsync(extensionBg, str)
return extensionDest

View File

@@ -224,6 +224,10 @@ export = {
.then(() => {
debug('copied extension')
// ensure write access before overwriting
return fs.chmod(extensionBg, 0o0644)
})
.then(() => {
// and overwrite background.js with the final string bytes
return fs.writeFileAsync(extensionBg, str)
})

View File

@@ -1,6 +1,9 @@
require('../../spec_helper')
const os = require('os')
const mockfs = require('mock-fs')
const path = require('path')
const _ = require('lodash')
const extension = require('@packages/extension')
const launch = require('@packages/launcher/lib/browsers')
@@ -59,6 +62,7 @@ describe('lib/browsers/chrome', () => {
})
afterEach(function () {
mockfs.restore()
expect(this.criClient.ensureMinimumProtocolVersion).to.be.calledOnce
})
@@ -228,6 +232,43 @@ describe('lib/browsers/chrome', () => {
})
})
it('install extension and ensure write access', function () {
mockfs({
[path.resolve(`${__dirname }../../../../../extension/dist`)]: {
'background.js': mockfs.file({
mode: 0o0444,
}),
},
})
const getFile = function (path) {
return _.reduce(_.compact(_.split(path, '/')), (acc, item) => {
return acc.getItem(item)
}, mockfs.getMockRoot())
}
chrome._writeExtension.restore()
utils.getProfileDir.restore()
const profilePath = '/home/foo/snap/chromium/current'
const fullPath = `${profilePath}/Cypress/chromium-stable/interactive`
this.readJson.withArgs(`${fullPath}/Default/Preferences`).rejects({ code: 'ENOENT' })
this.readJson.withArgs(`${fullPath}/Default/Secure Preferences`).rejects({ code: 'ENOENT' })
this.readJson.withArgs(`${fullPath}/Local State`).rejects({ code: 'ENOENT' })
return chrome.open({
isHeadless: false,
isHeaded: false,
profilePath,
name: 'chromium',
channel: 'stable',
}, 'http://', {}, this.automation)
.then(() => {
expect((getFile(fullPath).getMode()) & 0o0700).to.be.above(0o0500)
})
})
it('cleans up an unclean browser profile exit status', function () {
this.readJson.withArgs('/profile/dir/Default/Preferences').resolves({
profile: {

View File

@@ -10,6 +10,8 @@ import sinon from 'sinon'
import * as firefox from '../../../lib/browsers/firefox'
import firefoxUtil from '../../../lib/browsers/firefox-util'
const path = require('path')
const _ = require('lodash')
const mockfs = require('mock-fs')
const FirefoxProfile = require('firefox-profile')
const launch = require('@packages/launcher/lib/browsers')
@@ -213,6 +215,39 @@ describe('lib/browsers/firefox', () => {
})
})
it('writes extension and ensure write access', function () {
mockfs({
[path.resolve(`${__dirname }../../../../../extension/dist`)]: {
'background.js': mockfs.file({
mode: 0o444,
}),
},
[`${process.env.HOME }/.config/Cypress/cy/test/browsers/firefox-stable/interactive/CypressExtension`]: {
'background.js': mockfs.file({
content: 'abcn',
mode: 0o444,
}),
},
[path.resolve(`${__dirname }/../../extension`)]: { 'abc': 'test' },
'/path/to/appData/firefox-stable/interactive': {
'xulstore.json': '[foo xulstore.json]',
'chrome': { 'userChrome.css': '[foo userChrome.css]' },
},
})
utils.writeExtension.restore()
const getFile = function (path) {
return _.reduce(_.compact(_.split(path, '/')), (acc, item) => {
return acc.getItem(item)
}, mockfs.getMockRoot())
}
return firefox.open(this.browser, 'http://', this.options).then(() => {
expect(getFile(`${process.env.HOME }/.config/Cypress/cy/test/browsers/firefox-stable/interactive/CypressExtension/background.js`).getMode()).to.be.equals(0o644)
})
})
// TODO: pick open port for debugger
it.skip('finds remote port for firefox debugger', function () {
return firefox.open(this.browser, 'http://', this.options).then(() => {