summaryrefslogtreecommitdiff
path: root/chromium/docs/telemetry_extension/README.md
blob: 8e4a9f6e860a29fc78eb4859efabf4f4487f3f40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# Telemetry Extension API

This document describes the Architecture for the third-party Telemetry
Extensions Platform.

[TOC]

# Overview

The Telemetry Extension Platform provides means for accessing Telemetry and
Diagnostics data of a ChromeOS device. The Telemetry Extension Platform
consists of 2 parts:

1. A Chrome headless extension for API access, background data gathering and
processing (Telemetry Extension)

2. A companion [Progressive Web App (PWA)](https://web.dev/progressive-web-apps/)
to show UI to a user.

The Telemetry Extension uses
[Manifest V3](https://developer.chrome.com/docs/extensions/mv3/intro/) to
benefit from using
[Service Workers](https://developer.chrome.com/docs/workbox/service-worker-overview/)
instead of a background script. Only when the PWA is open, the Telemetry
Extension periodically receives user driven requests from the PWA to fetch
telemetry and run diagnostics routines. The PWA also has its own launch icon
and it doesn’t have direct access to the telemetry and diagnostics API, but it
communicates with the Telemetry Extension using message passing.

This image shows an overview of the architecture.
<br>
<br>
![](images/TelemetryExtensionArchitecture.png)

# Components

## Telemetry Extension

The Telemetry Extension's role is to handle requests from the UI and gather
telemetry and diagnostics data. The Telemetry Extension has a service worker
and does not have a launch icon. For this specific situation a new Chrome
extension type was declared, the ChromeOS System extension. In a ChromeOS
System extension, the service worker has direct access to normal
[web APIs](https://developer.mozilla.org/en-US/docs/Web/API). Most of the
[common Chrome Extension APIs](https://developer.chrome.com/docs/extensions/reference/)
are disabled (besides `chrome.runtime` to communicate with the PWA) and access
to the Telemetry API is granted either directly through `os.` or via DPSL.js
the recommended way of using the API). Please note that each extension ID needs
to be allowlisted by Google in the Chrome codebase to have access to APIs.

## PWA

It is the role of the PWA to show UI to the user and communicate with the
Telemetry Extension to get telemetry and diagnostics data. The PWA has a
launch icon, UI, and access to web APIs.

## DPSL.js

DPSL.js stands for Diagnostic Processor Support Library for Javascript, it’s a
JS wrapper around the underlying Telemetry Extensions APIs. It offers an
abstracted way for querying the API and is supported and updated by Google to
always support the latest APIs. DPSL.js is Google’s recommended way to interact
with the telemetry extension APIs. The library is hosted on
[Github](https://github.com/GoogleChromeLabs/telemetry-support-extension-for-chromeos)
and published to [npm](https://www.npmjs.com/package/cros-dpsl-js), please refer
to the documentation.
[These tables](https://github.com/GoogleChromeLabs/telemetry-support-extension-for-chromeos/tree/main/src#functions)
show an overview of all available API functions.

## Communication

A Chrome extension and a PWA can communicate with each other using message
passing. Only PWAs can initiate communication because a PWA is running only
when the user launches it.
The following example shows how the communication between the two components
could look like. The PWA uses `chrome.runtime.sendMessage` to communicate with
the Chrome extension:

```javascript
// PWA code

// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";

// Make a simple request:
chrome.runtime.sendMessage(
  /* extensionId */ editorExtensionId,
  /* message in JSON */ {openUrlInEditor: url},
  /* callback */ function(response) {
    if (!response.success)
      handleError(url);
  });
```

The extension side can handle incoming requests as follows:

```javascript
// Extension code

chrome.runtime.onMessageExternal.addListener(
 function(request, sender, sendResponse) {
   if (sender.url == blocklistedWebsite)
     return;  // don't allow this web page access
   if (request.openUrlInEditor)
     openUrl(request.openUrlInEditor);
 });
```

# The Chrome extension

In order for a Chrome extension to have access to telemetry and diagnostics
APIs, the following requirements need to be satisfied:

1. The user must be either:

    a. managed and the Telemetry extension was force-installed via policy, or

    b. The user is the device owner (the first user of the device).

2. The PWA UI associated with the Telemetry extension must be opened for the
extension to have access to APIs.

3. The device hardware must belong to the OEM associated with the Telemetry
extension (e.g. HP Support Assist only runs on HP devices).

4. Only an allowlisted extension ID can access Telemetry Extension APIs. Each
allowlisted extension ID can be connected to one PWA origin. It is mandatory
to declare one entry in `externally_connectable.matches` list.
An example can be found here:
```json
"externally_connectable": {
 "matches": ["https://third-party.com/*"]
}
```

The `externally_connectable` key determines whether or not a website (or other
Chrome extension) can initiate communication with a Telemetry Extension. A
Telemetry Extension can always choose to communicate with sites indirectly via
content scripts injected into a tab. Please note that no matter what,
extensions should always validate and sanitize messages.  An extension should
never have a listener that evals random code sent in a message. This helps
mitigate the damage a sender (whether untrusted or compromised) may be able to
perform. This is also critical because other Chrome extensions may be running
on the site that tries to connect to the Telemetry Extension and can initiate
that connection.

# Development / Testing support

## Overriding PWA origin (Since M98) / Manufacturer (Since M105)

Support for overriding the PWA origin and manufacturer to use while development
and testing was added in version M98 and M105. The PWA origin option overrides
the allowlisted PWA origin while the manufacturer overrides the actual device
manufacturer fetched from cros_config. Here is what you need to do in order to
access the flags (you can skip to step 3 if you already have read/write access
to rootfs):

1. On your testing device, make sure you enable developer mode.

2. Make sure you have write access to rootfs, if not run `/usr/share/vboot/bin/make_dev_ssd.sh --remove_rootfs_verification`

3. Open `/etc/chrome_dev.conf` and add these lines to the end:
```
--telemetry-extension-pwa-origin-override-for-testing=<new-pwa-origin>
--telemetry-extension-manufacturer-override-for-testing=<new-manufacturer>
```

<ol start="4">
<li>In your Telemetry Extension's manifest.json, set the
externally_connectable.matches entry to match <new-pwa-origin>.</li>
</ol>

After following those steps, the new PWA and the Telemetry Extension should be
able to communicate via message passing.

## A Note on Serial Number

The device serial number can be accessed using `dpsl.telemetry.getVpdInfo()`
and the battery serial number is accessed using `dpsl.telemetry.getOemDataInfo()`.
Because of the sensitive nature of serial numbers, this information is guarded
using a runtime permission: `os.telemetry.serial_number`.
For technical limitation, this is now a mandatory permission, meaning the
chrome extension’s manifest.json needs to include it in the permissions list in
order to have access to serial numbers.

## Setup a secure connection on localhost

The Telemetry Extension enforces `https` as the protocol for communicating with
the PWA. During development, this leads to a rejection of a PWA hosted under
`http://localhost/` or another origin that does not have a valid certificate
that is trusted by Chrome. The following steps describe how to set up a secure
development PWA under crostini (Linux on ChromeOS). For this guide we assume
`localhost` as the host. Please note that the `openssl` commands for this
guide were taken from
[this](https://www.section.io/engineering-education/how-to-get-ssl-https-for-localhost/)
blog post.

* Setup crostini (`Settings>Developers>Linux development environment`) and make
sure that "My Files" are shared with Linux (right click on the "My Files" folder
and then select "Share with Linux").
* Navigate to a shared folder under `mnt/chromeos/..` and run the following
command to create a root certificate:
```
openssl genrsa -out CA.key -des3 2048
```
* Using this key, generate a root certificate:
```
openssl req -x509 -sha256 -new -nodes -days 3650 -key CA.key -out CA.pem
```
* Next up, create a file named `localhost.ext` with the following content:
```
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost
IP.1 = 127.0.0.1
```
* Now create a key and a Certificate Signing Request (CSR) for localhost using
the following commands:
```
openssl genrsa -out localhost.key -des3 2048
openssl req -new -key localhost.key -out localhost.csr
```
* Finally generate a Certificate for localhost with the following command:
```
openssl x509 -req -in localhost.csr -CA ../CA.pem -CAkey ../CA.key -CAcreateserial -days 3650 -sha256 -extfile localhost.ext -out localhost.crt
```
* For your convenience create a decrypted version of your key for localhost.
This can be used by your development instance.
````
openssl rsa -in localhost.key -out localhost.decrypted.key
````

You can now use the generated key and certificate for localhost in your
development environment. In order for Chrome to trust the key used by your
application, you need to add the CA root certificate to Chrome.
Under `Settings>Privacy and security>Security>Manage certificates` you are
able to set the root CA. Just select the `Authorities` tab and click `Import`.
Select the generated `CA.pem` file and click open. Now your Chrome instance
and testing environment trust each other.

# FAQs

Q: I found a bug, how do I report it?<br>
A: Thank you for your contribution. Please create a new bug with the description
and logs (if possible) on our
[bugtracker](https://partnerissuetracker.corp.google.com/issues/new?component=1225577&template=1725782).
You need a partner account to do that.

Q: Have a question?<br>
A: Please reach out to cros-oem-services-team@google.com.