• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 import {FunctionUtils} from 'common/function_utils';
18 import {OnBugreportReceived, RemoteBugreportReceiver} from 'interfaces/remote_bugreport_receiver';
19 import {OnTimestampReceived, RemoteTimestampReceiver} from 'interfaces/remote_timestamp_receiver';
20 import {RemoteTimestampSender} from 'interfaces/remote_timestamp_sender';
21 import {RealTimestamp} from 'trace/timestamp';
22 import {Message, MessageBugReport, MessagePong, MessageTimestamp, MessageType} from './messages';
23 import {OriginAllowList} from './origin_allow_list';
24 
25 class RemoteTool {
26   constructor(readonly window: Window, readonly origin: string) {}
27 }
28 
29 export class CrossToolProtocol
30   implements RemoteBugreportReceiver, RemoteTimestampReceiver, RemoteTimestampSender
31 {
32   private remoteTool?: RemoteTool;
33   private onBugreportReceived: OnBugreportReceived = FunctionUtils.DO_NOTHING_ASYNC;
34   private onTimestampReceived: OnTimestampReceived = FunctionUtils.DO_NOTHING_ASYNC;
35 
36   constructor() {
37     window.addEventListener('message', async (event) => {
38       await this.onMessageReceived(event);
39     });
40   }
41 
42   setOnBugreportReceived(callback: OnBugreportReceived) {
43     this.onBugreportReceived = callback;
44   }
45 
46   setOnTimestampReceived(callback: OnTimestampReceived) {
47     this.onTimestampReceived = callback;
48   }
49 
50   sendTimestamp(timestamp: RealTimestamp) {
51     if (!this.remoteTool) {
52       return;
53     }
54 
55     const message = new MessageTimestamp(timestamp.getValueNs());
56     this.remoteTool.window.postMessage(message, this.remoteTool.origin);
57     console.log('Cross-tool protocol sent timestamp message:', message);
58   }
59 
60   private async onMessageReceived(event: MessageEvent) {
61     if (!OriginAllowList.isAllowed(event.origin)) {
62       console.log(
63         'Cross-tool protocol ignoring message from non-allowed origin.',
64         'Origin:',
65         event.origin,
66         'Message:',
67         event.data
68       );
69       return;
70     }
71 
72     const message = event.data as Message;
73     if (message.type === undefined) {
74       return;
75     }
76 
77     if (!this.remoteTool) {
78       this.remoteTool = new RemoteTool(event.source as Window, event.origin);
79     }
80 
81     switch (message.type) {
82       case MessageType.PING:
83         console.log('Cross-tool protocol received ping message:', message);
84         (event.source as Window).postMessage(new MessagePong(), event.origin);
85         break;
86       case MessageType.PONG:
87         console.log('Cross-tool protocol received unexpected pong message:', message);
88         break;
89       case MessageType.BUGREPORT:
90         console.log('Cross-tool protocol received bugreport message:', message);
91         await this.onMessageBugreportReceived(message as MessageBugReport);
92         console.log('Cross-tool protocol processes bugreport message:', message);
93         break;
94       case MessageType.TIMESTAMP:
95         console.log('Cross-tool protocol received timestamp message:', message);
96         await this.onMessageTimestampReceived(message as MessageTimestamp);
97         console.log('Cross-tool protocol processed timestamp message:', message);
98         break;
99       case MessageType.FILES:
100         console.log('Cross-tool protocol received unexpected files message', message);
101         break;
102       default:
103         console.log('Cross-tool protocol received unsupported message type:', message);
104         break;
105     }
106   }
107 
108   private async onMessageBugreportReceived(message: MessageBugReport) {
109     const timestamp =
110       message.timestampNs !== undefined ? new RealTimestamp(message.timestampNs) : undefined;
111     await this.onBugreportReceived(message.file, timestamp);
112   }
113 
114   private async onMessageTimestampReceived(message: MessageTimestamp) {
115     const timestamp = new RealTimestamp(message.timestampNs);
116     await this.onTimestampReceived(timestamp);
117   }
118 }
119