mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat(adb): implement push (#4697)
This commit is contained in:
parent
b8112dedca
commit
f89dcc7ba7
1
android-types-internal.d.ts
vendored
1
android-types-internal.d.ts
vendored
@ -30,6 +30,7 @@ export interface AndroidDevice<BrowserContextOptions, BrowserContext, Page> exte
|
|||||||
shell(command: string): Promise<Buffer>;
|
shell(command: string): Promise<Buffer>;
|
||||||
open(command: string): Promise<AndroidSocket>;
|
open(command: string): Promise<AndroidSocket>;
|
||||||
installApk(file: string | Buffer, options?: { args?: string[] }): Promise<void>;
|
installApk(file: string | Buffer, options?: { args?: string[] }): Promise<void>;
|
||||||
|
push(file: string | Buffer, path: string, options?: { mode?: number }): Promise<void>;
|
||||||
launchBrowser(options?: BrowserContextOptions & { packageName?: string }): Promise<BrowserContext>;
|
launchBrowser(options?: BrowserContextOptions & { packageName?: string }): Promise<BrowserContext>;
|
||||||
close(): Promise<void>;
|
close(): Promise<void>;
|
||||||
|
|
||||||
|
|||||||
@ -213,7 +213,13 @@ export class AndroidDevice extends ChannelOwner<channels.AndroidDeviceChannel, c
|
|||||||
|
|
||||||
async installApk(file: string | Buffer, options?: { args: string[] }): Promise<void> {
|
async installApk(file: string | Buffer, options?: { args: string[] }): Promise<void> {
|
||||||
return this._wrapApiCall('androidDevice.installApk', async () => {
|
return this._wrapApiCall('androidDevice.installApk', async () => {
|
||||||
await this._channel.installApk({ file: await readApkFile(file), args: options && options.args });
|
await this._channel.installApk({ file: await loadFile(file), args: options && options.args });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async push(file: string | Buffer, path: string, options?: { mode: number }): Promise<void> {
|
||||||
|
return this._wrapApiCall('androidDevice.push', async () => {
|
||||||
|
await this._channel.push({ file: await loadFile(file), path, mode: options ? options.mode : undefined });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +267,7 @@ export class AndroidSocket extends ChannelOwner<channels.AndroidSocketChannel, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readApkFile(file: string | Buffer): Promise<string> {
|
async function loadFile(file: string | Buffer): Promise<string> {
|
||||||
if (isString(file))
|
if (isString(file))
|
||||||
return (await util.promisify(fs.readFile)(file)).toString('base64');
|
return (await util.promisify(fs.readFile)(file)).toString('base64');
|
||||||
return file.toString('base64');
|
return file.toString('base64');
|
||||||
|
|||||||
@ -149,6 +149,10 @@ export class AndroidDeviceDispatcher extends Dispatcher<AndroidDevice, channels.
|
|||||||
await this._object.installApk(Buffer.from(params.file, 'base64'), { args: params.args });
|
await this._object.installApk(Buffer.from(params.file, 'base64'), { args: params.args });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async push(params: channels.AndroidDevicePushParams) {
|
||||||
|
await this._object.push(Buffer.from(params.file, 'base64'), params.path, params.mode);
|
||||||
|
}
|
||||||
|
|
||||||
async launchBrowser(params: channels.AndroidDeviceLaunchBrowserParams): Promise<channels.AndroidDeviceLaunchBrowserResult> {
|
async launchBrowser(params: channels.AndroidDeviceLaunchBrowserParams): Promise<channels.AndroidDeviceLaunchBrowserResult> {
|
||||||
const context = await this._object.launchBrowser(params.packageName, params);
|
const context = await this._object.launchBrowser(params.packageName, params);
|
||||||
return { context: new BrowserContextDispatcher(this._scope, context) };
|
return { context: new BrowserContextDispatcher(this._scope, context) };
|
||||||
|
|||||||
@ -2471,6 +2471,7 @@ export interface AndroidDeviceChannel extends Channel {
|
|||||||
open(params: AndroidDeviceOpenParams, metadata?: Metadata): Promise<AndroidDeviceOpenResult>;
|
open(params: AndroidDeviceOpenParams, metadata?: Metadata): Promise<AndroidDeviceOpenResult>;
|
||||||
shell(params: AndroidDeviceShellParams, metadata?: Metadata): Promise<AndroidDeviceShellResult>;
|
shell(params: AndroidDeviceShellParams, metadata?: Metadata): Promise<AndroidDeviceShellResult>;
|
||||||
installApk(params: AndroidDeviceInstallApkParams, metadata?: Metadata): Promise<AndroidDeviceInstallApkResult>;
|
installApk(params: AndroidDeviceInstallApkParams, metadata?: Metadata): Promise<AndroidDeviceInstallApkResult>;
|
||||||
|
push(params: AndroidDevicePushParams, metadata?: Metadata): Promise<AndroidDevicePushResult>;
|
||||||
setDefaultTimeoutNoReply(params: AndroidDeviceSetDefaultTimeoutNoReplyParams, metadata?: Metadata): Promise<AndroidDeviceSetDefaultTimeoutNoReplyResult>;
|
setDefaultTimeoutNoReply(params: AndroidDeviceSetDefaultTimeoutNoReplyParams, metadata?: Metadata): Promise<AndroidDeviceSetDefaultTimeoutNoReplyResult>;
|
||||||
connectToWebView(params: AndroidDeviceConnectToWebViewParams, metadata?: Metadata): Promise<AndroidDeviceConnectToWebViewResult>;
|
connectToWebView(params: AndroidDeviceConnectToWebViewParams, metadata?: Metadata): Promise<AndroidDeviceConnectToWebViewResult>;
|
||||||
close(params?: AndroidDeviceCloseParams, metadata?: Metadata): Promise<AndroidDeviceCloseResult>;
|
close(params?: AndroidDeviceCloseParams, metadata?: Metadata): Promise<AndroidDeviceCloseResult>;
|
||||||
@ -2757,6 +2758,15 @@ export type AndroidDeviceInstallApkOptions = {
|
|||||||
args?: string[],
|
args?: string[],
|
||||||
};
|
};
|
||||||
export type AndroidDeviceInstallApkResult = void;
|
export type AndroidDeviceInstallApkResult = void;
|
||||||
|
export type AndroidDevicePushParams = {
|
||||||
|
file: Binary,
|
||||||
|
path: string,
|
||||||
|
mode?: number,
|
||||||
|
};
|
||||||
|
export type AndroidDevicePushOptions = {
|
||||||
|
mode?: number,
|
||||||
|
};
|
||||||
|
export type AndroidDevicePushResult = void;
|
||||||
export type AndroidDeviceSetDefaultTimeoutNoReplyParams = {
|
export type AndroidDeviceSetDefaultTimeoutNoReplyParams = {
|
||||||
timeout: number,
|
timeout: number,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2312,6 +2312,12 @@ AndroidDevice:
|
|||||||
type: array?
|
type: array?
|
||||||
items: string
|
items: string
|
||||||
|
|
||||||
|
push:
|
||||||
|
parameters:
|
||||||
|
file: binary
|
||||||
|
path: string
|
||||||
|
mode: number?
|
||||||
|
|
||||||
setDefaultTimeoutNoReply:
|
setDefaultTimeoutNoReply:
|
||||||
parameters:
|
parameters:
|
||||||
timeout: number
|
timeout: number
|
||||||
|
|||||||
@ -1039,6 +1039,11 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
|||||||
file: tBinary,
|
file: tBinary,
|
||||||
args: tOptional(tArray(tString)),
|
args: tOptional(tArray(tString)),
|
||||||
});
|
});
|
||||||
|
scheme.AndroidDevicePushParams = tObject({
|
||||||
|
file: tBinary,
|
||||||
|
path: tString,
|
||||||
|
mode: tOptional(tNumber),
|
||||||
|
});
|
||||||
scheme.AndroidDeviceSetDefaultTimeoutNoReplyParams = tObject({
|
scheme.AndroidDeviceSetDefaultTimeoutNoReplyParams = tObject({
|
||||||
timeout: tNumber,
|
timeout: tNumber,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -287,6 +287,30 @@ export class AndroidDevice extends EventEmitter {
|
|||||||
debug('pw:android')('Written driver bytes: ' + success);
|
debug('pw:android')('Written driver bytes: ' + success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async push(content: Buffer, path: string, mode = 0o644): Promise<void> {
|
||||||
|
const socket = await this._backend.open(`sync:`);
|
||||||
|
const sendHeader = async (command: string, length: number) => {
|
||||||
|
const buffer = Buffer.alloc(command.length + 4);
|
||||||
|
buffer.write(command, 0);
|
||||||
|
buffer.writeUInt32LE(length, command.length);
|
||||||
|
await socket.write(buffer);
|
||||||
|
};
|
||||||
|
const send = async (command: string, data: Buffer) => {
|
||||||
|
await sendHeader(command, data.length);
|
||||||
|
await socket.write(data);
|
||||||
|
};
|
||||||
|
await send('SEND', Buffer.from(`${path},${mode}`));
|
||||||
|
const maxChunk = 65535;
|
||||||
|
for (let i = 0; i < content.length; i += maxChunk)
|
||||||
|
await send('DATA', content.slice(i, i + maxChunk));
|
||||||
|
await sendHeader('DONE', (Date.now() / 1000) | 0);
|
||||||
|
const result = await new Promise<Buffer>(f => socket.once('data', f));
|
||||||
|
const code = result.slice(0, 4).toString();
|
||||||
|
if (code !== 'OKAY')
|
||||||
|
throw new Error('Could not push: ' + code);
|
||||||
|
await socket.close();
|
||||||
|
}
|
||||||
|
|
||||||
private async _refreshWebViews() {
|
private async _refreshWebViews() {
|
||||||
const sockets = (await this._backend.runCommand(`shell:cat /proc/net/unix | grep webview_devtools_remote`)).toString().split('\n');
|
const sockets = (await this._backend.runCommand(`shell:cat /proc/net/unix | grep webview_devtools_remote`)).toString().split('\n');
|
||||||
if (this._isClosed)
|
if (this._isClosed)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user