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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
ash / components / arc / mojom / file_system.mojom [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Next MinVersion: 26
module arc.mojom;
import "ash/components/arc/mojom/app.mojom";
import "ash/components/arc/mojom/bitmap.mojom";
import "ash/components/arc/mojom/gfx.mojom";
import "ash/components/arc/mojom/intent_common.mojom";
import "ash/components/arc/mojom/video_common.mojom";
import "mojo/public/mojom/base/file_path.mojom";
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/token.mojom";
import "url/mojom/url.mojom";
// TODO(b/193097194): Use structured types (e.g., url.mojom.Url for URLs).
// Reminder: The input strings from ARC (e.g., authority, root_id and
// document_id) cannot be trusted and must NOT be used without appropriate
// escaping or validation, especially when constructing file paths from them.
// Represents a document in Android DocumentsProvider.
// See Android docs of DocumentsContract.Document for details.
struct Document {
// Opaque ID of the document.
string document_id;
// Display name of the document.
string display_name;
// MIME type of the document.
// A directory is represented by a document having MIME_TYPE_DIR MIME type.
string mime_type;
// Size of the document in bytes. If the size is unknown, -1 is set.
int64 size;
// Timestamp when the document was modified last time, in milliseconds
// since UNIX epoch.
// TODO(crbug.com/40497368): Use mojo_base.mojom.Time once the type is
// converted to a non-native type so that it can be used from Java.
uint64 last_modified;
// Path to a real file on the Android VFS corresponding to this document,
// e.g. "/storage/emulated/0/DCIM/kitten.jpg".
// This value is available in limited DocumentsProviders only. If the
// provider does not expose real VFS paths, this field is always set to null.
[MinVersion=5] string? android_file_system_path;
// Flag indicating that a document is deletable.
[MinVersion=12] bool supports_delete;
// Flag indicating that a document can be renamed.
[MinVersion=12] bool supports_rename;
// Flag indicating that a document supports writing.
[MinVersion=12] bool supports_write;
// Flag indicating that a document is a directory that supports creation of
// new files within it.
[MinVersion=12] bool dir_supports_create;
// Flag indicating that a document can be copied to another location within
// the same document provider.
[MinVersion=12] bool supports_copy;
// Flag indicating that a document can be moved to another location within
// the same document provider.
[MinVersion=12] bool supports_move;
// Flag indicating that a document has a thumbnail available that can be
// fetched with OpenThumbnail.
[MinVersion=15] bool supports_thumbnail;
};
// Represents a root in Android DocumentsProvider.
// See Android docs of DocumentsContract.Root for details.
struct Root {
// Authority for the root.
string authority;
// Opaque ID of the root.
string root_id;
// Opaque ID of the document which is a directory that represents the top
// directory of the root.
string document_id;
// Title for the root, which will be shown to a user.
string title;
// Summary for the root, which may be shown to a user.
string? summary;
// Icon for the root, represented in a ARGB_8888 bitmap.
ArcBitmap? icon;
// Flag indicating that at least one directory under this root supports
// creating contents.
[MinVersion=12] bool supports_create;
// Mime types supported by this root.
[MinVersion=12] array<string>? mime_types;
};
// Describes the type of a change made to a document.
[Extensible]
enum ChangeType {
// Indicates that the child document list of the watched directory was
// changed. Note that a watcher can be installed only on directory for now.
CHANGED = 0,
// Indicates that the watched document itself was deleted.
// Even if OnDocumentChanged() is called with this change type, the
// corresponding watcher is not uninstalled automatically. The host must
// call RemoveWatcher() to clean up an orphaned watcher.
DELETED = 1,
};
// Content URL associated with its MIME type.
struct ContentUrlWithMimeType {
url.mojom.Url content_url;
string mime_type;
};
// Request for opening URLs by sending an intent to the specified activity.
struct OpenUrlsRequest {
// Action type of the intent.
ActionType action_type;
// Target activity for the intent.
ActivityName activity_name;
// One or more URLs to open with the intent.
array<ContentUrlWithMimeType> urls;
// Optional string extras. These are the key-value pairs stored in android
// intents to carry additional data. See:
// https://developer.android.com/reference/android/content/Intent#putExtra(java.lang.String,%20java.lang.String)
[MinVersion=17] map<string, string>? extras;
};
// Supported action types for SelectFilesRequest.
// Corresponds to Android intent actions described in
// http://developer.android.com/reference/android/content/Intent.html except
// for OPEN_MEDIA_STORE_FILES, which is a dedicated intent action of
// ArcDocumentsUI.
[Extensible]
enum SelectFilesActionType {
GET_CONTENT, // Intent.ACTION_GET_CONTENT
OPEN_DOCUMENT, // Intent.ACTION_OPEN_DOCUMENT
OPEN_DOCUMENT_TREE, // Intent.ACTION_OPEN_DOCUMENT_TREE
CREATE_DOCUMENT, // Intent.ACTION_CREATE_DOCUMENT
// ArcDocumentsUI's intent action to open files indexed in Android's
// MediaStore with a customized file selector.
[MinVersion=22] OPEN_MEDIA_STORE_FILES,
};
// Request for having the user select files using ChromeOS file selector,
// converted from an Android intent.
struct SelectFilesRequest {
// Action type of the original Android intent.
SelectFilesActionType action_type;
// Acceptable document MIME types. Copied from Intent.EXTRA_MIME_TYPES if
// there are multiple disjoint MIME types (e.g. ["image/*", "video/*"]), or
// copied from Intent#getType if there is only one. Empty means ["*/*"].
array<string> mime_types;
// If true, only requests files that can be opened by Android ContentResolver.
// Corresponds to Intent.CATEGORY_OPENABLE.
bool openable_only;
// If true, allows the user to select multiple files.
// Corresponds to Intent.EXTRA_ALLOW_MULTIPLE.
bool allow_multiple;
// File name to be initially filled in the selector when creating a new file.
// Corresponds to Intent.EXTRA_TITLE.
string default_file_name;
// Directory path to be initially opened when the file selector is launched.
// Corresponds to DocumentsContract.EXTRA_INITIAL_URI.
string initial_content_uri;
// DocumentPath representation for initial URI.
// Filled only when DocumentsContract.EXTRA_INITIAL_URI points to a document
// served by a DocumentsProvider.
DocumentPath? initial_document_path;
// Android task ID of the request sender.
int32 task_id;
// Search query to run when the file selector is launched.
// Corresponds to Intent.EXTRA_CONTENT_QUERY.
string? search_query;
};
// Represents a path to a document served by a DocumentsProvider.
struct DocumentPath {
// Authority of the document provider.
string authority;
// List of document ID from the root document to the child document.
// This should at least contain root document ID.
array<string> path;
// Root ID where the path resides.
[MinVersion=24] string? root_id;
};
// Result for SelectFilesRequest.
struct SelectFilesResult {
// Content URLs of the selected files.
// Empty if the user closes the file selector without selecting any files.
array<url.mojom.Url> urls;
// Name of the selected Android picker activity.
// Filled only when the user selected an Android picker activity instead of
// selecting files. (e.g. "com.google.photos/.PickerActivity")
string? picker_activity;
};
// UI event to be dispatched to ChromeOS file selector.
struct FileSelectorEvent {
// Type of the UI event.
FileSelectorEventType type;
// Specifies the target directory/file for CLICK_DIRECTORY/CLICK_FILE.
FileSelectorElement click_target;
// Android task ID of the activity that created the file selector by sending
// a SelectFilesRequest.
int32 creator_task_id;
};
// Types of UI events for FileSelectorEvent.
[Extensible]
enum FileSelectorEventType {
CLICK_OK, // Clicks OK button.
CLICK_DIRECTORY, // Clicks a directory in the left pane.
CLICK_FILE, // Clicks a file in the right pane.
CLICK_CANCEL, // Clicks Cancel button.
};
// Request for GetFileSelectorElements.
struct GetFileSelectorElementsRequest {
// Android task ID of the activity that created the file selector by sending
// a SelectFilesRequest.
int32 creator_task_id;
};
// Represents a clickable UI element shown on ChromeOS file selector.
struct FileSelectorElement {
// User-visible label of the element (e.g. button text).
// This is usually equivalent to accessibility label of the element.
string name;
};
// A subset of clickable UI elements shown on ChromeOS file selector.
struct FileSelectorElements {
// List of directories in the left pane.
array<FileSelectorElement> directory_elements;
// List of files in the right pane.
array<FileSelectorElement> file_elements;
// Query text filled in the search box.
string? search_query;
};
// Returned output for GetRootSize.
struct RootSize {
// Available size of a root in bytes. Set to -1 if the available size is
// unknown or unbounded.
int64 available_bytes;
// Capacity of a root in bytes. Set to -1 if the capacity is unknown or
// unbounded.
int64 capacity_bytes;
};
// Returned output for OpenFileSessionToWrite.
struct FileSession {
// Unique ID for the URL that is opened and mapped to a ParcelFileDescriptor
// object to be closed after the ChromeOS file operation(s).
string url_id;
// FD for writing or reading the file specified by the URL.
handle fd;
};
// Representation of an entry in the MediaStore downloads collection.
struct MediaStoreDownloadMetadata {
// The display name of the download including its extension (e.g. "foo.pdf").
string display_name;
// The package name that contributed the download (e.g. "com.bar.foo").
string owner_package_name;
// The relative path of the download within the Download/ directory (e.g.
// "Download/foo/bar/"). The method implementation must verify that the
// `relative_path` is in fact within the Download/ directory, treating ARC as
// an untrusted source.
mojo_base.mojom.FilePath relative_path;
};
// Representation of an entry in a MediaStore collection.
[Extensible]
union MediaStoreMetadata {
[Default] uint8 unknown; // Actual value is ignored and is just a placeholder.
MediaStoreDownloadMetadata download;
};
// Next method ID: 15
interface FileSystemHost {
// Returns the name of the file specified by the URL.
// When an error occurs, returns null value.
[MinVersion=6] GetFileName@1(string url) => (string? name);
// Returns the size of the file specified by the URL.
// If the file does not exist or the size is unknown (e.g. directories and
// streams), -1 is returned.
[MinVersion=6] GetFileSize@2(string url) => (int64 size);
// Returns the last modified timestamp of the file specified by the URL.
[MinVersion=20] GetLastModified@11(url.mojom.Url url)
=> (mojo_base.mojom.Time? last_modified);
// Returns the MIME type of the file specified by the URL.
// When an error occurs, returns null value.
[MinVersion=6] GetFileType@3(string url) => (string? mime_type);
// Called when a watched document was changed.
// |type| describes the type of change made to the document.
[MinVersion=3] OnDocumentChanged@0(int64 watcher_id, ChangeType type);
// Called when the list of available roots or their metadata are changed.
[MinVersion=10] OnRootsChanged@6();
// Returns a unique ID to represent the file specified by the URL.
// The FD needs to be created by the caller itself.
[MinVersion=16] GetVirtualFileId@9(string url) => (string? id);
// Releases the ID generated by GetVirtualFileId() when it is no longer
// used.
[MinVersion=16] HandleIdReleased@10(string id) => (bool success);
// Returns an FD for reading the file specified by the URL.
[MinVersion=6] OpenFileToRead@4(string url) => (handle? fd);
// Asks the user to select files using ChromeOS file selector.
[MinVersion=9] SelectFiles@5(SelectFilesRequest request) =>
(SelectFilesResult result);
// Dispatches a UI event to the ChromeOS file selector previously opened by
// SelectFiles@5. This exists for running Android UI tests (CTS) on ChromeOS
// file selector, and thus it is only allowed under test conditions.
[MinVersion=11] OnFileSelectorEvent@7(FileSelectorEvent event) => ();
// Returns UI elements shown on the ChromeOS file selector previously opened
// by SelectFiles@5. This exists for running Android UI tests (CTS) on
// ChromeOS file selector, and thus it is only allowed under test conditions.
[MinVersion=11] GetFileSelectorElements@8(
GetFileSelectorElementsRequest request) =>
(FileSelectorElements elements);
// Invoked when the specified |uri| has been added to a MediaStore collection
// with the given |metadata|.
[MinVersion=23] OnMediaStoreUriAdded@12(
url.mojom.Url uri, MediaStoreMetadata metadata);
// Creates a Fusebox Moniker associated with the given content URI, shares the
// Moniker's path with the guest via seneschal, and returns the Moniker. A
// null value is returned on failure. On success, the caller is responsible
// for releasing the Moniker by calling DestroyMoniker() after they have
// finished using it.
[MinVersion=25] CreateMoniker@13(url.mojom.Url content_uri, bool read_only) =>
(mojo_base.mojom.Token? moniker);
// Destroys the given Fusebox Moniker and resources accosiated with it.
// Returns true when the Moniker and the resources have been successfully
// released. Otherwise false is returned, which indicates that the given
// Moniker has already been destroyed via DestroyMoniker(), or it is not the
// one created by ArcFileSystemBridge.
[MinVersion=25] DestroyMoniker@14(mojo_base.mojom.Token moniker) =>
(bool success);
};
// The browser process is using this interface in ArcFileSystemOperationRunner,
// the ARC process implements this interface used by ArcFileSystemService.
// Deprecated method IDs: 2, 5, 11, 18
// Next method ID: 27
interface FileSystemInstance {
// Notes about Android Documents Provider:
//
// In Android Storage Access Framework, a document is uniquely identified by
// a pair of "authority" and "document ID".
//
// - An authority specifies a Documents Provider that serves a document.
// It is the origin part of a content:// URI used to access the Documents
// Provider via Content Resolver protocol.
// Example: "com.android.providers.media.documents"
// - A documents provider may provide one or more roots. Each root is identified
// by a root ID.
// - A document ID is an opaque string that specifies a particular document
// in a documents provider. Its format varies by providers. Roots also have
// associated document IDs.
//
// See the following documents for details about Documents Provider:
// https://developer.android.com/guide/topics/providers/document-provider.html
// https://developer.android.com/reference/android/provider/DocumentsContract.html
// Installs a document watcher to watch updates of a document.
//
// Currently, watchers can be installed only on directories, and only
// directory content changes are notified.
//
// On success, a positive unique integer is returned as a watcher ID.
// FileSystemHost.OnDocumentChanged() will be called with the watcher ID
// on directory content changes.
// On failure, -1 is returned.
//
// It is allowed to install multiple watchers to the same directory. In that
// case, different watcher IDs are returned.
//
// Watchers are not persistent. When the Mojo connection is lost, all
// watchers are cleared. Also, after reconnecting, watcher IDs can be reused.
[MinVersion=3] AddWatcher@6(string authority, string document_id) =>
(int64 watcher_id);
// Queries child documents of the directory specified by |authority| and
// |parent_document_id| in Documents Provider.
// If such a directory does not exist, null is returned.
[MinVersion=2] GetChildDocuments@4(string authority,
string parent_document_id) =>
(array<Document>? documents);
// Queries the document specified by |authority| and |document_id| in
// Documents Provider.
// If such a document does not exist, null is returned.
[MinVersion=2] GetDocument@3(string authority, string document_id) =>
(Document? document);
// Asks the ContentResolver for the size of the file specified by the URL.
// If the file does not exist or the size is unknown (e.g. directories and
// streams), -1 is returned.
[MinVersion=1] GetFileSize@1(string url) => (int64 size);
// Asks the ContentResolver to get the MIME type of the file specified by the
// URL. When an error occurs, returns null value.
[MinVersion=4] GetMimeType@8(string url) => (string? mime_type);
// Queries recent documents of a root specified by |authority| and |root_id|.
// If the root exists and it supports recent document queries, a (possibly
// empty) list of documents is returned. Otherwise, null is returned.
[MinVersion=5] GetRecentDocuments@9(string authority, string root_id) =>
(array<Document>? documents);
// Obtains cached roots from all Documents Providers.
// If there is no root in ARC, an empty array is returned.
// If an error is found during GetRoots() method processing in ARC, null
// value is returned.
[MinVersion=10] GetRoots@12() => (array<Root>? roots);
// Queries available roots to find the one matching |root_id| and |authority|.
// Obtains the root's available bytes and capacity bytes for |root_size|.
// Returns null if there is no root that matches the input parameters.
[MinVersion=18] GetRootSize@22(string authority, string root_id) =>
(RootSize? root_size);
// Deletes the given document.
[MinVersion=12] DeleteDocument@13(string authority, string document_id) =>
(bool success);
// Changes the display name of an existing document.
[MinVersion=12] RenameDocument@14(string authority,
string document_id,
string display_name) =>
(Document? document);
// Creates a new document with given MIME type and display name.
[MinVersion=12] CreateDocument@15(string authority,
string parent_document_id,
string mime_type,
string display_name) =>
(Document? document);
// Copies the given document.
[MinVersion=12] CopyDocument@16(string authority,
string source_document_id,
string target_parent_document_id) =>
(Document? document);
// Moves the given document under a new parent.
[MinVersion=12] MoveDocument@17(string authority,
string source_document_id,
string source_parent_document_id,
string target_parent_document_id) =>
(Document? document);
// Establishes full-duplex communication with the host.
[MinVersion=7] Init@10(pending_remote<FileSystemHost> host_remote) => ();
// Asks the ContentResolver to get a FD to read the thumbnail of a
// DocumentsProvider file specified by the URL. The thumbnail should be close
// in size (width and height) but not necessarily the same as |size_hint|.
[MinVersion=15] OpenThumbnail@21(string url, Size size_hint) => (handle? fd);
// Closes the ParcelFileDescriptor corresponding to the url_id. An error
// message can be sent to the ContentProvider as needed.
[MinVersion=21] CloseFileSession@24(string url_id, string error_message);
// Asks the ContentResolver to get a FD to write to the file specified by the
// URL. FileSession is returned with a unique ID corresponding to the open
// session so the file can be closed properly after remote write operation.
[MinVersion=21] OpenFileSessionToWrite@25(url.mojom.Url url) =>
(FileSession? file_session);
// Asks the ContentResolver to get a FD to read the file specified by the
// URL. FileSession is returned with a unique ID corresponding to the open
// session so the file can be closed properly after remote read operation.
[MinVersion=21] OpenFileSessionToRead@26(url.mojom.Url url) =>
(FileSession? file_session);
// Uninstalls a document watcher.
//
// After this method call returns, OnDocumentChanged() will never be called
// with the watcher ID. Whether OnDocumentChanged() is called or not after
// this method is called and before this method returns is undefined.
//
// It fails if the specified watcher does not exist.
[MinVersion=3] RemoveWatcher@7(int64 watcher_id) => (bool success);
// Requests MediaProvider to scan specified files.
// When the specified file does not exist, the corresponding entry in
// MediaProvider is removed.
//
// NOTE: We use [UnlimitedSize] here because `paths` may be arbitrarily large
// and there have been crash dumps indicating that it actually happens with
// this message. See https://crbug.com/1142019.
[UnlimitedSize]
RequestMediaScan@0(array<string> paths);
// Reloads and refreshes entries in MediaStore under |directory_path|.
[MinVersion=14] ReindexDirectory@19(string directory_path);
// Searches for the removed files/directories under the given
// |directory_paths| (non-recursively) in MediaStore and removes them.
[MinVersion=14] RequestFileRemovalScan@20(array<string> directory_paths);
// Opens URLs by sending an intent to the specified activity with a specific
// launch window info.
//
// Since this grants read/write URL permissions to the activity, callers must
// ensure that the user is correctly aware of the URLs and the activity they
// are passing.
[MinVersion=19] OpenUrlsWithPermissionAndWindowInfo@23(
OpenUrlsRequest request, WindowInfo window_info) => ();
};