xref: /aosp_15_r20/external/perfetto/ui/src/frontend/android_bug_tool.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import {defer} from '../base/deferred';
18
19enum WebContentScriptMessageType {
20  UNKNOWN,
21  CONVERT_OBJECT_URL,
22  CONVERT_OBJECT_URL_RESPONSE,
23}
24
25const ANDROID_BUG_TOOL_EXTENSION_ID = 'mbbaofdfoekifkfpgehgffcpagbbjkmj';
26
27interface Attachment {
28  name: string;
29  objectUrl: string;
30  restrictionSeverity: number;
31}
32
33interface ConvertObjectUrlResponse {
34  action: WebContentScriptMessageType.CONVERT_OBJECT_URL_RESPONSE;
35  attachments: Attachment[];
36  issueAccessLevel: string;
37  issueId: string;
38  issueTitle: string;
39}
40
41export interface TraceFromBuganizer {
42  issueId: string;
43  issueTitle: string;
44  file: File;
45}
46
47export function loadAndroidBugToolInfo(): Promise<TraceFromBuganizer> {
48  const deferred = defer<TraceFromBuganizer>();
49
50  // Request to convert the blob object url "blob:chrome-extension://xxx"
51  // the chrome extension has to a web downloadable url "blob:http://xxx".
52  chrome.runtime.sendMessage(
53    ANDROID_BUG_TOOL_EXTENSION_ID,
54    {action: WebContentScriptMessageType.CONVERT_OBJECT_URL},
55    async (response: ConvertObjectUrlResponse) => {
56      switch (response.action) {
57        case WebContentScriptMessageType.CONVERT_OBJECT_URL_RESPONSE:
58          if (response.attachments?.length > 0) {
59            const filesBlobPromises = response.attachments.map(
60              async (attachment) => {
61                const fileQueryResponse = await fetch(attachment.objectUrl);
62                const blob = await fileQueryResponse.blob();
63                // Note: The blob's media type is always set to "image/png".
64                // Clone blob to clear media type.
65                return new File([blob], attachment.name);
66              },
67            );
68            const files = await Promise.all(filesBlobPromises);
69            deferred.resolve({
70              issueId: response.issueId,
71              issueTitle: response.issueTitle,
72              file: files[0],
73            });
74          } else {
75            throw new Error('Got no attachements from extension');
76          }
77          break;
78        default:
79          throw new Error(
80            `Received unhandled response code (${response.action}) from extension.`,
81          );
82      }
83    },
84  );
85  return deferred;
86}
87