Skip to content

Commit

Permalink
refactor: move videoCapture to browsers
Browse files Browse the repository at this point in the history
  • Loading branch information
flotwig committed Aug 30, 2022
1 parent a7f6d4b commit e3b1979
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 173 deletions.
31 changes: 18 additions & 13 deletions packages/server/lib/browsers/chrome.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import type { Protocol } from 'devtools-protocol'

import appData from '../util/app_data'
import { fs } from '../util/fs'
import * as videoCapture from '../video_capture'
import { CdpAutomation, screencastOpts } from './cdp_automation'
import * as protocol from './protocol'
import utils from './utils'
import type { Browser } from './types'
import type { Browser, BrowserInstance } from './types'
import { BrowserCriClient } from './browser-cri-client'
import type { LaunchedBrowser } from '@packages/launcher/lib/browsers'
import type { CriClient } from './cri-client'
import type { Automation } from '../automation'
import type { BrowserLaunchOpts, BrowserNewTabOpts, WriteVideoFrame } from '@packages/types'
import type { BrowserLaunchOpts, BrowserNewTabOpts, VideoBrowserOpt } from '@packages/types'

const debug = debugModule('cypress:server:browsers:chrome')

Expand Down Expand Up @@ -249,10 +249,14 @@ const _disableRestorePagesPrompt = function (userDir) {
.catch(() => { })
}

