Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[main][debug tool] enable check compressed data #2465

Merged
merged 10 commits into from
Jan 17, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function createDataSource(configuration: IConfiguration): IDataSource {
}

if (!urls || urls.length === 0) {
urls = ["*://*.microsoft.com/OneCollector/*", "*://*.visualstudio.com/v2/track*", "*://*.eastus-8.in.applicationinsights.azure.com/v2/track*"];
urls = ["*://*.microsoft.com/OneCollector/*", "*://*.visualstudio.com/v2/track*", "*://*.applicationinsights.azure.com/v2/track*"];
}
}

Expand Down
96 changes: 80 additions & 16 deletions tools/chrome-debug-extension/src/dataSources/defaultDataSource.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { createAsyncRejectedPromise, doAwait, IPromise } from "@nevware21/ts-async";
import { MessageSource, MessageType } from "../Enums";
import { IMessage } from "../interfaces/IMessage";
import { IDataSource } from "./IDataSource";
Expand Down Expand Up @@ -51,27 +52,90 @@ export class DefaultDataSource implements IDataSource {
_self.removeListener = (id: number): boolean => {
return listeners.delete(id);
};

function isGzip(data: ArrayBuffer): boolean {
const checkGzip = new Uint8Array(data);
if (checkGzip[0] === 0x1F && checkGzip[1] === 0x8B) {
console.log("This is gzipped.");
siyuniu-ms marked this conversation as resolved.
Show resolved Hide resolved
return true;
}
return false;
}

function decompressEvents(compressedString: ArrayBuffer): IPromise<Uint8Array> {
const DecompressionStream = (window as any).DecompressionStream;

if (DecompressionStream && typeof DecompressionStream !== "undefined") {
// If DecompressionStream is available, use it
const binaryData = new Uint8Array(compressedString);

// Create a ReadableStream from the Uint8Array
const compressedReadableStream = new ReadableStream({
start(controller) {
controller.enqueue(binaryData);
controller.close();
}
});

// Pipe through the DecompressionStream (gzip)
const decompressedReadableStream = compressedReadableStream.pipeThrough(
new DecompressionStream("gzip")
);

// Read the decompressed stream and return a Uint8Array
return new Response(decompressedReadableStream)
.arrayBuffer()
.then((decompressedBuffer) => {
return new Uint8Array(decompressedBuffer); // Return the decompressed data as Uint8Array
});
} else {
return createAsyncRejectedPromise(new Error("DecompressionStream is not supported in this environment."));
}
}

function processEvents(events: string[] | null, details: chrome.webRequest.WebRequestBodyDetails): void {
if (events) {
for (let i = events.length - 1; i >= 0; i--) {
try {
const event = JSON.parse(events[i]);
if (event !== undefined) {
if (Array.isArray(event)) {
for (const subEvent of event) {
_handleMessage(subEvent, details);
}
} else {
_handleMessage(event, details);
}
}
} catch (e) {
// Ignore
}
}
}
}

function _processWebRequest(details: chrome.webRequest.WebRequestBodyDetails): void {
if (details && (details.type === "xmlhttprequest" || details.type === "ping")) {
const events = details.requestBody && _convertToStringArray(details.requestBody.raw);
if (events) {
for (let i = events.length - 1; i >= 0; i--) {
try {
const event = JSON.parse(events[i]);
if (event !== undefined) {
if (Array.isArray(event)) {
for (const subEvent of event) {
_handleMessage(subEvent, details);
}
} else {
_handleMessage(event, details);
}
if (details.requestBody && details.requestBody.raw) {
let gzipped = isGzip(details.requestBody.raw[0].bytes as ArrayBuffer);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While its good to "validate" that it's really gzipped, we should be checking the Encoding header and only attempt this check if it was reported as encoded as gzipped.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requestHeaders is only available under onBeforeSendHeaders func

console.log("Gzipped: " + gzipped);
var events: string[] | null;
if (gzipped) {
doAwait(decompressEvents(details.requestBody.raw[0].bytes as ArrayBuffer), (decompressedData) => {
if (decompressedData) {
// details.requestBody.raw[0].bytes = decompressedData;
console.log("After decompression:", decompressedData);
events = _convertToStringArray([{bytes: decompressedData}]);
processEvents(events, details);
} else {
console.error("Decompression failed.");
}
} catch (e) {
// Ignore
}
});
} else {
events = details.requestBody && _convertToStringArray(details.requestBody.raw);
processEvents(events, details);
}

}
}
}
Expand Down
1 change: 1 addition & 0 deletions tools/chrome-debug-extension/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"target": "es2016",
"lib": [
"es2017",
"ES2018.Promise",
"dom"
],
"sourceMap": true,
Expand Down
Loading