Skip to content
This repository has been archived by the owner on Feb 2, 2021. It is now read-only.

Commit

Permalink
Merge pull request #755 from telerik/vladimirov/new-api-debug
Browse files Browse the repository at this point in the history
Implement new events for debuggable WebViews detection
  • Loading branch information
rosen-vladimirov authored Jul 14, 2016
2 parents ea92098 + 198ae8e commit c3f6c7c
Show file tree
Hide file tree
Showing 12 changed files with 712 additions and 53 deletions.
214 changes: 209 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ Contains common infrastructure for CLIs - mainly AppBuilder and NativeScript.
Installation
===

Latest version: 0.17.3
Latest version: 0.18.0

Release date: 2016, July 12
Release date: 2016, July 14

### System Requirements

Expand Down Expand Up @@ -293,6 +293,14 @@ require("mobile-cli-lib").deviceEmitter.on("applicationInstalled", function(ide
});
```

* `applicationUninstalled` - Raised when application is removed from device. The callback has two arguments - `deviceIdentifier` and `applicationIdentifier`. <br/><br/>
Sample usage:
```JavaScript
require("mobile-cli-lib").deviceEmitter.on("applicationUninstalled", function(identifier, applicationIdentifier) {
console.log("Application " + applicationIdentifier + " has been uninstalled from device with id: " + identifier);
});
```

* `debuggableAppFound` - Raised when application on a device becomes available for debugging. The callback has one argument - `applicationInfo`. <br/><br/>
Sample usage:
```JavaScript
Expand Down Expand Up @@ -327,13 +335,71 @@ Sample result for `applicationInfo` will be:
}
```

* `applicationUninstalled` - Raised when application is removed from device. The callback has two arguments - `deviceIdentifier` and `applicationIdentifier`. <br/><br/>
* `debuggableViewFound` - Raised when a new debuggable WebView is found. The callback has three arguments - `deviceIdentifier`, `appIdentifier` and `webViewInfo`.

Sample usage:
```JavaScript
require("mobile-cli-lib").deviceEmitter.on("applicationUninstalled", function(identifier, applicationIdentifier) {
console.log("Application " + applicationIdentifier + " has been uninstalled from device with id: " + identifier);
require("mobile-cli-lib")
.deviceEmitter.on("debuggableViewFound", function(deviceIdentifier, appIdentifier, debuggableViewInfo) {
console.log("On device " + deviceIdentifier + " the application " + appIdentifier + " now has new WebView: " + debuggableViewInfo);
});
```
Sample result for `debuggableViewInfo` will be:
```JSON
{
"description": "",
"devtoolsFrontendUrl": "http://chrome-devtools-frontend.appspot.com/serve_rev/@211d45a5b74b06d12bb016f3c4d54095faf2646f/inspector.html?ws=127.0.0.1:53213/devtools/page/4050",
"id": "4050",
"title": "New tab",
"type": "page",
"url": "chrome-native://newtab/",
"webSocketDebuggerUrl": "ws://127.0.0.1:53213/devtools/page/4050"
}
```

* `debuggableViewLost` - Raised when a debuggable WebView is lost. The callback has three arguments - `deviceIdentifier`, `appIdentifier` and `webViewInfo`.

Sample usage:
```JavaScript
require("mobile-cli-lib")
.deviceEmitter.on("debuggableViewLost", function(deviceIdentifier, appIdentifier, debuggableViewInfo) {
console.log("On device " + deviceIdentifier + " the application " + appIdentifier + " now cannot debug WebView: " + debuggableViewInfo);
});
```
Sample result for `debuggableViewInfo` will be:
```JSON
{
"description": "",
"devtoolsFrontendUrl": "http://chrome-devtools-frontend.appspot.com/serve_rev/@211d45a5b74b06d12bb016f3c4d54095faf2646f/inspector.html?ws=127.0.0.1:53213/devtools/page/4050",
"id": "4050",
"title": "New tab",
"type": "page",
"url": "chrome-native://newtab/",
"webSocketDebuggerUrl": "ws://127.0.0.1:53213/devtools/page/4050"
}
```

* `debuggableViewChanged` - Raised when a property of debuggable WebView is changed, for example it's title. The callback has three arguments - `deviceIdentifier`, `appIdentifier` and `webViewInfo`.

Sample usage:
```JavaScript
require("mobile-cli-lib")
.deviceEmitter.on("debuggableViewChanged", function(deviceIdentifier, appIdentifier, debuggableViewInfo) {
console.log("On device " + deviceIdentifier + " the application " + appIdentifier + " has changes in WebView: " + debuggableViewInfo);
});
```
Sample result for `debuggableViewInfo` will be:
```JSON
{
"description": "",
"devtoolsFrontendUrl": "http://chrome-devtools-frontend.appspot.com/serve_rev/@211d45a5b74b06d12bb016f3c4d54095faf2646f/inspector.html?ws=127.0.0.1:53213/devtools/page/4050",
"id": "4050",
"title": "New tab 2",
"type": "page",
"url": "chrome-native://newtab/",
"webSocketDebuggerUrl": "ws://127.0.0.1:53213/devtools/page/4050"
}
```

* `companionAppInstalled` - Raised when application is removed from device. The callback has two arguments - `deviceIdentifier` and `framwork`. <br/><br/>
Sample usage:
Expand Down Expand Up @@ -548,6 +614,144 @@ Sample result will be:
}]]
```

* `getDebuggableApps(deviceIdentifiers: string[]): Promise<IDeviceApplicationInformation[]>[]` - This function checks the proc/net/unix file of each device from the deviceIdentifiers argument for web views connected to abstract ports and returns information about the applications.
```JavaScript
/**
* Describes basic information about application on device.
*/
interface IDeviceApplicationInformation {
/**
* The device identifier.
*/
deviceIdentifier: string;

/**
* The application identifier.
*/
appIdentifier: string;

/**
* The framework of the project (Cordova or NativeScript).
*/
framework: string;
}
```

Sample usage:
```JavaScript
Promise.all(require("mobile-cli-lib").devicesService.getDebuggableApps(["4df18f307d8a8f1b", "JJY5KBTW75TCHQUK"]))
.then(function(data) {
data.forEach(function(apps) {
console.log(apps);
});
}, function(err) {
console.log(err);
});
```
Sample result will be:
```JSON
[[{
"deviceIdentifier": "4df18f307d8a8f1b",
"appIdentifier": "com.telerik.Fitness",
"framework": "NativeScript"
}, {
"deviceIdentifier": "4df18f307d8a8f1b",
"appIdentifier": "com.telerik.livesynctest",
"framework": "Cordova"
}], [{
"deviceIdentifier": "JJY5KBTW75TCHQUK",
"appIdentifier": "com.telerik.PhotoAlbum",
"framework": "NativeScript"
}]]
```

* `getDebuggableViews(deviceIdentifier: string, appIdentifier: string): Promise<IDebugWebViewInfo[]>` - This function returns WebViews that can be debugged for specified application on specified device.
> NOTE: This method works only for Cordova based applications. DO NOT pass appIdentifier of NativeScript application.
```JavaScript
/**
* Describes information for WebView that can be debugged.
*/
interface IDebugWebViewInfo {
/**
* Short description of the view.
*/
description: string;

/**
* Url to the devtools.
* @example http://chrome-devtools-frontend.appspot.com/serve_rev/@211d45a5b74b06d12bb016f3c4d54095faf2646f/inspector.html?ws=127.0.0.1:53213/devtools/page/4024
*/
devtoolsFrontendUrl: string;

/**
* Unique identifier of the web view. Could be number or GUID.
* @example 4027
*/
id: string;

/**
* Title of the WebView.
* @example https://bit.ly/12345V is not available
*/
title: string;

/**
* Type of the WebView.
* @example page
*/
type: string;

/**
* URL loaded in the view.
* @example https://bit.ly/12345V
*/
url: string;

/**
* Debugger URL.
* @example ws://127.0.0.1:53213/devtools/page/4027
*/
webSocketDebuggerUrl: string;
}
```

Sample usage:
```JavaScript
require("mobile-cli-lib")
.devicesService
.getDebuggableViews("4df18f307d8a8f1b", "com.telerik.cordovaApp")
.then(function(data) {
console.log(data);
}, function(err) {
console.log(err);
});
```

Sample result will be:
```JSON
[{
"description": "",
"devtoolsFrontendUrl": "http://chrome-devtools-frontend.appspot.com/serve_rev/@211d45a5b74b06d12bb016f3c4d54095faf2646f/inspector.html?ws=127.0.0.1:53213/devtools/page/4050",
"id": "4050",
"title": "New tab",
"type": "page",
"url": "chrome-native://newtab/",
"webSocketDebuggerUrl": "ws://127.0.0.1:53213/devtools/page/4050"
},

{
"description": "",
"devtoolsFrontendUrl": "http://chrome-devtools-frontend.appspot.com/serve_rev/@211d45a5b74b06d12bb016f3c4d54095faf2646f/inspector.html?ws=127.0.0.1:53213/devtools/page/4032",
"id": "4032",
"title": "New tab",
"type": "page",
"url": "chrome-native://newtab/",
"webSocketDebuggerUrl": "ws://127.0.0.1:53213/devtools/page/4032"
}
]
```

### Module liveSyncService
> Stability: 1 - Could be changed due to some new requirments.
Expand Down
12 changes: 12 additions & 0 deletions appbuilder/device-emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ export class DeviceEmitter extends EventEmitter {
device.applicationManager.on("debuggableAppLost", (debuggableAppInfo: Mobile.IDeviceApplicationInformation) => {
this.emit("debuggableAppLost", debuggableAppInfo);
});

device.applicationManager.on("debuggableViewFound", (appIdentifier: string, debuggableWebViewInfo: Mobile.IDebugWebViewInfo) => {
this.emit("debuggableViewFound", device.deviceInfo.identifier, appIdentifier, debuggableWebViewInfo);
});

device.applicationManager.on("debuggableViewLost", (appIdentifier: string, debuggableWebViewInfo: Mobile.IDebugWebViewInfo) => {
this.emit("debuggableViewLost", device.deviceInfo.identifier, appIdentifier, debuggableWebViewInfo);
});

device.applicationManager.on("debuggableViewChanged", (appIdentifier: string, debuggableWebViewInfo: Mobile.IDebugWebViewInfo) => {
this.emit("debuggableViewChanged", device.deviceInfo.identifier, appIdentifier, debuggableWebViewInfo);
});
}

private checkCompanionAppChanged(device: Mobile.IDevice, applicationName: string, eventName: string): void {
Expand Down
57 changes: 56 additions & 1 deletion definitions/mobile.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ declare module Mobile {
getApplicationInfo(applicationIdentifier: string): IFuture<Mobile.IApplicationInfo>;
tryStartApplication(appIdentifier: string, framework?: string): IFuture<void>;
getDebuggableApps(): IFuture<Mobile.IDeviceApplicationInformation[]>;
getDebuggableAppViews(appIdentifiers: string[]): IFuture<IDictionary<Mobile.IDebugWebViewInfo[]>>;
}

/**
Expand Down Expand Up @@ -300,7 +301,7 @@ declare module Mobile {
getDeviceByIdentifier(identifier: string): Mobile.IDevice;
mapAbstractToTcpPort(deviceIdentifier: string, appIdentifier: string): IFuture<string>;
detectCurrentlyAttachedDevices(): IFuture<void>;
startEmulator(platform?: string): IFuture<void>;
startEmulator(platform?: string): IFuture<void>;
}

/**
Expand All @@ -321,6 +322,60 @@ declare module Mobile {
* @return {Mobile.IDeviceApplicationInformation[]} Returns array of applications information for the applications which are available for debugging.
*/
getDebuggableApps(deviceIdentifier: string): IFuture<Mobile.IDeviceApplicationInformation[]>;

/**
* Gets all mapped abstract to tcp ports for specified device id and application identifiers.
* @param deviceIdentifier {string} The identifier of the device.
* @param appIdentifiers {string[]} Application identifiers that will be checked.
* @return {IFuture<IDictionary<number>>} Dictionary, where the keys are app identifiers and the values are local ports.
*/
getMappedAbstractToTcpPorts(deviceIdentifier: string, appIdentifiers: string[]): IFuture<IDictionary<number>>;
}

/**
* Describes information for WebView that can be debugged.
*/
interface IDebugWebViewInfo {
/**
* Short description of the view.
*/
description: string;

/**
* Url to the devtools.
* @example http://chrome-devtools-frontend.appspot.com/serve_rev/@211d45a5b74b06d12bb016f3c4d54095faf2646f/inspector.html?ws=127.0.0.1:53213/devtools/page/4024
*/
devtoolsFrontendUrl: string;

/**
* Unique identifier of the web view. Could be number or GUID.
* @example 4027
*/
id: string;

/**
* Title of the WebView.
* @example https://bit.ly/12345V is not available
*/
title: string;

/**
* Type of the WebView.
* @example page
*/
type: string;

/**
* URL loaded in the view.
* @example https://bit.ly/12345V
*/
url: string;

/**
* Debugger URL.
* @example ws://127.0.0.1:53213/devtools/page/4027
*/
webSocketDebuggerUrl: string;
}

interface IiTunesValidator {
Expand Down
25 changes: 25 additions & 0 deletions mobile/android/android-application-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export class AndroidApplicationManager extends ApplicationManagerBase {
private $options: ICommonOptions,
private $logcatHelper: Mobile.ILogcatHelper,
private $androidProcessService: Mobile.IAndroidProcessService,
private $httpClient: Server.IHttpClient,
$logger: ILogger) {
super($logger);
}
Expand Down Expand Up @@ -83,6 +84,30 @@ export class AndroidApplicationManager extends ApplicationManagerBase {
return this.$androidProcessService.getDebuggableApps(this.identifier);
}

public getDebuggableAppViews(appIdentifiers: string[]): IFuture<IDictionary<Mobile.IDebugWebViewInfo[]>> {
return ((): IDictionary<Mobile.IDebugWebViewInfo[]> => {
let mappedAppIdentifierPorts = this.$androidProcessService.getMappedAbstractToTcpPorts(this.identifier, appIdentifiers).wait(),
applicationViews: IDictionary<Mobile.IDebugWebViewInfo[]> = {};

_.each(mappedAppIdentifierPorts, (port: number, appIdentifier: string) => {
applicationViews[appIdentifier] = [];
let localAddress = `http://127.0.0.1:${port}/json`;

try {
if (port) {
let apps = this.$httpClient.httpRequest(localAddress).wait().body;
applicationViews[appIdentifier] = JSON.parse(apps);
}
} catch (err) {
this.$logger.trace(`Error while checking ${localAddress}. Error is: ${err.message}`);
}
});

return applicationViews;

}).future<IDictionary<Mobile.IDebugWebViewInfo[]>>()();
}

private getStartPackageActivity(framework?: string): string {
framework = framework || "";
return startPackageActivityNames[framework.toLowerCase()] || this.$staticConfig.START_PACKAGE_ACTIVITY_NAME;
Expand Down
Loading

0 comments on commit c3f6c7c

Please sign in to comment.