async function _recordVideo (cdpAutomation: CdpAutomation, writeVideoFrame: WriteVideoFrame, browserMajorVersion: number) {
const opts = browserMajorVersion >= CHROME_VERSION_WITH_FPS_INCREASE ? screencastOpts() : screencastOpts(1)
async function _recordVideo (cdpAutomation: CdpAutomation, videoOptions: VideoBrowserOpt, browserMajorVersion: number) {
const screencastOptions = browserMajorVersion >= CHROME_VERSION_WITH_FPS_INCREASE ? screencastOpts() : screencastOpts(1)

await cdpAutomation.startVideoRecording(writeVideoFrame, opts)
const videoController = await videoCapture.start(videoOptions)

videoOptions.setVideoController(videoController)

await cdpAutomation.startVideoRecording(videoController.writeVideoFrame, screencastOptions)
}

// a utility function that navigates to the given URL
Expand Down Expand Up @@ -552,7 +556,7 @@ export = {

if (!options.url) throw new Error('Missing url in connectToNewSpec')

await this.attachListeners(browser, options.url, pageCriClient, automation, options)
await this.attachListeners(options.url, pageCriClient, automation, options)
},

async connectToExisting (browser: Browser, options: BrowserLaunchOpts, automation: Automation) {
Expand All @@ -570,7 +574,7 @@ export = {
await this._setAutomation(pageCriClient, automation, browserCriClient.resetBrowserTargets, options)
},

async attachListeners (browser: Browser, url: string, pageCriClient: CriClient, automation: Automation, options: BrowserLaunchOpts | BrowserNewTabOpts) {
async attachListeners (url: string, pageCriClient: CriClient, automation: Automation, options: BrowserLaunchOpts | BrowserNewTabOpts) {
if (!browserCriClient) throw new Error('Missing browserCriClient in attachListeners')

const cdpAutomation = await this._setAutomation(pageCriClient, automation, browserCriClient.resetBrowserTargets, options)
Expand All @@ -580,7 +584,7 @@ export = {
await options['onInitializeNewBrowserTab']?.()

await Promise.all([
options.writeVideoFrame && this._recordVideo(cdpAutomation, options.writeVideoFrame, browser.majorVersion),
options.video && _recordVideo(cdpAutomation, options.video, Number(options.browser.majorVersion)),
this._handleDownloads(pageCriClient, options.downloadsFolder, automation),
])

Expand All @@ -590,9 +594,11 @@ export = {
await this._handlePausedRequests(pageCriClient)
_listenForFrameTreeChanges(pageCriClient)
}

return cdpAutomation
},

async open (browser: Browser, url, options: BrowserLaunchOpts, automation: Automation): Promise<LaunchedBrowser> {
async open (browser: Browser, url, options: BrowserLaunchOpts, automation: Automation): Promise<BrowserInstance> {
const { isTextTerminal } = options

const userDir = utils.getProfileDir(browser, isTextTerminal)
Expand Down Expand Up @@ -644,7 +650,7 @@ export = {
// first allows us to connect the remote interface,
// start video recording and then
// we will load the actual page
const launchedBrowser = await launch(browser, 'about:blank', port, args) as LaunchedBrowser & { browserCriClient: BrowserCriClient}
const launchedBrowser = await launch(browser, 'about:blank', port, args) as unknown as BrowserInstance & { browserCriClient: BrowserCriClient}

la(launchedBrowser, 'did not get launched browser instance')

Expand All @@ -671,7 +677,6 @@ export = {

launchedBrowser.browserCriClient = browserCriClient

/* @ts-expect-error */
launchedBrowser.kill = (...args) => {
debug('closing remote interface client')

Expand All @@ -686,7 +691,7 @@ export = {

const pageCriClient = await browserCriClient.attachToTargetUrl('about:blank')

await this.attachListeners(browser, url, pageCriClient, automation, options)
await this.attachListeners(url, pageCriClient, automation, options)

// return the launched browser process
// with additional method to close the remote connection
Expand Down
31 changes: 18 additions & 13 deletions packages/server/lib/browsers/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import menu from '../gui/menu'
import * as Windows from '../gui/windows'
import { CdpAutomation, screencastOpts, CdpCommand, CdpEvent } from './cdp_automation'
import * as savedState from '../saved_state'
import * as videoCapture from '../video_capture'
import utils from './utils'
import * as errors from '../errors'
import type { Browser, BrowserInstance } from './types'
import type { BrowserWindow, WebContents } from 'electron'
import type { Automation } from '../automation'
import type { BrowserLaunchOpts, Preferences } from '@packages/types'
import type { BrowserLaunchOpts, Preferences, VideoBrowserOpt } from '@packages/types'

// TODO: unmix these two types
type ElectronOpts = Windows.WindowOptions & BrowserLaunchOpts
Expand Down Expand Up @@ -72,7 +73,7 @@ const _getAutomation = async function (win, options, parent) {
// after upgrading to Electron 8, CDP screenshots can hang if a screencast is not also running
// workaround: start and stop screencasts between screenshots
// @see https://github.com/cypress-io/cypress/pull/6555#issuecomment-596747134
if (!options.writeVideoFrame) {
if (!options.video) {
await sendCommand('Page.startScreencast', screencastOpts())
const ret = await fn(message, data)

Expand Down Expand Up @@ -109,6 +110,14 @@ function _installExtensions (win: BrowserWindow, extensionPaths: string[], optio
}))
}

async function recordVideo (cdpAutomation: CdpAutomation, videoOptions: VideoBrowserOpt) {
const videoController = await videoCapture.start(videoOptions)

videoOptions.setVideoController(videoController)

await cdpAutomation.startVideoRecording(videoController.writeVideoFrame)
}

export = {
_defaultOptions (projectRoot: string | undefined, state: Preferences, options: BrowserLaunchOpts, automation: Automation): ElectronOpts {
const _this = this
Expand Down Expand Up @@ -179,7 +188,7 @@ export = {

_getAutomation,

async _render (url: string, automation: Automation, preferences, options: { projectRoot?: string, isTextTerminal: boolean }) {
async _render (url: string, automation: Automation, preferences, options: ElectronOpts) {
const win = Windows.create(options.projectRoot, preferences)

if (preferences.browser.isHeadless) {
Expand All @@ -192,7 +201,7 @@ export = {
win.maximize()
}

const launched = await this._launch(win, url, automation, preferences)
const launched = await this._launch(win, url, automation, preferences, options.video)

automation.use(await _getAutomation(win, preferences, automation))

Expand Down Expand Up @@ -225,7 +234,7 @@ export = {
return this._launch(win, url, automation, electronOptions)
},

async _launch (win: BrowserWindow, url: string, automation: Automation, options) {
async _launch (win: BrowserWindow, url: string, automation: Automation, options: ElectronOpts, videoOptions?: VideoBrowserOpt) {
if (options.show) {
menu.set({ withInternalDevTools: true })
}
Expand All @@ -239,9 +248,7 @@ export = {

this._attachDebugger(win.webContents)

let ua

ua = options.userAgent
const ua = options.userAgent

if (ua) {
this._setUserAgent(win.webContents, ua)
Expand Down Expand Up @@ -273,8 +280,9 @@ export = {
const cdpAutomation = await this._getAutomation(win, options, automation)

automation.use(cdpAutomation)

await Promise.all([
options.writeVideoFrame && cdpAutomation.startVideoRecording(options.writeVideoFrame),
videoOptions && recordVideo(cdpAutomation, videoOptions),
this._handleDownloads(win, options.downloadsFolder, automation),
])

Expand Down Expand Up @@ -480,10 +488,7 @@ export = {

debug('launching browser window to url: %s', url)

const win = await this._render(url, automation, preferences, {
projectRoot: options.projectRoot,
isTextTerminal: options.isTextTerminal,
})
const win = await this._render(url, automation, preferences, electronOptions)

await _installExtensions(win, launchOptions.extensions, electronOptions)

Expand Down
16 changes: 12 additions & 4 deletions packages/server/lib/browsers/firefox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Debug from 'debug'
import getPort from 'get-port'
import path from 'path'
import urlUtil from 'url'
import { debug as launcherDebug, launch, LaunchedBrowser } from '@packages/launcher/lib/browsers'
import { debug as launcherDebug, launch } from '@packages/launcher/lib/browsers'
import { doubleEscape } from '@packages/launcher/lib/windows'
import FirefoxProfile from 'firefox-profile'
import * as errors from '../errors'
Expand All @@ -18,9 +18,10 @@ import mimeDb from 'mime-db'
import { getRemoteDebuggingPort } from './protocol'
import type { BrowserCriClient } from './browser-cri-client'
import type { Automation } from '../automation'
import * as videoCapture from '../video_capture'
import { getCtx } from '@packages/data-context'
import { getError } from '@packages/errors'
import type { BrowserLaunchOpts, BrowserNewTabOpts } from '@packages/types'
import type { BrowserLaunchOpts, BrowserNewTabOpts, VideoBrowserOpt } from '@packages/types'

const debug = Debug('cypress:server:browsers:firefox')

Expand Down Expand Up @@ -379,6 +380,13 @@ export function connectToExisting () {
getCtx().onWarning(getError('UNEXPECTED_INTERNAL_ERROR', new Error('Attempting to connect to existing browser for Cypress in Cypress which is not yet implemented for firefox')))
}

async function recordVideo (videoOptions: VideoBrowserOpt) {
const videoController = await videoCapture.start({ ...videoOptions, webmInput: true })

videoOptions.onProjectCaptureVideoFrames(videoController.writeVideoFrame)
videoOptions.setVideoController(videoController)
}

export async function open (browser: Browser, url: string, options: BrowserLaunchOpts, automation: Automation): Promise<BrowserInstance> {
// see revision comment here https://wiki.mozilla.org/index.php?title=WebDriver/RemoteProtocol&oldid=1234946
const hasCdp = browser.majorVersion >= 86
Expand Down Expand Up @@ -456,6 +464,7 @@ export async function open (browser: Browser, url: string, options: BrowserLaunc
utils.ensureCleanCache(browser, options.isTextTerminal),
utils.writeExtension(browser, options.isTextTerminal, options.proxyUrl, options.socketIoRoute),
utils.executeBeforeBrowserLaunch(browser, defaultLaunchOptions, options),
options.video && recordVideo(options.video),
])

if (Array.isArray(launchOptions.extensions)) {
Expand Down Expand Up @@ -529,7 +538,7 @@ export async function open (browser: Browser, url: string, options: BrowserLaunc
// user can overwrite this default with these env vars or --height, --width arguments
MOZ_HEADLESS_WIDTH: '1280',
MOZ_HEADLESS_HEIGHT: '721',
}) as LaunchedBrowser & { browserCriClient: BrowserCriClient}
}) as unknown as BrowserInstance

try {
browserCriClient = await firefoxUtil.setup({ automation, extensions: launchOptions.extensions, url, foxdriverPort, marionettePort, remotePort, onError: options.onError, options })
Expand All @@ -543,7 +552,6 @@ export async function open (browser: Browser, url: string, options: BrowserLaunc
// monkey-patch the .kill method to that the CDP connection is closed
const originalBrowserKill = browserInstance.kill

/* @ts-expect-error */
browserInstance.kill = (...args) => {
debug('closing remote interface client')

Expand Down
Loading

0 comments on commit e3b1979

Please sign in to comment.