mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat(scopes): make page a scope (#4385)
This commit is contained in:
parent
58b5872ecb
commit
2158d6d073
1
.gitignore
vendored
1
.gitignore
vendored
@ -16,3 +16,4 @@ lib/
|
|||||||
jest-report.json
|
jest-report.json
|
||||||
drivers/
|
drivers/
|
||||||
/docs/api.json
|
/docs/api.json
|
||||||
|
.android-sdk/
|
||||||
|
@ -18,7 +18,7 @@ import * as debug from 'debug';
|
|||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import * as stream from 'stream';
|
import * as stream from 'stream';
|
||||||
import * as ws from 'ws';
|
import * as ws from 'ws';
|
||||||
import { makeWaitForNextTask } from '../../utils/utils';
|
import { createGuid, makeWaitForNextTask } from '../../utils/utils';
|
||||||
|
|
||||||
export interface Backend {
|
export interface Backend {
|
||||||
devices(): Promise<DeviceBackend[]>;
|
devices(): Promise<DeviceBackend[]>;
|
||||||
@ -69,20 +69,13 @@ export class AndroidDevice {
|
|||||||
async launchBrowser(packageName: string): Promise<AndroidBrowser> {
|
async launchBrowser(packageName: string): Promise<AndroidBrowser> {
|
||||||
debug('pw:android')('Force-stopping', packageName);
|
debug('pw:android')('Force-stopping', packageName);
|
||||||
await this.backend.runCommand(`shell:am force-stop ${packageName}`);
|
await this.backend.runCommand(`shell:am force-stop ${packageName}`);
|
||||||
const hasDefaultSocket = !!(await this.backend.runCommand(`shell:cat /proc/net/unix | grep chrome_devtools_remote$`));
|
|
||||||
debug('pw:android')('Starting', packageName);
|
const socketName = createGuid();
|
||||||
|
const commandLine = `_ --disable-fre --no-default-browser-check --no-first-run --remote-debugging-socket-name=${socketName}`;
|
||||||
|
debug('pw:android')('Starting', packageName, commandLine);
|
||||||
|
await this.backend.runCommand(`shell:echo "${commandLine}" > /data/local/tmp/chrome-command-line`);
|
||||||
await this.backend.runCommand(`shell:am start -n ${packageName}/com.google.android.apps.chrome.Main about:blank`);
|
await this.backend.runCommand(`shell:am start -n ${packageName}/com.google.android.apps.chrome.Main about:blank`);
|
||||||
let pid = 0;
|
|
||||||
debug('pw:android')('Polling pid for', packageName);
|
|
||||||
while (!pid) {
|
|
||||||
const ps = (await this.backend.runCommand(`shell:ps -A | grep ${packageName}`)).split('\n');
|
|
||||||
const proc = ps.find(line => line.endsWith(packageName));
|
|
||||||
if (proc)
|
|
||||||
pid = +proc.replace(/\s+/g, ' ').split(' ')[1];
|
|
||||||
await new Promise(f => setTimeout(f, 100));
|
|
||||||
}
|
|
||||||
debug('pw:android')('PID=' + pid);
|
|
||||||
const socketName = hasDefaultSocket ? `chrome_devtools_remote_${pid}` : 'chrome_devtools_remote';
|
|
||||||
debug('pw:android')('Polling for socket', socketName);
|
debug('pw:android')('Polling for socket', socketName);
|
||||||
while (true) {
|
while (true) {
|
||||||
const net = await this.backend.runCommand(`shell:cat /proc/net/unix | grep ${socketName}$`);
|
const net = await this.backend.runCommand(`shell:cat /proc/net/unix | grep ${socketName}$`);
|
||||||
@ -91,7 +84,7 @@ export class AndroidDevice {
|
|||||||
await new Promise(f => setTimeout(f, 100));
|
await new Promise(f => setTimeout(f, 100));
|
||||||
}
|
}
|
||||||
debug('pw:android')('Got the socket, connecting');
|
debug('pw:android')('Got the socket, connecting');
|
||||||
const browser = new AndroidBrowser(this, packageName, socketName, pid);
|
const browser = new AndroidBrowser(this, packageName, socketName);
|
||||||
await browser._open();
|
await browser._open();
|
||||||
return browser;
|
return browser;
|
||||||
}
|
}
|
||||||
@ -104,7 +97,6 @@ export class AndroidDevice {
|
|||||||
export class AndroidBrowser extends EventEmitter {
|
export class AndroidBrowser extends EventEmitter {
|
||||||
readonly device: AndroidDevice;
|
readonly device: AndroidDevice;
|
||||||
readonly socketName: string;
|
readonly socketName: string;
|
||||||
readonly pid: number;
|
|
||||||
private _socket: SocketBackend | undefined;
|
private _socket: SocketBackend | undefined;
|
||||||
private _receiver: stream.Writable;
|
private _receiver: stream.Writable;
|
||||||
private _waitForNextTask = makeWaitForNextTask();
|
private _waitForNextTask = makeWaitForNextTask();
|
||||||
@ -112,12 +104,11 @@ export class AndroidBrowser extends EventEmitter {
|
|||||||
onclose?: () => void;
|
onclose?: () => void;
|
||||||
private _packageName: string;
|
private _packageName: string;
|
||||||
|
|
||||||
constructor(device: AndroidDevice, packageName: string, socketName: string, pid: number) {
|
constructor(device: AndroidDevice, packageName: string, socketName: string) {
|
||||||
super();
|
super();
|
||||||
this._packageName = packageName;
|
this._packageName = packageName;
|
||||||
this.device = device;
|
this.device = device;
|
||||||
this.socketName = socketName;
|
this.socketName = socketName;
|
||||||
this.pid = pid;
|
|
||||||
this._receiver = new (ws as any).Receiver() as stream.Writable;
|
this._receiver = new (ws as any).Receiver() as stream.Writable;
|
||||||
this._receiver.on('message', message => {
|
this._receiver.on('message', message => {
|
||||||
this._waitForNextTask(() => {
|
this._waitForNextTask(() => {
|
||||||
|
27
utils/avd_install.sh
Executable file
27
utils/avd_install.sh
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SDKDIR=$PWD/.android-sdk
|
||||||
|
export ANDROID_SDK_ROOT=${SDKDIR}
|
||||||
|
export ANDROID_HOME=${SDKDIR}
|
||||||
|
export ANDROID_AVD_HOME=${SDKDIR}/avd
|
||||||
|
|
||||||
|
mkdir ${SDKDIR}
|
||||||
|
mkdir ${SDKDIR}/cmdline-tools
|
||||||
|
|
||||||
|
echo Downloading Android SDK...
|
||||||
|
cd ${SDKDIR}/cmdline-tools
|
||||||
|
curl https://dl.google.com/android/repository/commandlinetools-mac-6858069_latest.zip -o commandlinetools-mac-6858069_latest.zip
|
||||||
|
unzip commandlinetools-mac-6858069_latest.zip
|
||||||
|
mv cmdline-tools latest
|
||||||
|
|
||||||
|
echo Installing emulator...
|
||||||
|
yes | ${SDKDIR}/cmdline-tools/latest/bin/sdkmanager platform-tools emulator
|
||||||
|
|
||||||
|
echo Installing system image...
|
||||||
|
${SDKDIR}/cmdline-tools/latest/bin/sdkmanager "system-images;android-30;google_apis;x86"
|
||||||
|
|
||||||
|
echo Installing platform SDK...
|
||||||
|
${SDKDIR}/cmdline-tools/latest/bin/sdkmanager "platforms;android-30"
|
||||||
|
|
||||||
|
echo Starting ADB...
|
||||||
|
${SDKDIR}/platform-tools/adb devices
|
9
utils/avd_recreate.sh
Executable file
9
utils/avd_recreate.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SDKDIR=$PWD/.android-sdk
|
||||||
|
export ANDROID_SDK_ROOT=${SDKDIR}
|
||||||
|
export ANDROID_HOME=${SDKDIR}
|
||||||
|
export ANDROID_AVD_HOME=${SDKDIR}/avd
|
||||||
|
|
||||||
|
${SDKDIR}/cmdline-tools/latest/bin/avdmanager delete avd --name android30
|
||||||
|
echo -ne '\n' | ${SDKDIR}/cmdline-tools/latest/bin/avdmanager create avd --name android30 --device pixel_4_xl --package "system-images;android-30;google_apis;x86"
|
8
utils/avd_start.sh
Executable file
8
utils/avd_start.sh
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SDKDIR=$PWD/.android-sdk
|
||||||
|
export ANDROID_SDK_ROOT=${SDKDIR}
|
||||||
|
export ANDROID_HOME=${SDKDIR}
|
||||||
|
export ANDROID_AVD_HOME=${SDKDIR}/avd
|
||||||
|
|
||||||
|
${SDKDIR}/emulator/emulator -avd android30
|
63
utils/avd_test.js
Normal file
63
utils/avd_test.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { _clank } = require('..');
|
||||||
|
const assert = require('assert');
|
||||||
|
const childProcess = require('child_process');
|
||||||
|
const path = require('path');
|
||||||
|
const readline = require('readline');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
console.error('Timed out starting emulator');
|
||||||
|
process.exit(1);
|
||||||
|
}, 60000);
|
||||||
|
const proc = childProcess.spawn(path.join(process.cwd(), '.android-sdk/emulator/emulator'), ['-no-window', '-avd', 'android30', '-verbose'], {
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
ANDROID_SDK_ROOT: path.join(process.cwd(), '.android-sdk'),
|
||||||
|
ANDROID_HOME: path.join(process.cwd(), '.android-sdk'),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
proc.stdout.on('data', data => console.log(data.toString()));
|
||||||
|
proc.stderr.on('data', data => console.log(data.toString()));
|
||||||
|
await waitForLine(proc, /boot completed/);
|
||||||
|
|
||||||
|
const context = await _clank.launchPersistentContext('');
|
||||||
|
const [page] = context.pages();
|
||||||
|
await page.goto('data:text/html,<title>Hello world</title>');
|
||||||
|
assert(await page.title() === 'Hello world');
|
||||||
|
await context.close();
|
||||||
|
process.exit(0);
|
||||||
|
})();
|
||||||
|
|
||||||
|
async function waitForLine(proc, regex) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const rl = readline.createInterface({ input: proc.stdout });
|
||||||
|
const failError = new Error('Process failed to launch!');
|
||||||
|
rl.on('line', onLine);
|
||||||
|
rl.on('close', reject.bind(null, failError));
|
||||||
|
proc.on('exit', reject.bind(null, failError));
|
||||||
|
proc.on('error', reject.bind(null, failError));
|
||||||
|
|
||||||
|
function onLine(line) {
|
||||||
|
const match = line.match(regex);
|
||||||
|
if (!match)
|
||||||
|
return;
|
||||||
|
resolve(match);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user