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) => ();
};