• 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
17import {FunctionUtils} from 'common/function_utils';
18import {OnBugreportReceived, RemoteBugreportReceiver} from 'interfaces/remote_bugreport_receiver';
19import {OnTimestampReceived, RemoteTimestampReceiver} from 'interfaces/remote_timestamp_receiver';
20import {RemoteTimestampSender} from 'interfaces/remote_timestamp_sender';
21import {RealTimestamp} from 'trace/timestamp';
22import {Message, MessageBugReport, MessagePong, MessageTimestamp, MessageType} from './messages';
23import {OriginAllowList} from './origin_allow_list';
24
25class RemoteTool {
26  constructor(readonly window: Window, readonly origin: string) {}
27}
28
29export 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