Skip to content

Commit ee21558

Browse files
szuendDevtools-frontend LUCI CQ
authored andcommitted
Simplify copy-to-clipboard helpers in BinaryResourceViewFactory
This CL replaces the utf8/hex methods on BinaryResourceViewFactory with a slower but sync version and removes the caching. This makes handling with the "StreamingContentData" easier since we don't have to update the cached value when the "StreamingContentData" updates. Note that this is not a big deal performance wise. The utf8/hex helpers are not invoked often: When the user triggers a "copy-to-clipboard" action and for utf8 when we create the view initially. Using the sync version over `fetch` is also slightly slower (by a factor of 2x for a 20MB string), but the sync code is much simpler to deal with. [email protected] Bug: 375546679 Change-Id: Ie5b6038cb1d0183014058c5b0bdef76c6bec0ca4 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/5993270 Reviewed-by: Philip Pfaffe <[email protected]> Commit-Queue: Simon Zünd <[email protected]>
1 parent 87ce37e commit ee21558

File tree

3 files changed

+33
-51
lines changed

3 files changed

+33
-51
lines changed

front_end/panels/network/BinaryResourceView.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export class BinaryResourceView extends UI.Widget.VBox {
8484
new BinaryViewObject(
8585
'base64', i18n.i18n.lockedString('Base64'), i18nString(UIStrings.copiedAsBase),
8686
this.binaryResourceViewFactory.createBase64View.bind(this.binaryResourceViewFactory),
87-
() => Promise.resolve(this.binaryResourceViewFactory.base64())),
87+
this.binaryResourceViewFactory.base64.bind(this.binaryResourceViewFactory)),
8888
new BinaryViewObject(
8989
'hex', i18nString(UIStrings.hexViewer), i18nString(UIStrings.copiedAsHex),
9090
this.binaryResourceViewFactory.createHexView.bind(this.binaryResourceViewFactory),
@@ -105,7 +105,7 @@ export class BinaryResourceView extends UI.Widget.VBox {
105105

106106
const copyButton = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.copyToClipboard), 'copy');
107107
copyButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, _event => {
108-
void this.copySelectedViewToClipboard();
108+
this.copySelectedViewToClipboard();
109109
}, this);
110110
this.toolbar.appendToolbarItem(copyButton);
111111

@@ -129,12 +129,12 @@ export class BinaryResourceView extends UI.Widget.VBox {
129129
return binaryViewObject || null;
130130
}
131131

