geckoview-architecture.rst (36299B)
1 .. -*- Mode: rst; fill-column: 80; -*- 2 3 ===================== 4 Architecture overview 5 ===================== 6 7 .. contents:: Table of Contents 8 :depth: 2 9 :local: 10 11 Introduction 12 ============ 13 14 *Gecko* is a Web engine developed by Mozilla and used to power Firefox on 15 various platforms. A Web engine is roughly comprised of a JavaScript engine, a 16 Rendering engine, HTML parser, a Network stack, various media encoders, a 17 Graphics engine, a Layout engine and more. 18 19 Code that is part of a browser itself is usually referred to as "chrome" code 20 (from which the popular Chrome browser takes its name) as opposed to code part 21 of a Web site, which is usually referred to "content" code or content Web page. 22 23 *GeckoView* is an Android library that can be used to embed Gecko into Android 24 apps. Android apps that embed Gecko this way are usually referred to by 25 "embedders" or simply "apps". 26 27 GeckoView powers all currently active Mozilla browsers on Android, like Firefox 28 for Android and Firefox Focus. 29 30 API 31 === 32 33 The following sections describe parts of the GeckoView API that are public and 34 exposed to embedders. 35 36 |api-diagram| 37 38 Overall tenets 39 -------------- 40 41 GeckoView is an opinionated library that contains a minimal UI and makes no 42 assumption about the type of app that is being used by. Its main consumers 43 inside Mozilla are browsers, so a lot of features of GeckoView are geared 44 towards browsers, but there is no assumption that the embedder is actually a 45 browser (e.g. there is no concept of "tab" in GeckoView). 46 47 The GeckoView API tries to retain as little data as possible, delegating most 48 data storage to apps. Notable exceptions to this rule are: permissions, 49 extensions and cookies. 50 51 View, Runtime and Session 52 ------------------------- 53 54 |view-runtime-session| 55 56 There are three main classes in the GeckoView API: 57 58 - ``GeckoRuntime`` represents an instance of Gecko running in an app. Normally, 59 apps have only one instance of the runtime which lives for as long as the app 60 is alive. Any object in the API that is not specific to a *session* 61 (more to this later) is usually reachable from the runtime. 62 - ``GeckoSession`` represents a web site *instance*. You can think of it as a 63 *tab* in a browser or a Web view in an app. Any object related to the 64 specific session will be reachable from this object. Normally, embedders 65 would have many instances of ``GeckoSession`` representing each tab that is 66 currently open. Internally, a session is represented as a "window" with one 67 single tab in it. 68 - ``GeckoView`` is an Android ``View`` that embedders can use to paint a 69 ``GeckoSession`` in the app. Normally, only ``GeckoSession`` s associated to 70 a ``GeckoView`` are actually *alive*, i.e. can receive events, fire timers, 71 etc. 72 73 Delegates 74 --------- 75 76 Because GeckoView has no UI elements and doesn't store a lot of data, it needs 77 a way to *delegate* behavior when Web sites need functionality that requires 78 these features. 79 80 To do that, GeckoView exposes Java interfaces to the embedders, called 81 Delegates. Delegates are normally associated to either the runtime, when they 82 don't refer to a specific session, or a session, when they are 83 session-specific. 84 85 The most important delegates are: 86 87 - ``Autocomplete.StorageDelegate`` Which is used by embedders to implement 88 autocomplete functionality for logins, addresses and credit cards. 89 - ``ContentDelegate`` Which receives events from the content Web page like 90 "open a new window", "on fullscreen request", "this tab crashed" etc. 91 - ``HistoryDelegate`` Which receives events about new or modified history 92 entries. GeckoView itself does not store history so the app is required to 93 listen to history events and store them permanently. 94 - ``NavigationDelegate`` Informs the embedder about navigation events and 95 requests. 96 - ``PermissionDelegate`` Used to prompt the user for permissions like 97 geolocation, notifications, etc. 98 - ``PromptDelegate`` Implements content-side prompts like alert(), confirm(), 99 basic HTTP auth, etc. 100 - ``MediaSession.Delegate`` Informs the embedder about media elements currently 101 active on the page and allows the embedder to pause, resume, receive playback 102 state etc. 103 - ``WebExtension.MessageDelegate`` Used by the embedder to exchange messages 104 with built-in extensions. See also `Interacting with Web Content <../consumer/web-extensions.html>`_. 105 106 107 .. _GeckoDisplay: 108 109 GeckoDisplay 110 ------------ 111 112 GeckoView can paint to either a ``SurfaceView`` or a ``TextureView``. 113 114 - ``SufaceView`` is what most apps will use and it's the default, it provides a 115 barebone wrapper around a GL surface where GeckoView can paint on. 116 SurfaceView is not part of normal Android compositing, which means that 117 Android is not able to paint (partially) on top of a SurfaceView or apply 118 transformations and animations to it. 119 - ``TextureView`` offers a surface which can be transformed and animated but 120 it's slower and requires more memory because it's `triple-buffered 121 <https://en.wikipedia.org/wiki/Multiple_buffering#Triple_buffering>`_ 122 (which is necessary to offer animations). 123 124 Most apps will use the ``GeckoView`` class to paint the web page. The 125 ``GeckoView`` class is an Android ``View`` which takes part in the Android view 126 hierarchy. 127 128 Android recycles the ``GeckoView`` whenever the app is not visible, releasing 129 the associated ``SurfaceView`` or ``TextureView``. This triggers a few actions 130 on the Gecko side: 131 132 - The GL Surface is released, and Gecko is notified in 133 `SyncPauseCompositor <https://searchfox.org/mozilla-central/rev/ead7da2d9c5400bc7034ff3f06a030531bd7e5b9/widget/android/nsWindow.cpp#1114>`_. 134 - The ``<browser>`` associated to the ``GeckoSession`` is `set to inactive <https://searchfox.org/mozilla-central/rev/ead7da2d9c5400bc7034ff3f06a030531bd7e5b9/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java#553>`_, 135 which essentially freezes the JavaScript engine. 136 137 Apps that do not use ``GeckoView``, because e.g. they cannot use 138 ``SurfaceView``, need to manage the active state manually and call 139 ``GeckoSession.setActive`` whenever the session is not being painted on the 140 screen. 141 142 Thread safety 143 ------------- 144 145 Apps will inevitably have to deal with the Android UI in a significant way. 146 Most of the Android UI toolkit operates on the UI thread, and requires 147 consumers to execute method calls on it. The Android UI thread runs an event 148 loop that can be used to schedule tasks on it from other threads. 149 150 Gecko, on the other hand, has its own main thread where a lot of the front-end 151 interactions happen, and many methods inside Gecko expect to be called on the 152 main thread. 153 154 To not overburden the App with unnecessary multi-threaded code, GeckoView will 155 always bridge the two "main threads" and redirect method calls as appropriate. 156 Most GeckoView delegate calls will thus happen on the Android UI thread and 157 most APIs are expected to be called on the UI thread as well. 158 159 This can sometimes create unexpected performance considerations, as illustrated 160 in later sections. 161 162 GeckoResult 163 ----------- 164 165 An ubiquitous tool in the GeckoView API is ``GeckoResult``. GeckoResult is a 166 promise-like class that can be used by apps and by Gecko to return values 167 asynchronously in a thread-safe way. Internally, ``GeckoResult`` will keep 168 track of what thread it was created on, and will execute callbacks on the same 169 thread using the thread's ``Handler``. 170 171 When used in Gecko, ``GeckoResult`` can be converted to ``MozPromise`` using 172 ``MozPromise::FromGeckoResult``. 173 174 Page load 175 --------- 176 177 |pageload-diagram| 178 179 GeckoView offers several entry points that can be used to react to the various 180 stages of a page load. The interactions can be tricky and surprising so we will 181 go over them in details in this section. 182 183 For each page load, the following delegate calls will be issued: 184 ``onLoadRequest``, ``onPageStart``, ``onLocationChange``, 185 ``onProgressChange``, ``onSecurityChange``, ``onSessionStateChange``, 186 ``onCanGoBack``, ``onCanGoForward``, ``onLoadError``, ``onPageStop``. 187 188 Most of the method calls are self-explanatory and offer the App a chance to 189 update the UI in response to a change in the page load state. The more 190 interesting delegate calls will be described below. 191 192 onPageStart and onPageStop 193 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 194 195 ``onPageStart`` and ``onPageStop`` are guaranteed to appear in pairs and in 196 order, and denote the beginning and the end of a page load. In between a start 197 and stop event, multiple ``onLoadRequest`` and ``onLocationChange`` call can be 198 executed, denoting redirects. 199 200 onLoadRequest 201 ~~~~~~~~~~~~~ 202 203 ``onLoadRequest``, which is perhaps the most important, can be used by the App 204 to intercept page loads. The App can either *deny* the load, which will stop 205 the page from loading, and handle it internally, or *allow* the 206 load, which will load the page in Gecko. ``onLoadRequest`` is called for all 207 page loads, regardless of whether they were initiated by the app itself, by Web 208 content, or as a result of a redirect. 209 210 When the page load originates in Web content, Gecko has to synchronously 211 wait for the Android UI thread to schedule the call to ``onLoadRequest`` and 212 for the App to respond. This normally takes a negligible amount of time, but 213 when the Android UI thread is busy, e.g. because the App is being painted for 214 the first time, the delay can be substantial. This is an area of GeckoView that 215 we are actively trying to improve. 216 217 onLoadError 218 ~~~~~~~~~~~ 219 220 ``onLoadError`` is called whenever the page does not load correctly, e.g. 221 because of a network error or a misconfigured HTTPS server. The App can return 222 a URL to a local HTML file that will be used as error page internally by Gecko. 223 224 onLocationChange 225 ~~~~~~~~~~~~~~~~ 226 227 ``onLocationChange`` is called whenever Gecko commits to a navigation and the 228 URL can safely displayed in the URL bar. 229 230 onSessionStateChange 231 ~~~~~~~~~~~~~~~~~~~~ 232 233 ``onSessionStateChange`` is called whenever any piece of the session state 234 changes, e.g. form content, scrolling position, zoom value, etc. Changes are 235 batched to avoid calling this API too frequently. 236 237 Apps can use ``onSessionStateChange`` to store the serialized state to 238 disk to support restoring the session at a later time. 239 240 Third-party root certificates 241 ----------------------------- 242 243 Gecko maintains its own Certificate Authority store and does not use the 244 platform's CA store. GeckoView follows the same policy and will not, by 245 default, read Android's CA store to determine root certificates. 246 247 However, GeckoView provides a way to import all third-party CA roots added to 248 the Android CA store by setting the `enterpriseRootsEnabled 249 <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#enterpriseRootsEnabled(boolean)>`_ 250 runtime setting to ``true``, this feature is implemented in `EnterpriseRoots 251 <https://searchfox.org/mozilla-central/rev/26a6a38fb515dbab0bb459c40ec4b877477eefef/mobile/android/geckoview/src/main/java/org/mozilla/gecko/EnterpriseRoots.java>`_ 252 253 There is not currently any API for an app to manually specify additional CA 254 roots, although this might change with `Bug 1522162 255 <https://bugzilla.mozilla.org/show_bug.cgi?id=1522162>`_. 256 257 Lite and Omni builds 258 --------------------- 259 260 A variation of the default GeckoView build, dubbed `Omni` in the codebase, 261 provides additional libraries that can be helpful when building a browser app. 262 Currently, the `Glean 263 <https://docs.telemetry.mozilla.org/concepts/glean/glean.html>`_ library is 264 included in the ``geckoview-omni`` package. The default build ``geckoview``, 265 which does not contain such libraries, is similarly dubbed `Lite` in the 266 codebase. 267 268 The additional libraries in the Omni package are directly built into Gecko's 269 main ``.so`` file, ``libxul.so``. These libraries are then declared in the 270 ``.module`` package inside the ``maven`` repository, e.g. see the ``.module`` 271 file for `geckoview-omni 272 <https://maven.mozilla.org/maven2/org/mozilla/geckoview/geckoview-omni/102.0.20220623063721/geckoview-omni-102.0.20220623063721.module>`_: 273 274 .. code-block:: json 275 276 "capabilities": [ 277 { 278 "group": "org.mozilla.geckoview", 279 "name": "geckoview-omni", 280 "version": "102.0.20220623063721" 281 }, 282 { 283 "group": "org.mozilla.telemetry", 284 "name": "glean-native", 285 "version": "44.1.1" 286 } 287 ] 288 289 Notice the ``org.mozilla.telemetry:glean-native`` capability is declared 290 alongside ``org.mozilla.geckoview``. 291 292 The main Glean library then depends on ``glean-native`` which is either 293 provided in a standalone package (for apps that do not include GeckoView) or by 294 the GeckoView capability above. 295 296 In Treeherder, the Lite build is denoted with ``Lite``, while the Omni builds 297 don't have extra denominations as they are the default build, so e.g. for 298 ``x86_64`` the platform names would be: 299 300 - ``Android 7.0 x86-64`` for the Omni build 301 - ``Android 7.0 x86-64 Lite`` for the Lite build 302 303 Extensions 304 ---------- 305 306 Extensions can be installed using ``WebExtensionController::install`` and 307 ``WebExtensionController::installBuiltIn``, which asynchronously returns a 308 ``WebExtension`` object that can be used to set delegates for 309 extension-specific behavior. 310 311 The ``WebExtension`` object is immutable, and will be replaced every time a 312 property changes. For instance, to disable an extension, apps can use the 313 ``disable`` method, which will return an updated version of the 314 ``WebExtension`` object. 315 316 Internally, all ``WebExtension`` objects representing one extension share the 317 same delegates, which are stored in ``WebExtensionController``. 318 319 Given the extensive sprawling amount of data associated to extensions, 320 extension installation persists across restarts. Existing extensions can be 321 listed using ``WebExtensionController::list``. 322 323 In addition to ordinary WebExtension APIs, GeckoView allows ``builtIn`` 324 extensions to communicate to the app via native messaging. Apps can register 325 themselves as native apps and extensions will be able to communicate to the app 326 using ``connectNative`` and ``sendNativeMessage``. Further information can be 327 found `here <../consumer/web-extensions.html>`__. 328 329 Internals 330 ========= 331 332 The following sections describe how Gecko and GeckoView are implemented. These 333 parts of GeckoView are not normally exposed to embedders. 334 335 Process Model 336 ------------- 337 338 Internally, Gecko uses a multi-process architecture, most of the chrome code 339 runs in the *main* process, while content code runs in *child* processes also 340 called *content* processes. There are additional types of specialized processes 341 like the *socket* process, which runs parts of the networking code, the *gpu* 342 process which executes GPU commands, the *extension* process which runs most 343 extension content code, etc. 344 345 We intentionally do not expose our process model to embedders. 346 347 To learn more about the multi-process architecture see `Fission for GeckoView 348 engineers <https://gist.github.com/agi/c900f3e473ff681158c0c907e34780e4>`_. 349 350 The majority of the GeckoView Java code runs on the main process, with a thin 351 glue layer on the child processes, mostly contained in ``GeckoThread``. 352 353 Process priority on Android 354 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 355 356 On Android, each process is assigned a given priority. When the device is 357 running low on memory, or when the system wants to conserve resources, e.g. 358 when the screen has been off for a long period of time, or the battery is low, 359 Android will sort all processes in reverse priority order and kill, using a 360 ``SIGKILL`` event, enough processes until the given free memory and resource 361 threshold is reached. 362 363 Processes that are necessary to the function of the device get the highest 364 priority, followed by apps that are currently visible and focused on the 365 screen, then apps that are visible (but not on focus), background processes and 366 so on. 367 368 Processes that do not have a UI associated to it, e.g. background services, 369 will normally have the lowest priority, and thus will be killed most 370 frequently. 371 372 To increase the priority of a service, an app can ``bind`` to it. There are 373 three possible ``bind`` priority values 374 375 - ``BIND_IMPORTANT``: The process will be *as important* as the process binding 376 to it 377 - default priority: The process will have lower priority than the process 378 binding to it, but still higher priority than a background service 379 - ``BIND_WAIVE_PRIORITY``: The bind will be ignored for priority 380 considerations. 381 382 It's important to note that the priority of each service is only relative to 383 the priority of the app binding to it. If the app is not visible, the app 384 itself and all services attached to it, regardless of binding, will get 385 background priority (i.e. the lowest possible priority). 386 387 Process management 388 ~~~~~~~~~~~~~~~~~~ 389 390 Each Gecko process corresponds to an Android ``service`` instance, which has to 391 be declared in GeckoView's ``AndroidManifest.xml``. 392 393 For example, this is the definition of the ``media`` process: 394 395 .. rstcheck: ignore-languages=xml 396 .. code-block:: xml 397 398 <service 399 android:name="org.mozilla.gecko.media.MediaManager" 400 android:enabled="true" 401 android:exported="false" 402 android:isolatedProcess="false" 403 android:process=":media"> 404 405 Process creation is controlled by Gecko which interfaces to Android using 406 ``GeckoProcessManager``, which translates Gecko's priority to Android's 407 ``bind`` values. 408 409 Because all priorities are waived when the app is in the background, it's not 410 infrequent that Android kills some of GeckoView's services, while still leaving 411 the main process alive. 412 413 It is therefore very important that Gecko is able to recover from process 414 disappearing at any moment at runtime. 415 416 Priority Hint 417 ~~~~~~~~~~~~~ 418 419 Internally, GeckoView ties the lifetime of the ``Surface`` associated to a 420 ``GeckoSession`` and the process priority of the process where the session 421 lives. 422 423 The underlying assumption is that a session that is not visible doesn't have a 424 surface associated to it and it's not being used by the user so it shouldn't 425 receive high priority status. 426 427 The way this is implemented is `by setting 428 <https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java#114,123>`_ 429 the ``active`` property on the ``browser`` object to ``false``, which causes 430 Gecko to de-prioritize the process, assuming that no other windows in the same 431 process have ``active=true``. See also `GeckoDisplay`_. 432 433 However, there are use cases where just looking at the surface is not enough. 434 For instance, when the user opens the settings menu, the currently selected tab 435 becomes invisible, but the user will still expect the browser to retain that 436 tab state with a higher priority than all the other tabs. Similarly, when the 437 browser is put in the background, the surface associated to the current tab 438 gets destroyed, but the current tab is still more important than the other 439 tabs, but because it doesn't have a surface associated to it, we have no way to 440 differentiate it from all the other tabs. 441 442 To solve the above problem, we expose an API for consumers to *boost* a session 443 priority, `setPriorityHint 444 <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.html#setPriorityHint(int)>`_. 445 The priority hint is taken into consideration when calculating the 446 priority of a process. Any process that contains either an active session or a 447 session with the priority hint `is boosted 448 <https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/dom/ipc/BrowserParent.cpp#3593>`_ 449 to the highest priority. 450 451 Shutdown 452 -------- 453 454 Android does not provide apps with a notification whenever the app is shutting 455 down. As explained in the section above, apps will simply be killed whenever 456 the system needs to reclaim resources. This means that Gecko on Android will 457 never shutdown cleanly, and that shutdown actions will never execute. 458 459 .. _principals: 460 461 Principals 462 ---------- 463 464 In Gecko, a *website* loaded in a session is represented by an abstraction 465 called `principal 466 <https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/caps/nsIPrincipal.idl>`_. 467 Principals contain information that is used to determine what permissions have 468 been granted to the website instance, what APIs are available to it, which 469 container the page is loaded in, is the page in private browsing or not, etc. 470 471 Principals are used throughout the Gecko codebase, GeckoView, however, does not 472 expose the concept to the API. This is intentional, as exposing it would 473 potentially expose the app to various security sensitive concepts, which would 474 violate the "secure" requirement for the GeckoView API. 475 476 The absence of principals from the API is, e.g., why GeckoView does not offer a 477 way to set permissions given a URL string, as permissions are internally stored 478 by principal. See also `Setting Permissions`_. 479 480 To learn more about principals see `this talk by Bobby Holley 481 <https://www.youtube.com/watch?v=28FPetl5Fl4>`_. 482 483 Window model 484 ------------ 485 486 Internally, Gecko has the concept of *window* and *tab*. Given that GeckoView 487 doesn't have the concept of tab (since it might be used to build something that 488 is *not* a browser) we hide Gecko tabs from the GeckoView API. 489 490 Each ``GeckoSession`` corresponds to a Gecko ``window`` object with exactly one 491 ``tab`` in it. Because of this you might see ``window`` and ``session`` used 492 interchangeably in the code. 493 494 Internally, Gecko uses ``window`` s for other things other than 495 ``GeckoSession``, so we have to sometime be careful about knowing which windows 496 belong to GeckoView and which don't. For example, the background extension page 497 is implemented as a ``window`` object that doesn't paint to a surface. 498 499 EventDispatcher 500 --------------- 501 502 The GeckoView codebase is written in C++, JavaScript and Java, it runs across 503 processes and often deals with asynchronous and garbage-collected code with 504 complex lifetime dependencies. To make all of this work together, GeckoView 505 uses a cross-language event-driven architecture. 506 507 The main orchestrator of this event-driven architecture is ``EventDispatcher``. 508 Each language has an implementation of ``EventDispatcher`` that can be used to 509 fire events that are reachable from any language. 510 511 Each window (i.e. each session) has its own ``EventDispatcher`` instance, which 512 is also present on the content process. There is also a global 513 ``EventDispatcher`` that is used to send and receive events that are not 514 related to a specific session. 515 516 Events can have data associated to it, which is represented as a 517 ``GeckoBundle`` (essentially a ``String``-keyed variant map) on the Java and 518 C++ side, and a plain object on the JavaScript side. Data is automatically 519 converted back and forth by ``EventDispatcher``. 520 521 In Java, events are fired in the same thread where the listener was registered, 522 which allows us to ensure that events are received in a consistent order and 523 data is kept consistent, so that we by and large don't have to worry about 524 multi-threaded issues. 525 526 JNI 527 --- 528 529 GeckoView code uses the Java Native Interface or JNI to communicate between 530 Java and C++ directly. Our JNI exports are generated from the Java source code 531 whenever the ``@WrapForJNI`` annotation is present. For non-GeckoView code, the 532 list of classes for which we generate imports is defined at 533 ``widget/android/bindings``. 534 535 The lifetime of JNI objects depends on their native implementation: 536 537 - If the class implements ``mozilla::SupportsWeakPtr``, the Java object will 538 store a ``WeakPtr`` to the native object and will not own the lifetime of the 539 object. 540 - If the class implements ``AddRef`` and ``Release`` from ``nsISupports``, the 541 Java object will store a ``RefPtr`` to the native object and will hold a 542 strong reference until the Java object releases the object using 543 ``DisposeNative``. 544 - If neither cases apply, the Java object will store a C++ pointer to the 545 native object. 546 547 Calling Runtime delegates from native code 548 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 549 550 Runtime delegates can be reached directly using the ``GeckoRuntime`` singleton. 551 A common pattern is to expose a ``@WrapForJNI`` method on ``GeckoRuntime`` that 552 will call the delegate, that than can be used on the native side. E.g. 553 554 .. code:: java 555 556 @WrapForJNI 557 private void featureCall() { 558 ThreadUtils.runOnUiThread(() -> { 559 if (mFeatureDelegate != null) { 560 mFeatureDelegate.feature(); 561 } 562 }); 563 } 564 565 And then, on the native side: 566 567 .. code:: cpp 568 569 java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance(); 570 if (runtime != nullptr) { 571 runtime->FeatureCall(); 572 } 573 574 Session delegates 575 ~~~~~~~~~~~~~~~~~ 576 577 ``GeckoSession`` delegates require a little more care, as there's a copy of a 578 delegate for each ``window``. Normally, a method on ``android::nsWindow`` is 579 added which allows Gecko code to call it. A reference to ``nsWindow`` can be 580 obtained from a ``nsIWidget`` using ``nsWindow::From``: 581 582 .. code:: cpp 583 584 RefPtr<nsWindow> window = nsWindow::From(widget); 585 window->SessionDelegateFeature(); 586 587 The ``nsWindow`` implementation can then forward the call to 588 ``GeckoViewSupport``, which is the JNI native side of ``GeckoSession.Window``. 589 590 .. code:: cpp 591 592 void nsWindow::SessionDelegateFeature() { 593 auto acc(mGeckoViewSupport.Access()); 594 if (!acc) { 595 return; 596 } 597 acc->SessionDelegateFeature(aResponse); 598 } 599 600 Which can in turn forward the call to the Java side using the JNI stubs. 601 602 .. code:: cpp 603 604 auto GeckoViewSupport::SessionDelegateFeature() { 605 GeckoSession::Window::LocalRef window(mGeckoViewWindow); 606 if (!window) { 607 return; 608 } 609 window->SessionDelegateFeature(); 610 } 611 612 And finally, the Java implementation calls the session delegate. 613 614 .. code:: java 615 616 @WrapForJNI 617 private void sessionDelegateFeature() { 618 final GeckoSession session = mOwner.get(); 619 if (session == null) { 620 return; 621 } 622 ThreadUtils.postToUiThread(() -> { 623 final FeatureDelegate delegate = session.getFeatureDelegate(); 624 if (delegate == null) { 625 return; 626 } 627 delegate.feature(); 628 }); 629 } 630 631 .. _permissions: 632 633 Permissions 634 ----------- 635 636 There are two separate but related permission concepts in GeckoView: `Content` 637 permissions and `Android` permissions. See also the related `consumer doc 638 <../consumer/permissions.html>`_ on permissions. 639 640 Content permissions 641 ~~~~~~~~~~~~~~~~~~~ 642 643 Content permissions are granted to individual web sites (more precisely, 644 `principals`_) and are managed internally using ``nsIPermissionManager``. 645 Content permissions are used by Gecko to keep track which website is allowed to 646 access a group of Web APIs or functionality. The Web has the concept of 647 permissions, but not all Gecko permissions map to Web-exposed permissions. 648 649 For instance, the ``Notification`` permission, which allows websites to fire 650 notifications to the user, is exposed to the Web through 651 `Notification.requestPermission 652 <https://developer.mozilla.org/en-US/docs/Web/API/Notification/requestPermission>`_, 653 while the `autoplay` permission, which allows websites to play video and audio 654 without user interaction, is not exposed to the Web and websites have no way to 655 set or request this permission. 656 657 GeckoView retains content permission data, which is an explicit violation of 658 the design principle of not storing data. This is done because storing 659 permissions is very complex, making a mistake when dealing with permissions 660 often ends up being a security vulnerability, and because permissions depend on 661 concepts that are not exposed to the GeckoView API like `principals`_. 662 663 Android permissions 664 ~~~~~~~~~~~~~~~~~~~ 665 666 Consumers of GeckoView are Android apps and therefore they have to receive 667 permission to use certain features on behalf of websites. 668 669 For instance, when a website requests Geolocation permission for the first 670 time, the app needs to request the corresponding Geolocation Android permission 671 in order to receive position data. 672 673 You can read more about Android permissions on `this doc 674 <https://developer.android.com/guide/topics/permissions/overview>`_. 675 676 677 Implementation 678 ~~~~~~~~~~~~~~ 679 680 The main entry point from Gecko is ``nsIContentPermissionPrompt.prompt``, which 681 is handled in the `Permission module 682 <https://searchfox.org/mozilla-central/rev/256f84391cf5d4e3a4d66afbbcd744a5bec48956/mobile/android/components/geckoview/GeckoViewPermission.jsm#21>`_ 683 in the same process where the request is originated. 684 685 The permission module calls the child actor `GeckoViewPermission 686 <https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/actors/GeckoViewPermissionChild.jsm#47>`_ 687 which issues a `GeckoView:ContentPermission 688 <https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/actors/GeckoViewPermissionChild.jsm#75>`_ 689 request to the Java front-end as needed. 690 691 Media permissions are requested using a global observer, and therefore are 692 handled in a `Process actor 693 <https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/actors/GeckoViewPermissionProcessChild.jsm#41>`_, 694 media permissions requests have enough information to redirect the request to 695 the corresponding window child actor, with the exception of requests that are 696 not associated with a window, which are redirected to the `current active 697 window 698 <https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/actors/GeckoViewPermissionProcessParent.jsm#28-35>`_. 699 700 Setting permissions 701 ~~~~~~~~~~~~~~~~~~~ 702 703 Permissions are stored in a map between a `principal <#principals>`_ and a list 704 of permission (key, value) pairs. To prevent security vulnerabilities, GeckoView 705 does not provide a way to set permissions given an arbitrary URL and requires 706 consumers to get hold of the `ContentPermission 707 <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.ContentPermission.html>`_ 708 object. The ContentPermission object is returned in `onLocationChange 709 <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.NavigationDelegate.html#onLocationChange(org.mozilla.geckoview.GeckoSession,java.lang.String,java.util.List)>`_ 710 upon navigation, making it unlikely to have confusion bugs whereby the 711 permission is given to the wrong website. 712 713 Internally, some permissions are only present when a certain override is set, 714 e.g. Tracking Protection override permissions are only present when the page 715 has been given a TP override. Because the only way to set the value of a 716 permission is to get hold of the ``ContentPermission`` object, `we manually insert 717 <https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/mobile/android/modules/geckoview/GeckoViewNavigation.jsm#605-625>`_ 718 a `trackingprotection` permission on every page load. 719 720 Autofill Support 721 ---------------- 722 723 GeckoView supports third-party autofill providers through Android's `autofill framework <https://developer.android.com/guide/topics/text/autofill>`_. Internally, this support is referred to as `autofill`. 724 725 Document tree 726 ~~~~~~~~~~~~~ 727 728 The autofill Java front-end is located in the `Autofill class 729 <https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/Autofill.java#37>`_. 730 GeckoView maintains a virtual tree structure of the current document for each 731 ``GeckoSession``. 732 733 The virtual tree structure is composed of `Node 734 <https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/Autofill.java#593>`_ 735 objects which are immutable. Data associated to a node, including mutable data 736 like the current value, is stored in a separate `NodeData 737 <https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/Autofill.java#171>`_ 738 class. Only HTML nodes that are relevant to autofilling are referenced in the 739 virtual structure and each node is associated to a root node, e.g. the root 740 ``<form>`` element. All root nodes are children of the autofill `mRoot 741 <https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/Autofill.java#210>`_ 742 node, hence making the overall structure a tree rather than a collection of 743 trees. Note that the root node is the only node in the virtual structure that 744 does not correspond to an actual element on the page. 745 746 Internally, nodes are assigned a unique ``UUID`` string, which is used to match 747 nodes between the Java front-end and the data stored in GeckoView's chrome 748 Javascript. The autofill framework itself requires integer IDs for nodes, so we 749 store a mapping between UUIDs and integer IDs in the associated ``NodeData`` 750 object. The integer IDs are used only externally, while internally only the 751 UUIDs are used. The reason why we use a separate ID structure from the autofill 752 framework is that this allows us to `generate UUIDs 753 <https://searchfox.org/mozilla-central/rev/7e34cb7a0094a2f325a0c9db720cec0a2f2aca4f/mobile/android/actors/GeckoViewAutoFillChild.jsm#217-220>`_ 754 directly in the isolated content processes avoiding an IPC roundtrip to the 755 main process. 756 757 Each ``Node`` object is associated to an ``EventCallback`` object which is 758 invoked whenever the node is autofilled by the autofill framework. 759 760 Detecting autofillable nodes 761 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 762 763 GeckoView scans every web page for password ``<input>`` elements whenever the 764 ``pageshow`` event `fires 765 <https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/actors/GeckoViewAutoFillChild.jsm#74-78>`_. 766 767 It also uses ``DOMFormHasPassword`` and ``DOMInputPasswordAdded`` to detect 768 whenever a password element is added to the DOM after the ``pageshow`` event. 769 770 Prefs 771 ----- 772 773 `Preferences </modules/libpref/index.html>`_ (or prefs) are used throughout 774 Gecko to configure the browser, enable custom features, etc. 775 776 GeckoView does not directly expose prefs to Apps. A limited set configuration 777 options is exposed through ``GeckoRuntimeSettings``. 778 779 ``GeckoRuntimeSettings`` can be easily mapped to a Gecko ``pref`` using 780 ``Pref``, e.g. 781 782 .. code:: java 783 784 /* package */ final Pref<Boolean> mPrefExample = 785 new Pref<Boolean>("example.pref", false); 786 787 The value of the pref can then be read internally using ``mPrefExample.get`` 788 and written to using ``mPrefExample.commit``. 789 790 Front-end and back-end 791 ---------------------- 792 793 |code-layers| 794 795 Gecko and GeckoView code can be divided in five layers: 796 797 - **Java API** the outermost code layer that is publicly accessible to 798 GeckoView embedders. 799 - **Java Front-End** All the Java code that supports the API and talks directly 800 to the Android APIs and to the JavaScript and C++ front-ends. 801 - **JavaScript Front-End** The main interface to the Gecko back-end (or Gecko 802 proper) in GeckoView is JavaScript, we use this layer to call into Gecko and 803 other utilities provided by Gecko, code lives in ``mobile/android`` 804 - **C++ Front-End** A smaller part of GeckoView is written in C++ and interacts 805 with Gecko directly, most of this code is lives in ``widget/android``. 806 - **C++/Rust Back-End** This is often referred to as "platform", includes all 807 core parts of Gecko and is usually accessed to in GeckoView from the C++ 808 front-end or the JavaScript front-end. 809 810 Modules and Actors 811 ------------------ 812 813 GeckoView's JavaScript Front-End is largely divided into units called modules 814 and actors. For each feature, each window will have an instance of a Module, a 815 parent-side Actor and (potentially many) content-side Actor instances. For a 816 detailed description of this see `here <https://gist.github.com/agi/c900f3e473ff681158c0c907e34780e4#actors>`__. 817 818 Testing infrastructure 819 ---------------------- 820 821 For a detailed description of our testing infrastructure see `GeckoView junit 822 Test Framework <junit.html>`_. 823 824 .. |api-diagram| image:: ../assets/api-diagram.png 825 .. |view-runtime-session| image:: ../assets/view-runtime-session.png 826 .. |pageload-diagram| image:: ../assets/pageload-diagram.png 827 .. |code-layers| image:: ../assets/code-layers.png