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

Commit

Permalink
Implement new events for debuggable WebViews detection
Browse files Browse the repository at this point in the history
Implement `debuggableViewFound`, `debuggableViewLost` and `debuggableViewChanged` events that will be raised when there's a change in application's debuggable views.
Add new method to Public API: `getDebuggableViews` which will return debuggable views per application on device.
  • Loading branch information
rosen-vladimirov committed Jul 14, 2016
1 parent ea92098 commit 7680f28
Show file tree
Hide file tree
Showing 10 changed files with 488 additions and 45 deletions.
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
20 changes: 20 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,25 @@ 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) => {
if (port) {
let apps = this.$httpClient.httpRequest(`http://127.0.0.1:${port}/json`).wait().body;
applicationViews[appIdentifier] = JSON.parse(apps);
} else {
applicationViews[appIdentifier] = [];
}
});

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
41 changes: 40 additions & 1 deletion mobile/application-manager-base.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { EventEmitter } from "events";
import {TARGET_FRAMEWORK_IDENTIFIERS} from "../constants";

export abstract class ApplicationManagerBase extends EventEmitter implements Mobile.IDeviceApplicationManager {
private lastInstalledAppIdentifiers: string[];
private lastAvailableDebuggableApps: Mobile.IDeviceApplicationInformation[];
private lastAvailableDebuggableAppViews: IDictionary<Mobile.IDebugWebViewInfo[]> = {};

constructor(protected $logger: ILogger) {
super();
Expand Down Expand Up @@ -82,6 +84,7 @@ export abstract class ApplicationManagerBase extends EventEmitter implements Mob
public abstract getApplicationInfo(applicationIdentifier: string): IFuture<Mobile.IApplicationInfo>;
public abstract canStartApplication(): boolean;
public abstract getDebuggableApps(): IFuture<Mobile.IDeviceApplicationInformation[]>;
public abstract getDebuggableAppViews(appIdentifiers: string[]): IFuture<IDictionary<Mobile.IDebugWebViewInfo[]>>;

private checkForAvailableDebuggableAppsChanges(): IFuture<void> {
return (() => {
Expand All @@ -94,7 +97,43 @@ export abstract class ApplicationManagerBase extends EventEmitter implements Mob
this.lastAvailableDebuggableApps = currentlyAvailableDebuggableApps;

_.each(newAvailableDebuggableApps, (appInfo: Mobile.IDeviceApplicationInformation) => this.emit("debuggableAppFound", appInfo));
_.each(notAvailableAppsForDebugging, (appInfo: Mobile.IDeviceApplicationInformation) => this.emit("debuggableAppLost", appInfo));
_.each(notAvailableAppsForDebugging, (appInfo: Mobile.IDeviceApplicationInformation) => {
this.emit("debuggableAppLost", appInfo);

if (_.has(this.lastAvailableDebuggableAppViews, appInfo.appIdentifier)) {
// Prevent emitting debuggableViewLost when application cannot be debugged anymore.
delete this.lastAvailableDebuggableAppViews[appInfo.appIdentifier];
}
});

let cordovaDebuggableAppIdentifiers = _(currentlyAvailableDebuggableApps)
.filter(c => c.framework === TARGET_FRAMEWORK_IDENTIFIERS.Cordova)
.map(c => c.appIdentifier)
.value();

let currentlyAvailableAppViews = this.getDebuggableAppViews(cordovaDebuggableAppIdentifiers).wait();

_.each(currentlyAvailableAppViews, (currentlyAvailableViews, appIdentifier) => {
let previouslyAvailableViews = this.lastAvailableDebuggableAppViews[appIdentifier];

let newAvailableViews = _.differenceBy(currentlyAvailableViews, previouslyAvailableViews, "id");
let notAvailableViews = _.differenceBy(previouslyAvailableViews, currentlyAvailableViews, "id");

_.each(notAvailableViews, debugWebViewInfo => this.emit("debuggableViewLost", appIdentifier, debugWebViewInfo));
_.each(newAvailableViews, debugWebViewInfo => this.emit("debuggableViewFound", appIdentifier, debugWebViewInfo));

// Determine which of the views had changed since last check and raise debuggableViewChanged event for them:
let keptViews = _.differenceBy(currentlyAvailableViews, newAvailableViews, "id");
_.each(keptViews, view => {
let previousTimeViewInfo = _.find(previouslyAvailableViews, previousView => previousView.id === view.id);
if (!_.isEqual(view, previousTimeViewInfo)) {
this.emit("debuggableViewChanged", appIdentifier, view);
}
});

this.lastAvailableDebuggableAppViews[appIdentifier] = currentlyAvailableViews;
});

}).future<void>()();
}
}
5 changes: 5 additions & 0 deletions mobile/ios/device/ios-application-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ export class IOSApplicationManager extends ApplicationManagerBase {
return Future.fromResult([]);
}

public getDebuggableAppViews(appIdentifiers: string[]): IFuture<IDictionary<Mobile.IDebugWebViewInfo[]>> {
// Implement when we can find debuggable applications for iOS.
return Future.fromResult(null);
}

private lookupApplications(): IDictionary<Mobile.IDeviceApplication> {
let func = () => {
let dictionaryPointer = ref.alloc(CoreTypes.cfDictionaryRef);
Expand Down
5 changes: 5 additions & 0 deletions mobile/ios/simulator/ios-simulator-application-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,9 @@ export class IOSSimulatorApplicationManager extends ApplicationManagerBase {
public getDebuggableApps(): IFuture<Mobile.IDeviceApplicationInformation[]> {
return Future.fromResult([]);
}

public getDebuggableAppViews(appIdentifiers: string[]): IFuture<IDictionary<Mobile.IDebugWebViewInfo[]>> {
// Implement when we can find debuggable applications for iOS.
return Future.fromResult(null);
}
}
Loading

0 comments on commit 7680f28

Please sign in to comment.