132-
private async copySelectedViewToClipboard(): Promise<void> {
132+
private copySelectedViewToClipboard(): void {
133133
const viewObject = this.getCurrentViewObject();
134134
if (!viewObject) {
135135
return;
136136
}
137-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(await viewObject.content());
137+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(viewObject.content());
138138
this.copiedText.setText(viewObject.copiedMessage);
139139
this.copiedText.element.classList.remove('fadeout');
140140
function addFadeoutClass(this: BinaryResourceView): void {
@@ -208,13 +208,12 @@ export class BinaryViewObject {
208208
type: string;
209209
label: string;
210210
copiedMessage: string;
211-
content: () => Promise<string>;
211+
content: () => string;
212212
private createViewFn: () => UI.Widget.Widget;
213213
private view: UI.Widget.Widget|null;
214214

215215
constructor(
216-
type: string, label: string, copiedMessage: string, createViewFn: () => UI.Widget.Widget,
217-
content: () => Promise<string>) {
216+
type: string, label: string, copiedMessage: string, createViewFn: () => UI.Widget.Widget, content: () => string) {
218217
this.type = type;
219218
this.label = label;
220219
this.copiedMessage = copiedMessage;

front_end/ui/legacy/components/source_frame/BinaryResourceViewFactory.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,18 @@ describeWithEnvironment('BinaryResourceViewFactory', () => {
3030
assert.strictEqual(
3131
await getResourceText(factory.createUtf8View()), 'sending this utf-8 string as a binary message...');
3232
});
33+
34+
it('returns the right content for the "copy-to-clipboard" getters', async () => {
35+
const base64content = new TextUtils.ContentData.ContentData(
36+
'c2VuZGluZyB0aGlzIHV0Zi04IHN0cmluZyBhcyBhIGJpbmFyeSBtZXNzYWdlLi4u', true, '');
37+
const factory = new SourceFrame.BinaryResourceViewFactory.BinaryResourceViewFactory(
38+
TextUtils.StreamingContentData.StreamingContentData.from(base64content),
39+
'http://example.com' as Platform.DevToolsPath.UrlString, Common.ResourceType.resourceTypes.WebSocket);
40+
41+
assert.strictEqual(factory.base64(), 'c2VuZGluZyB0aGlzIHV0Zi04IHN0cmluZyBhcyBhIGJpbmFyeSBtZXNzYWdlLi4u');
42+
assert.strictEqual(
43+
factory.hex(),
44+
'73656e64696e672074686973207574662d3820737472696e6720617320612062696e617279206d6573736167652e2e2e');
45+
assert.strictEqual(factory.utf8(), 'sending this utf-8 string as a binary message...');
46+
});
3347
});

front_end/ui/legacy/components/source_frame/BinaryResourceViewFactory.ts

Lines changed: 13 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,56 +13,27 @@ export class BinaryResourceViewFactory {
1313
private streamingContent: TextUtils.StreamingContentData.StreamingContentData;
1414
private readonly contentUrl: Platform.DevToolsPath.UrlString;
1515
private readonly resourceType: Common.ResourceType.ResourceType;
16-
private arrayPromise: Promise<Uint8Array>|null;
17-
private hexPromise: Promise<string>|null;
18-
private utf8Promise: Promise<string>|null;
16+
1917
constructor(
2018
content: TextUtils.StreamingContentData.StreamingContentData, contentUrl: Platform.DevToolsPath.UrlString,
2119
resourceType: Common.ResourceType.ResourceType) {
2220
this.streamingContent = content;
2321
this.contentUrl = contentUrl;
2422
this.resourceType = resourceType;
25-
this.arrayPromise = null;
26-
this.hexPromise = null;
27-
this.utf8Promise = null;
2823
}
2924

30-
private async fetchContentAsArray(): Promise<Uint8Array> {
31-
if (!this.arrayPromise) {
32-
this.arrayPromise = new Promise(async resolve => {
33-
const fetchResponse = await fetch('data:;base64,' + this.streamingContent.content().base64);
34-
resolve(new Uint8Array(await fetchResponse.arrayBuffer()));
35-
});
36-
}
37-
return await this.arrayPromise;
38-
}
39-
40-
async hex(): Promise<string> {
41-
if (!this.hexPromise) {
42-
this.hexPromise = new Promise(async resolve => {
43-
const content = await this.fetchContentAsArray();
44-
const hexString = BinaryResourceViewFactory.uint8ArrayToHexString(content);
45-
resolve(hexString);
46-
});
47-
}
48-
49-
return this.hexPromise;
25+
hex(): string {
26+
const binaryString = window.atob(this.base64());
27+
const array = Uint8Array.from(binaryString, m => m.codePointAt(0) as number);
28+
return BinaryResourceViewFactory.#uint8ArrayToHexString(array);
5029
}
5130

5231
base64(): string {
5332
return this.streamingContent.content().base64;
5433
}
5534

56-
async utf8(): Promise<string> {
57-
if (!this.utf8Promise) {
58-
this.utf8Promise = new Promise(async resolve => {
59-
const content = await this.fetchContentAsArray();
60-
const utf8String = new TextDecoder('utf8').decode(content);
61-
resolve(utf8String);
62-
});
63-
}
64-
65-
return this.utf8Promise;
35+
utf8(): string {
36+
return new TextUtils.ContentData.ContentData(this.base64(), /* isBase64 */ true, 'text/plain', 'utf-8').text;
6637
}
6738

6839
createBase64View(): ResourceSourceFrame {
@@ -77,23 +48,21 @@ export class BinaryResourceViewFactory {
7748
}
7849

7950
createUtf8View(): ResourceSourceFrame {
80-
const utf8fn = (): Promise<TextUtils.ContentData.ContentData> =>
81-
this.utf8().then(str => new TextUtils.ContentData.ContentData(str, /* isBase64 */ false, 'text/plain'));
82-
const utf8ContentProvider =
83-
new TextUtils.StaticContentProvider.StaticContentProvider(this.contentUrl, this.resourceType, utf8fn);
8451
return new ResourceSourceFrame(
85-
utf8ContentProvider, this.resourceType.canonicalMimeType(), {lineNumbers: true, lineWrapping: true});
52+
TextUtils.StaticContentProvider.StaticContentProvider.fromString(
53+
this.contentUrl, this.resourceType, this.utf8()),
54+
this.resourceType.canonicalMimeType(), {lineNumbers: true, lineWrapping: true});
8655
}
8756

88-
static uint8ArrayToHexString(uint8Array: Uint8Array): string {
57+
static #uint8ArrayToHexString(uint8Array: Uint8Array): string {
8958
let output = '';
9059
for (let i = 0; i < uint8Array.length; i++) {
91-
output += BinaryResourceViewFactory.numberToHex(uint8Array[i], 2);
60+
output += BinaryResourceViewFactory.#numberToHex(uint8Array[i], 2);
9261
}
9362
return output;
9463
}
9564

96-
static numberToHex(number: number, padding: number): string {
65+
static #numberToHex(number: number, padding: number): string {
9766
let hex = number.toString(16);
9867
while (hex.length < padding) {
9968
hex = '0' + hex;

0 commit comments

Comments
 (0)