# Technical Documentation: BrowserWorks/waterfox

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/BrowserWorks/waterfox)

### Overview (README.md)

# Waterfox

Waterfox is a customisable browser based on Mozilla Firefox. This repository contains Mozilla platform code, Waterfox product code, branding, features, packaging, and release files.

## Building

Waterfox uses the Mozilla build system. The usual `./mach` entry points apply:

```sh
./mach bootstrap
./mach build
./mach package
./mach test --auto
```

## Contributing

Most Firefox development documentation still applies to this tree. Use the Firefox Source Docs for the shared Mozilla build system, testing tools, and platform code.

## Resources

- [Waterfox website](https://www.waterfox.net/)
- [Firefox Source Docs](https://firefox-source-docs.mozilla.org/)

---

### Metrics Index (`docs/metrics/index.md`)

# Metrics

The metrics collected by Firefox using the
[Glean SDK](https://mozilla.github.io/glean/book/index.html)
are documented in
[The Glean Dictionary](https://dictionary.telemetry.mozilla.org/apps/firefox_desktop/).

---

### Performance Index (`docs/performance/index.md`)

# Performance

This page explains how to optimize the performance of the Firefox code base.

The [test documentation](/testing/perfdocs/index.rst)
explains how to test for performance in Firefox.
The [profiler documentation](/tools/profiler/index.rst)
explains how to use the Gecko profiler.

```{toctree}
:hidden:
:glob:

*
memory/*
```

## General Performance references

* Tips on generating valid performance metrics by [benchmarking](Benchmarking.md)
* [GPU Performance](GPU_performance.md) Tips for reducing impacts on browser performance in front-end code.
* [Automated Performance testing and Sheriffing](automated_performance_testing_and_sheriffing.md) Information on automated performance testing and sheriffing at Mozilla.
* [Performance best practices for Firefox front-end engineers](bestpractices.md) Tips for reducing impacts on browser performance in front-end code.
* [Reporting a performance problem](reporting_a_performance_problem.md) A user friendly guide to reporting a performance problem. A development environment is not required.
* [Scroll Linked Effects](scroll-linked_effects.md) Information on scroll-linked effects, their effect on performance, related tools, and possible mitigation techniques.

## Memory profiling and leak detection tools

* The [Developer Tools Memory panel](memory/memory.md) supports taking heap snapshots, diffing them, computing dominator trees to surface "heavy retainers", and recording allocation stacks.
* [About:memory](memory/about_colon_memory.md) about:memory is the easiest-to-use tool for measuring memory usage in Mozilla code, and is the best place to start. It also lets you do other memory-related operations like trigger GC and CC, dump GC & CC logs, and dump DMD reports. about:memory is built on top of Firefox's [memory reporting](memory/memory_reporting.md) infrastructure.
* [DMD](memory/dmd.md) is a tool that identifies shortcomings in about:memory's measurements, and can also do multiple kinds of general heap profiling.
* [AWSY](memory/awsy.md) (are we slim yet?) is a memory usage and regression tracker.
* [Bloatview](memory/bloatview.md) prints per-class statistics on allocations and refcounts, and provides gross numbers on the amount of memory being leaked broken down by class. It is used as part of Mozilla's continuous integration testing.
* [Refcount Tracing and Balancing](memory/refcount_tracing_and_balancing.md) are ways to track down leaks caused by incorrect uses of reference counting. They are slow and not particular easy to use, and thus most suitable for use by expert developers.
* [GC and CC Logs](memory/gc_and_cc_logs.md)
* [LogAlloc](https://searchfox.org/firefox-main/source/memory/replace/logalloc/README) is a tool that dumps a log of memory allocations in Gecko. That log can then be replayed against Firefox's default memory allocator independently or through another replace-malloc library, allowing the testing of other allocators under the exact same workload.
* [See also the documentation on Leak-hunting strategies and tips.](memory/leak_hunting_strategies_and_tips.md)

## Profiling and performance tools

* [JIT Profiling with perf](jit_profiling_with_perf.md) Using perf to collect JIT profiles.
* [JIT Profiling with samply](jit_profiling_with_samply.md) Using samply to collect JIT profiles
* [Profiling with simpleperf](profiling_with_simpleperf.md) `simpleperf` is the Android equivalent of Linux's `perf`
* [Profiling with Instruments](profiling_with_instruments.md) How to use Apple's Instruments tool to profile Mozilla code.
* [Profiling with xperf](profiling_with_xperf.md) How to use Microsoft's Xperf tool to profile Mozilla code.
* [Profiling with Concurrency Visualizer](profiling_with_concurrency_visualizer.md) How to use Visual Studio's Concurrency Visualizer tool to profile Mozilla code.
* [Profiling with Zoom](profiling_with_zoom.md) Zoom is a profiler for Linux done by the people who made Shark.
* [Adding a new telemetry probe](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/start/adding-a-new-probe.html) Information on how to add a new measurement to the Telemetry performance-reporting system

## Power Profiling

* [An overview of power profiling](power_profiling_overview.md). It includes details about hardware, what can be measured, and recommended approaches. It should be the starting point for anybody new to power profiling.
* **(Mac, Linux)** [tools/power/rapl](tools_power_rapl.md) is a command-line utility in the Mozilla codebase that uses the Intel RAPL interface to gather direct power estimates for the package, cores, GPU and memory.
* **(Mac-only)** [powermetrics](powermetrics.md) is a command-line utility that gathers and displays a wide range of global and per-process measurements, including CPU usage, GPU usage, and various wakeups frequencies.
* **(All-platforms)** [TimerFirings](timerfirings_logging.md) logging is a built-in logging mechanism that prints data on every time fired.
* **(Mac-only)** [Activity Monitor and top](activity_monitor_and_top.md) The battery status menu, Activity Monitor and top are three related Mac tools that have major flaws but often consulted by users, and so are worth understanding.
* **(Windows, Mac and Linux)** [Intel Power Gadget](intel_power_gadget.md) Intel Power Gadget provides real-time graphs for package and processor RAPL estimates. It also provides an API through which those estimates can be obtained.
* **(Linux only)** [perf](perf.md) perf is a powerful command-line utility that can measure many different things, including energy estimates and high-context measurements of things such as wakeups.
* **(Linux-only)** [turbostat](turbostat.md) is a command-line utility that gathers and displays various power-related measurements, with a focus on per-CPU measurements such as frequencies and C-states.
* **(Linux-only)** [powertop](https://01.org/powertop) is an interactive command-line utility that gathers and displays various power-related measurements.

## Performance Metrics

* [PerfStats](perfstats.md) - A framework for low-overhead collection of internal performance metrics.

---

### Performance Power Profiling Overview (`docs/performance/power_profiling_overview.md`)

# Power profiling

This article covers important background information about power
profiling, with an emphasis on Intel processors used in desktop and
laptop machines. It serves as a starting point for anybody doing power
profiling for the first time.

## Basic physics concepts

In physics, *[power](https://en.wikipedia.org/wiki/Power_%28physics%29)*
is the rate of doing
*[work](https://en.wikipedia.org/wiki/Work_%28physics%29 "Work (physics)")*.
It is equivalent to an amount of
*[energy](https://en.wikipedia.org/wiki/Energy_%28physics%29 "Energy (physics)"){.mw-redirect}*
consumed per unit time. In SI units, energy is measured in Joules, and
power is measured in Watts, which is equivalent to Joules per second.

Although power is an instantaneous concept, in practice measurements of
it are determined in a non-instantaneous fashion, i.e. by dividing an
energy amount by a non-infinitesimal time period. Strictly speaking,
such a computation gives the *average power* but this is often referred
to as just the *power* when context makes it clear.

In the context of computing, a fully-charged mobile device battery (as
found in a laptop or smartphone) holds a certain amount of energy, and
the speed at which that stored energy is depleted depends on the power
consumption of the mobile device. That in turn depends on the software
running on the device. Web browsers are popular applications and can be
power-intensive, and therefore can significantly affect battery life. As
a result, it is worth optimizing (i.e. reducing) the power consumption
caused by Firefox and Firefox OS.

## Intel processor basics

### Processor layout

The following diagram (from the [Intel Power Governor
documentation)](https://software.intel.com/en-us/articles/intel-power-governor)
shows how machines using recent Intel processors are constructed.



The important points are as follows.

- The processor has one or more *packages*. These are part of the
  actual processor that you buy from Intel. Client processors (e.g.
  Core i3/i5/i7) have one package. Server processors (e.g. Xeon)
  typically have two or more packages.
- Each package contains multiple *cores*.
- Each core typically has
  [hyper-threading](https://en.wikipedia.org/wiki/Hyper-threading),
  which means it contains two logical *CPUs*.
- The part of the package outside the cores is called the [*uncore* or
  *system agent*](https://en.wikipedia.org/wiki/Uncore)*.* It includes
  various components including the L3 cache, memory controller, and,
  for processors that have one, the integrated GPU.
- RAM is separate from the processor.

### C-states

Intel processors have aggressive power-saving features. The first is the
ability to switch frequently (thousands of times per second) between
active and idle states, and there are actually several different kinds
of idle states. These different states are called
*[C-states](https://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface#Processor_states).*
C0 is the active/busy state, where instructions are being executed. The
other states have higher numbers and reflect increasing deeper idle
states. The deeper an idle state is, the less power it uses, but the
longer it takes to wake up from.

Note: the [ACPI
standard](https://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface)
specifies four states, C0, C1, C2 and C3. Intel maps these to
processor-specific states such as C0, C1, C2, C6 and C7. and many tools
report C-states using the latter names. The exact relationship is
confusing, and chapter 13 of the [Intel optimization
manual](http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html)
has more details. The important thing is that C0 is always the active
state, and for the idle states a higher number always means less power
consumption.

The other thing to note about C-states is that they apply both to cores
and the entire package --- i.e. if all cores are idle then the entire
package can also become idle, which reduces power consumption even
further.

The fraction of time that a package or core spends in an idle C-state is
called the *C-state residency*. This is a misleading term --- the active
state, C0, is also a C-state --- but one that is nonetheless common.

Intel processors have model-specific registers (MSRs) containing
measurements of how much time is spent in different C-states, and tools
such as [powermetrics](powermetrics.md)
(Mac), powertop and
[turbostat](turbostat.md) (Linux) can
expose this information.

A *wakeup* occurs when a core or package transitions from an idle state
to the active state. This happens when the OS schedules a process to run
due to some kind of event. Common causes of wakeups include scheduled
timers going off and blocked I/O system calls receiving data.
Maintaining C-state residency is crucial to keep power consumption low,
and so reducing wakeup frequency is one of the best ways to reduce power
consumption.

One consequence of the existence of C-states is that observations made
during power profiling --- even more than with other kinds of profiling
--- can disturb what is being observed. For example, the Gecko Profiler
takes samples at 1000Hz using a timer. Each of these samples can trigger
a wakeup, which consumes power and obscures Firefox's natural wakeup
patterns. For this reason, integrating power measurements into the Gecko
Profiler is unlikely to be useful, and other power profiling tools
typically use much lower sampling rates (e.g. 1Hz.)

### P-states

Intel processors also support multiple *P-states*. P0 is the state where
the processor is operating at maximum frequency and voltage, and
higher-numbered P-states operate at a lower frequency and voltage to
reduce power consumption. Processors can have dozens of P-states, but
the transitions are controlled by the hardware and OS and so P-states
are of less interest to application developers than C-states.

## Power and power-related measurements

There are several kinds of power and power-related measurements. Some
are global (whole-system) and some are per-process. The following
sections list them from best to worst.

### Power measurements

The best measurements are measured in joules and/or watts, and are taken
by measuring the actual hardware in some fashion. These are global
(whole-system) measurements that are affected by running programs but
also by other things such as (for laptops) how bright the monitor
backlight is.

- Devices such as ammeters give the best results, but these can be
  expensive and difficult to set up.
- A cruder technique that works with mobile machines and devices is to
  run a program for a long time and simply time how long it takes for
  the battery to drain. The long measurement times required are a
  disadvantage, though.

### Power estimates

The next best measurements come from recent (Sandy Bridge and later)
Intel processors that implement the *RAPL* (Running Average Power Limit)
interface that provides MSRs containing energy consumption estimates for
up to four *power planes* or *domains* of a machine, as seen in the
diagram above.

- PKG: The entire package.
  - PP0: The cores.
  - PP1: An uncore device, usually the GPU (not available on all
    processor models.)
- DRAM: main memory (not available on all processor models.)

The following relationship holds: PP0 + PP1 \<= PKG. DRAM is independent
of the other three domains.

These values are computed using a power model that uses
processor-internal counts as inputs, and they have been
[verified](http://www.computer.org/csdl/proceedings/ispass/2013/5776/00/06557170.pdf)
as being fairly accurate. They are also updated frequently, at
approximately 1,000 Hz, though the variability in their update latency
means that they are probably only accurate at lower frequencies, e.g. up
to 20 Hz or so. See section 14.9 of Volume 3 of the [Intel Software
Developer's
Manual](http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html)
for more details about RAPL.

Tools that can take RAPL readings include the following.

- `tools/power/rapl`: all planes; Linux and Mac.
- [Intel Power
  Gadget](intel_power_gadget.md): PKG and
  PP0 planes; Windows, Mac and Linux.
- [powermetrics](powermetrics.md): PKG
  plane; Mac.
- [perf](perf.md): all planes; Linux.
- [turbostat](turbostat.md): PKG, PP0 and
  PP1 planes; Linux.

Of these,
[tools/power/rapl](tools_power_rapl.md) is
generally the easiest and best to use because it reads all power planes,
it's a command line utility, and it doesn't measure anything else.

### Proxy measurements

The next best measurements are proxy measurements, i.e. measurements of
things that affect power consumption such as CPU activity, GPU activity,
wakeup frequency, C-state residency, disk activity, and network
activity. Some of these are measured on a global basis, and some can be
measured on a per-process basis. Some can also be measured via
instrumentation within Firefox itself.

The correlation between each proxy measure and power consumption is hard
to know and can vary greatly. When used carefully, however, they can
still be useful. This is because they can often be measured in a more
fine-grained fashion than power measurements and estimates, which is
vital for gaining insight into how a program can reduce power
consumption.

Most profiling tools provide at least some proxy measurements.

### Hybrid proxy measurements

These are combinations of proxy measurements. The combinations are
semi-arbitrary, they amplify the unreliability of proxy measurements,
and unlike non-hybrid proxy measurements, they don't have a clear
physical meaning. Avoid them.

The most notable example of a hybrid proxy measurement is the ["Energy
Impact" used by OS X's Activity
[Monitor](activity_monitor_and_top.md#What-does-Energy-Impact-measure).

## Ways to user power-related measurements

### Low-context measurements

Most power-related measurements are global or per-process. Such
low-context measurements are typically good for understand *if* power
consumption is good or bad, but in the latter case they often don't
provide much insight into why the problem is occurring, which part of
the code is at fault, or how it can be fixed. Nonetheless, they can
still help improve understanding of a problem by using *differential
profiling*.

- Compare browsers to see if Firefox is doing better or worse than
  another browser on a particular workload.
- Compare different versions of Firefox to see if Firefox has improved
  or worsened over time on a particular workload. This can identify
  specific changes that caused regressions, for example.
- Compare different configurations of Firefox to see if a particular
  feature is affecting things.
- Compare different workloads. This can be particularly useful if the
  workloads only vary slightly. For example, it can be useful to
  gradually remove elements from a web page and see how the
  power-related measurements change. Even just switching a tab from
  the foreground to the background can make a difference.

### High-context measurements

A few power-related measurements can be obtained in a high-context
fashion, e.g. with stack traces that clearly pinpoint specific parts of
the code as being responsible.

- Standard performance profiling tools that measure CPU usage or
  proxies of CPU usage (such as instruction counts) typically provide
  high-context measurements. This is useful because high CPU usage
  typically causes high power consumption.
- Some tools can provide high-context wakeup measurements:
  [dtrace](dtrace.md) (on Mac) and
  [perf](perf.md) (on Linux.)
- Source-level instrumentation, such as [TimerFirings
  logging](timerfirings_logging.md), can
  identify which timers are firing frequently.

## Power profiling how-to

This section aims to put together all the above information and provide
a set of strategies for finding, diagnosing and fixing cases of high
power consumption.

- First of all, all measurements are best done on a quiet machine that
  is running little other than the program of interest. Global
  measurements in particular can be completely skewed and unreliable
  if this is not the case.
- Find or confirm a test case where Firefox's power consumption is
  high. "High" can most easily be gauged by comparing against other
  browsers. Use power measurements or estimates (e.g. via
  [tools/power/rapl](tools_power_rapl.md),
  or `mach power` on Mac, or [Intel Power
  Gadget](intel_power_gadget.md) on
  Windows) for the comparisons. Avoid lower-quality measurements,
  especially Activity Monitor's "Energy Impact".
- Try using differential profiling to narrow down the cause.
  - Try turning hardware acceleration on or off; e10s on or off;
    Flash on or off.
  - Try putting the relevant tab in the foreground vs. in the
    background.
  - If the problem manifests on a particular website, try saving a
    local copy of the site and then manually removing HTML elements
    to see if a particular page feature is causing the problem
- Many power problems are caused by either high CPU usage or high
  wakeup frequency. Use one of the low-context tools to determine if
  this is the case (e.g. on Mac use
  [powermetrics](powermetrics.md).) If
  so, follow that up by using a tool that gives high-context
  measurements, which hopefully will identify the cause of the
  problem.
  - For high CPU usage, many profilers can be used: Firefox's dev
    tools profiler, the Gecko Profiler, or generic performance
    profilers.
  - For high wakeup counts, use
    [dtrace](dtrace.md) or
    [perf](perf.md) or [TimerFirings logging](timerfirings_logging.md).
- On Mac workloads that use graphics, Activity Monitor's "Energy"
  tab can tell you if the high-performance GPU is being used, which
  uses more power than the integrated GPU.
- If neither CPU usage nor wakeup frequency identifies the problem,
  more ingenuity may be needed. Looking at other measurements (C-state
  residency, GPU usage, etc.) may be helpful.
- Animations are sometimes the cause of high power consumption. The
  [animation
  inspector](/devtools-user/page_inspector/how_to/work_with_animations/index.rst#animation-inspector)
  in the Firefox Devtools can identify them. Alternatively, [here is
  an
  explanation](https://bugzilla.mozilla.org/show_bug.cgi?id=1190721#c10)
  of how one developer diagnosed two animation-related problems the
  hard way (which required genuine platform expertise).
- The approximate cause of power problems often isn't that hard to
  find. Fixing them is often the hard part. Good luck.
- If you do fix a problem by improving a proxy measurement, you should
  verify that it also improves a power measurement or estimate. That
  way you know the fix had a genuine effect.

## Further reading

Chapter 13 of the [Intel optimization
manual](http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html)
has many details about optimizing for power consumption. Section 13.5
("Tuning Software for Intelligent Power Consumption") in particular is
worth reading.

---

### Rust Components Index (`docs/rust-components/index.md`)

# Rust Components

This section is meant to make it easier to use and implement cross-platform components written in Rust.

```{toctree}
:titlesonly:
:maxdepth: 2

Topic Guides <topic-guides/index>
API References <api/index>
Developing Rust Components <developing-rust-components/index>
uniffi-bindgen-gecko-js developers guide <uniffi-bindgen-gecko-js-dev-guide/index>
```

---

### Testing Rust Code Index (`docs/testing-rust-code/index.md`)

# Testing & Debugging Rust Code

This page explains how to test and debug Rust code in Firefox.

The [build documentation](/build/buildsystem/rust.rst) explains how to add
new Rust code to Firefox. The [code documentation](/writing-rust-code/index.md)
explains how to write and work with Rust code in Firefox.

## Testing Mozilla crates

Rust code will naturally be tested as part of system tests such as Mochitests.
This section describes the two methods for unit testing of individual Rust
crates. Which method should be used depends on the circumstances.

### Rust tests

If a Mozilla crate has "normal" Rust tests (i.e. `#[test]` functions that run
with `cargo test`), you can add the crate's name to `RUST_TESTS` in
[toolkit/library/rust/moz.build](https://searchfox.org/firefox-main/source/toolkit/library/rust/moz.build).
(Cargo features can be activated for Rust tests by adding them to
`RUST_TEST_FEATURES` in the same file.)

Rust tests are run with `./mach rusttests`. They run on automation in a couple
of `rusttests` jobs, but not on all platforms.

Rust tests have one major restriction: they cannot link against Gecko symbols.
Therefore, Rust tests cannot be used for crates that use Gecko crates like
`nsstring` and `xpcom`.

It's also possible to use `RUST_TESTS` in a different `moz.build` file. See
`testing/geckodriver/moz.build` and the [geckodriver testing docs] for an
example.

[geckodriver testing docs]: /testing/geckodriver/Testing.md

### GTests

Another way to unit test a Mozilla crate is by writing a GTest that uses FFI to
call into Rust code. This requires the following steps.

- Create a new test crate whose name is the same as the name of crate being
  tested, with a `-gtest` suffix.
- Add to the test crate a Rust file, a C++ file containing GTest `TEST()`
  functions that use FFI to call into the Rust file, a `Cargo.toml` file that
  references the Rust file, and a `moz.build` file that references the C++
  file.
- Add an entry to the `[dependencies]` section in
  [toolkit/library/gtest/rust/Cargo.toml](https://searchfox.org/firefox-main/source/toolkit/library/gtest/rust/Cargo.toml).
- Add an `extern crate` entry to
  [toolkit/library/gtest/rust/lib.rs](https://searchfox.org/firefox-main/source/toolkit/library/gtest/rust/lib.rs).

See
[xpcom/rust/gtest/nsstring/](https://searchfox.org/firefox-main/source/xpcom/rust/gtest/nsstring)
for a simple example. (Note that the `moz.build` file is in the parent
directory for that crate.)

A Rust GTest can be run like any other GTest via `./mach gtest`, using the C++
`TEST()` functions as the starting point.

Unlike Rust tests, GTests can be used when linking against Gecko symbols is required.

## Testing third-party crates

In general we don't run tests for third-party crates. The assumption is that
these crates are sufficiently well-tested elsewhere.

## Debugging Rust code

In theory, Rust code is debuggable much like C++ code, using standard tools
like `gdb`, `rr`, and the Microsoft Visual Studio Debugger. In practice, the
experience can be worse, because shortcomings such as the following can occur.

- Inability to print local variables, even in non-optimized builds.
- Inability to call generic functions.
- Missing line numbers and stack frames.
- Printing of basic types such as `Option` and `Vec` is sometimes sub-optimal.
  If you see a warning "Missing auto-load script at offset 0 in section
  `.debug_gdb_scripts`" when starting `gdb`, the `rust-gdb` wrapper may give
  better results.

## Logging from Rust code

### Rust logging

The `RUST_LOG` environment variable (from the `env_logger` crate) can be used
to enable logging to stderr from Rust code in Firefox. The logging macros from
the `log` crate can be used. In order of importance, they are: `error!`,
`warn!`, `info!`, `debug!`, `trace!`.

For example, to show all log messages of `info` level or higher, run:

```
RUST_LOG=info firefox
```

Module-level logging can also be specified, see the [documentation] for the
`env_logger` crate for details.

To restrict logging to child processes, use `RUST_LOG_CHILD` instead of
`RUST_LOG`.

[documentation]: https://docs.rs/env_logger/

### Gecko logging

Rust logging can also be forwarded to the [Gecko logger] for capture via
`MOZ_LOG` and `MOZ_LOG_FILE`.

[Gecko logger]: /xpcom/logging.rst

- When parsing modules from `MOZ_LOG`, modules containing `::` are considered
  to be Rust modules. To log everything in a top-level module like
  `neqo_transport`, specify it as `neqo_transport::*`. For example:

```
MOZ_LOG=timestamp,sync,nsHostResolver:5,neqo_transport::*:5,proxy:5 firefox
```

- When logging from a submodule the `::*` is allowed but isn't necessary.
  So these two lines are equivalent:

```
MOZ_LOG=timestamp,sync,neqo_transport::recovery:5 firefox
MOZ_LOG=timestamp,sync,neqo_transport::recovery::*:5 firefox
```

- `debug!` and `trace!` logs will not appear in non-debug builds. This is due
  to our use of the `release_max_level_info` feature in the `log` crate.

- When using both `MOZ_LOG` and `RUST_LOG`, modules that are specified in
  `MOZ_LOG` will not appear in `RUST_LOG`.

---

### Update Infrastructure Index (`docs/update-infrastructure/index.md`)

# Mozilla Update Infrastructure

Firefox, Thunderbird, and Mozilla VPN updates rely on [backend service known as Balrog](https://github.com/mozilla-releng/balrog). Periodically, these applications check for updates by pinging an URL[^1] which contains information about both the application running, and details of the system it is running on. If Balrog finds an update based on the provided information, it returns a simple XML response with a link to the update file, and some metadata about it.

# Watershed Updates

Most of the time, an update will take an application directly from whatever version it is currently running to the latest version of that application. This is greatly preferred, both to save time, bandwidth, reduce restarts, and increase security by ensuring we get to the latest version of something as quickly as possible. Unfortunately, sometimes we must route through an intermediate version first, typically the version that is currently running does not provide Balrog with enough information to accurately serve a correct update to the latest version. These are colloquially known as "watershed" updates. (This name comes from the fact that these updates change something about the update process itself, making them a kind of "watershed moment" for updates.)

At the time of writing (July, 2024), we currently have the following watershed updates in place for Firefox's release channel:

* 12.0, all platforms. In this release [we added support for distinguishing the running and supported architectures in macOS builds in the update URL](https://bugzilla.mozilla.org/show_bug.cgi?id=583671).
* 43.0.1, Windows only. This release was [preparation for desupporting SHA-1 hashes in our Windows builds](https://bugzilla.mozilla.org/show_bug.cgi?id=1234277).
* 45.0.2, Linux only. We added support for [sending the GTK 3 version to the update URL](https://bugzilla.mozilla.org/show_bug.cgi?id=1227023).
* 47.0.2, Windows only. We [added CPU instruction set information to the update URL](https://bugzilla.mozilla.org/show_bug.cgi?id=1271761) to later allow SSE1 to be deprecated.
* 56.0, Windows only. We added support for [sending information about the JAWS accessibility application to the update URL](https://bugzilla.mozilla.org/show_bug.cgi?id=1402376) to avoid updating people on crashy versions of it. Additionally, we [added support for LZMA compression to the updater](https://bugzilla.mozilla.org/show_bug.cgi?id=641212) and [swapped to new MAR signing keys](https://bugzilla.mozilla.org/show_bug.cgi?id=1324498).
* 57.0.4[^2], Linux & Mac only. We [added support for LZMA compression to the updater](https://bugzilla.mozilla.org/show_bug.cgi?id=641212) and [swapped to new MAR signing keys](https://bugzilla.mozilla.org/show_bug.cgi?id=1324498). (Note: Windows was not required here because they picked up this change in the above 56.0 watershed.)
* 72.0.2, all platforms. This is a required version due to a [necessary two-step password database migration](https://bugzilla.mozilla.org/show_bug.cgi?id=1615382).
* 109.0.1, macOS only. This updates the channel-prefs.js file (normally excluded from updates) due to [signature issues](https://bugzilla.mozilla.org/show_bug.cgi?id=1804303).
* 127.0, Windows only. The issuer for our code-signing certificate changed, [requiring an updated Mozilla Maintenance Service](https://bugzilla.mozilla.org/show_bug.cgi?id=1894689).

[^1]: Here is a sample URL: <https://aus5.mozilla.org/update/3/Firefox/85.0/20200518093924/WINNT_x86_64-msvc-x64/en-US/release/Windows_NT%2010.0.0.0.18363.1016%20(x64)/default/default/update.xml>
[^2]: While not directly related to the watershed, it is notable that due to LZMA MAR support shipping in the previous version (56.0), which was _not_ a watershed for Linux and Mac, we shipped two different sets of MARs for 57.0, 57.0.1, 57.0.2, 57.0.3, and 57.0.4: we had bz2 MARs, which builds older than 56.0 were served, and a separate set of LZMA MARs that were shipped to 56.0 and higher. More details on this can be found on [this awfully complicated spreadsheet that was produced around that time](https://docs.google.com/spreadsheets/d/1xcs9iTShJI8WBvxrz547Zr5JClqdRUYEZRMbQqdQ58I/edit#gid=0).

# Desupport Updates

From time to time we stop supporting a platform, hardware or library that we depend on. When we do this, we must ensure we don't update affected users to a version that they can no longer run. This can take two forms:

* In the distant past, we would simply stop serving updates altogether, leaving users on their current version.
* More recently, we will first move users to our `esr` channel - generally giving them another year of support before ending updates altogether.

Below is a list of desupports and moves to `esr` that we've done on the Firefox release channel:

* (Ancient, desupported at various old versions): Darwin 6, Darwin 7, Darwin 8, Darwin 9, Windows_95, Windows_98, Windows_NT 4, Windows_NT 5.0, Windows_NT 5.1.0, Windows_NT 5.1.1, GTK 2.0., GTK 2.1., GTK 2.2., GTK 2.3., GTK 2.4., GTK 2.5., GTK 2.6., GTK 2.7., GTK 2.8., GTK 2.9., GTK 2.10., GTK 2.11., GTK 2.12., GTK 2.13., GTK 2.14., GTK 2.15., GTK 2.16., GTK 2.17., PPC Architecture
* <46.0: [Desupported GTK <3.4](https://bugzilla.mozilla.org/show_bug.cgi?id=1270358)
* <49.0: Desupported [Darwin 10, 11, and 12](https://bugzilla.mozilla.org/show_bug.cgi?id=1275607) (macOS 10.6, 10.7, 10.8), [SSE and MMX instruction sets](https://bugzilla.mozilla.org/show_bug.cgi?id=1284901)
* <52.0: [Moved Windows XP, Server 2003, and Vista users to esr52](https://bugzilla.mozilla.org/show_bug.cgi?id=1318922)
* <53.0: [Desupported 32-bit macOS hardware](https://bugzilla.mozilla.org/show_bug.cgi?id=1325584)
* <77.0: [Moved Darwin 13, 14, and 15](https://bugzilla.mozilla.org/show_bug.cgi?id=1639199) (macOS 10.9, 10.10, and 10.11) to esr78
* <116.0: [Moved Darwin 16, 17, and 18](https://bugzilla.mozilla.org/show_bug.cgi?id=1836375) (macOS 10.12, 10.13, and 10.14) to esr115
* <116.0: [Moved Windows 7, 8, and 8.1](https://bugzilla.mozilla.org/show_bug.cgi?id=1594270) to esr115

---

### Writing Rust Code Index (`docs/writing-rust-code/index.md`)

# Writing Rust Code

This page explains how to write and work with Rust code in Firefox, with an
emphasis on interoperation with C++ code.

The [build documentation](/build/buildsystem/rust.rst) explains how to add
new Rust code to Firefox. The [test documentation](/testing-rust-code/index.md)
explains how to test and debug Rust code in Firefox.

```{toctree}
:titlesonly:
:maxdepth: 1
:glob:

*
```

---

### Devtools Docs Contributor README (`devtools/docs/contributor/README.md`)

# Firefox Developer Tools: Contributor Docs

This is a guide to working on the code for Firefox Developer Tools. If you're looking for help with using the tools, see the [user docs](https://firefox-source-docs.mozilla.org/devtools-user/). For other ways to get involved, check out our [community site](https://firefox-dev.tools).

---

### Devtools Docs Contributor Architecture Overview (`devtools/docs/contributor/architecture-overview.md`)

# Architecture overview

Broadly speaking, the tools are divided in two parts: the server and the client. A **server** is anything that can be debugged: for example, your browser, but it could also be Firefox for Android, running on another device. The **client** is the front-end side of the tools, and it is what developers interact with when using the tools.

Since these two parts are decoupled, we can connect to any server using the same client. This enables us to debug multiple types of servers, using the same protocol to communicate.

You will often hear about `actors`. Each feature that can be debugged (for example, network) is exposed via an `actor`, which provides data about that specific feature. It's up to each server to implement some or all actors; the client needs to find out and decide what it can render on the front-side when it connects to the server. So when we want to debug a new feature, we might need to do work in two parts of the code: the server (perhaps implementing a new actor, or extending existing ones) and the client (to display the debugging data returned by the actor).

Often, an actor will correspond to a panel. But a panel might want to get data from multiple actors.

You might also hear about `the toolbox`. The toolbox is what everyone else calls `developer tools` i.e. the front-end that you see when you open the tools in your browser.

---

### Code Quality Typescript Index (`docs/code-quality/typescript/index.md`)

# TypeScript

In firefox-main, we are introducing the use of [TypeScript](https://www.typescriptlang.org/)
to help provide type autocompletion, static analysis and type checking of our
JavaScript code.

:::{note}
At the moment we are in the bootstrap/experimentation phase, there are various
parts of infrastructure that have not yet been created, and incomplete type
definitions which may cause issues for projects. Hence TypeScript is not
recommended for all projects for the time being.

We are currently prioritising enabling type autocompletion across the code base,
before we proceed to more work on type checking.

You can work towards enabling TypeScript by ensuring your code passes the
[ESLint jsdoc rules](https://searchfox.org/firefox-main/search?q=jsdoc%2F&path=eslint-plugin-mozilla%2Flib%2Fconfigs&case=false&regexp=false).

If you are interested, please ask in the Lint and Formatting channel (#lint:mozilla.org)
on Matrix.
:::

## Where TypeScript is Currently Enabled

TypeScript is currently only enabled on a [limited set of directories](https://searchfox.org/firefox-main/source/tools/lint/typescript.yml).

## Editor Support

VS Code has TypeScript support built-in and should work "out of the box".

For other editors, see this [TypeScript Wiki Page](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Editor-Support).

## Running TypeScript Locally

The TypeScript linter may be run on the directories where it is enabled using:

```
./mach lint -l typescript path/to/file # (or to the directory)
```

## Updating Gecko Type Definitions

Updating types currently happens manually, although [we are in the process of
automating it](https://bugzilla.mozilla.org/show_bug.cgi?id=1975513).

In the meantime, developers using TypeScript must update the type definitions
[manually using some scripts](updatingTypes.md).

## Best Practices

For working with TypeScript we have some [best practices](bestPractices.md)
which will help to get the type definitions set up correctly.

## Frequently Asked Questions

* Why does running TypeScript check and report errors in other files?
  * Changes in one file may impact on another, and TypeScript can detect this.
  * Additionally, the way that TypeScript works means that it will run across
    the whole project regardless, so we report all the issues that it reports.
* Will my patches get backed out due to TypeScript failures?
  * Currently no. Whilst we have a [TypeScript Linter on CI](../lint/linters/typescript.rst)
    it is currently tier-3 which is hidden from the sheriffs view.
  * Failures will however, be reported on reviews on Phabricator.
  * We will promote the linter to tier-2 and tier-1 once we have more automation
    in place for type generation.
* Why isn't this being encouraged for everyone?
  * As discussed in the note at the top of the page, we are still in the set-up
    and experimentation phase. There is a lot of infrastructure that is required
    to make TypeScript usable on a day to day basis.
* Are we planning to allow using TypeScript files and compiling directly from
  TypeScript?
  * No. In the past we've worked to avoid processing or compilation steps,
    wherever possible when developing JavaScript. This helps to reduce code-test
    cycle times and make debugging simpler.
  * Whilst it is possible we could change the approach in future, it is not an
    objective of enabling TypeScript over the firefox-main code base.
* Something isn't working as I would expect, where should I look/ask?
  * We have a [meta bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1945456)
    for TypeScript issues in firefox-main. We work through them over time, though
    we appreciate help as well.
  * See the [Getting Help](#getting-help) section.

## Getting Help

The Lint & Formatting channel (#lint:mozilla.org) on Matrix is the best place
    to ask questions.

## Further Reading

* The [TypeScript documentation](https://www.typescriptlang.org/docs/) is very
  useful in understanding how TypeScript works and how types may be set up.
  * The [JavaScript section starting here](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html),
    is especially useful for firefox-main development.

---

### Rust Components Api Index (`docs/rust-components/api/index.md`)

# Rust components API References

Choose a language to get started

- [JS](./js/index.md)
- [Kotlin](https://mozilla.github.io/application-services/kotlin/index.html)
- [Swift](https://mozilla.github.io/application-services/swift/index.html)

---

### Rust Components Developing Rust Components Index (`docs/rust-components/developing-rust-components/index.md`)

# Developing Shared Rust Components

Shared Rust Components is a strategy to create a single component that provides the same functionality for Firefox Desktop, Firefox Android and Firefox iOS.

This strategy was first adopted for sync in response to issues stemming from separate sync implementations for each application. Separate sync implementations lead to duplicate logic across platforms, which was difficult to maintain. Furthermore, the likelihood of errors was very high -- especially since each implementation had to sync with the other implementations. Since then more components have adopted the Rust components strategy and some non-Firefox projects have started using the components (for example nimbus-experimenter).

The basic idea is to write the component in Rust then generate a set of Kotlin/Swift/JS bindings that can be consumed by the Firefox applications.
Rust was chosen because it supports a large number of target platforms, including Android and iOS.
The [UniFFI](https://mozilla.github.io/uniffi-rs/latest/) library was created to handle bindings
generation.

## Pros and cons of adding a shared Rust component

### Pros

* Less work than creating a multiple implementations.
* More consistent behavior across different applications.
* Better sync integrations (this follows from the last point, since behavior differences often become larger bugs when sync is involved).
* Build JavaScript, Kotlin, and Swift docs from the Rust docstrings.

### Cons

* More work than creating a single implementation.
* Requires engineers to write and understand Rust.
* Still requires some application glue code to integrate the component.
  Often it's trivial like [TabsStore](https://searchfox.org/firefox-main/source/services/sync/modules/TabsStore.sys.mjs), but sometimes it's larger.

### Neutral

* Performance is usually similar to JavaScript/Kotlin code.
  FFI overhead typically negates any speedups from using Rust.

## Shared Rust component ownership

Teams that write shared Rust components are responsible for maintaining their health.
This includes monitoring error reports and working with application teams to maintain integrations as the application code changes.
Error reports are currently only available for Android, but we will soon be extending this to all platforms.


```{toctree}
:titlesonly:
:maxdepth: 1

example-component
uniffi
logging
observability
threading
other-desktop-specific-concerns
```

---

### Rust Components Topic Guides Index (`docs/rust-components/topic-guides/index.md`)

# Topic Guides

Here are the guides on various topics related to Rust components.

```{toctree}
:titlesonly:
:maxdepth: 1
:glob:

*
```

---

### Rust Components Uniffi Bindgen Gecko Js Dev Guide Index (`docs/rust-components/uniffi-bindgen-gecko-js-dev-guide/index.md`)

# uniffi-bindgen-gecko-js Developers Guide

This section describes the internal workings of `uniffi-bindgen-gecko-js` for developers working with this code.
It builds on the [UniFFI user guide](https://mozilla.github.io/uniffi-rs/latest/) internals documentation, which is recommended reading before diving into these specifics.

## UniFFI bindings pipeline

`uniffi-bindgen-gecko-js` uses the bindings pipeline ([docs](https://github.com/mozilla/uniffi-rs/blob/main/docs/manual/src/internals/bindings_ir.md) [more docs](https://github.com/mozilla/uniffi-rs/blob/main/docs/manual/src/internals/bindings_ir_pipeline.md)).
`uniffi-bindgen-gecko-js` is the first bindings generator to adopt this code, although we hope to eventually move all bindings to this system.
This means the `uniffi-bindgen-gecko-js` code may look different than other bindings, but we hope it's only temporary.

```{toctree}
:titlesonly:
:maxdepth: 1

js-and-cpp-layers
lifting-and-lowering
rust-calls
js-callback-interfaces
```

---

### Dom Docs Push Index (`dom/docs/push/index.md`)

# Push

<div class="note">
<div class="admonition-title">Note</div>
This document describes how Firefox implements the Web Push standard internally, and is intended for developers working directly on Push. If you are looking for how to consume push, please refer to the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Push_API" target="_blank">following MDN document</a>

</div>

## High level push architecture

The following sequence diagram describes the high level push architecture as observed by web application. The diagram describes the interactions between a Web application's client code running in the browser, Firefox, [Autopush](https://autopush.readthedocs.io/en/latest/) (Firefox's push server that delivers push notifications) and a third party server that sends the push notifications to Autopush

The dotted lines are done by the consumer of push.

```{mermaid}
sequenceDiagram
	participant TP as Web Application JS
	participant F as Firefox
	participant A as Autopush
	participant TPS as Third party Server
		TP->>F: subscribe(scope)
		activate TP
		activate F
		F->>A: subscribe(scope) using web socket
		activate A
		A->>F: URL
		deactivate A
		F->>F: Create pub/privKey Encryption pair
		F->>F: Persist URL, pubKey, privKey indexed using an id derived from scope
		F->>TP: URL + pubKey
		deactivate F
		TP-->>TPS: URL + pubKey
		deactivate TP
		TPS-->>TPS: Encrypt payload using pubKey
		TPS-->>A: Send encrypted payload using URL
		activate A
		A->>F: Send encrypted payload using web socket
		deactivate A
		activate F
		F->>F: Decrypt payload using privKey
		F->>F: Display Notification
		deactivate F
```

## Firefox Desktop

### Flow diagram for source code

The source code for push is available under [`dom/push`](https://searchfox.org/firefox-main/source/dom/push) in mozilla-central.

The following flow diagram describes how different modules interact with each other to provide the push API to consumers.

```{mermaid}
flowchart TD
    subgraph Public API

    W[Third party Web app]-->|imports| P[PushManager.webidl]
    end
    subgraph Browser Code
        P-->|Implemented by| MM
        MM{Main Thread?}-->|Yes| B[Push.sys.mjs]
        MM -->|NO| A[PushManager.cpp]
        B-->|subscribe,getSubscription| D[PushComponents.sys.mjs]
        A-->|subscribe,getSubscription| D
        D-->|subscribe,getSubscription| M[PushService.sys.mjs]
        M-->|Storage| S[PushDB.sys.mjs]
        M-->|Network| N[PushWebSocket.sys.mjs]
        F[FxAccountsPush.sys.mjs] -->|uses| D
    end
    subgraph Server
    N-. Send, Receive.-> O[Autopush]
    end
    subgraph Local Storage
    S-->|Read,Write| PP[(IndexedDB)]
    end
```

### The Push Web Socket

Push in Firefox Desktop communicates with Autopush using a web socket connection.

The web socket connection is created as the browser initializes and is managed by the following state diagram.

```{mermaid}
stateDiagram-v2
		state "Shut Down" as SD
		state "Waiting for WebSocket to start" as W1
		state "Waiting for server hello" as W2
		state "Ready" as R
    [*] --> SD
		 SD --> W1: beginWSSetup
		 W1 --> W2: wsOnStart Success
		 W2 --> R: handleHelloReply
		 R --> R: send (subscribe)
         R --> R: Receive + notify observers
		 R --> SD: wsOnStop
		 R --> SD: sendPing Fails
		 W1 --> SD: wsOnStart fails
		 W2 --> SD: invalid server hello
		 R --> [*]
```

Once the Push web socket is on the `Ready` state, it is ready to send new subscriptions to Autopush, and receive push notifications from those subscriptions.

Push uses an observer pattern to notify observers of any incoming push notifications. See the [high level architecture](#high-level-push-architecture) section.

### Push Storage

Push uses IndexedDB to store subscriptions for the following reasons:

1. In case the consumer attempts to re-subscribe, storage is used as a cache to serve the URL and the public key
1. In order to persist the private key, so that it can be used to decrypt any incoming push notifications

The following is what gets persisted:

```{mermaid}
erDiagram
    Subscription {
        string channelID "Key, Derived from scope"
        string pushEndpoint "Unique endpoint for this subscription"
        string scope "Usually the origin, unique value for internal consumers"
        Object p256dhPublicKey "Object representing the public key"
        Object p256dhPrivateKey "Object representing the private key"
    }
```

## Firefox for Android

See also:

* [Rust Push Component](https://mozilla.github.io/application-services/book/rust-docs/push/index.html)
* [Push Service Bridge HTTP Interface](https://autopush.readthedocs.io/en/latest/http.html#push-service-bridge-http-interface)
* [Android Components: Push](https://github.com/mozilla/gecko-dev/blob/master/mobile/android/android-components/components/feature/push/README.md)

### Flow diagram for source code

The source code for push is available under the following paths in mozilla-central:

* [`dom/push/`](https://searchfox.org/firefox-main/source/dom/push/)
* [`mobile/shared/components/geckoview/GeckoViewPush.sys.mjs`](mobile/shared/components/geckoview/GeckoViewPush.sys.mjs)
* [`mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebPush*.java`](https://searchfox.org/firefox-main/source/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/)
* Under `mobile/android/android-components/components`:
  * [`feature/push/src/main/java/mozilla/components/feature/push/`](https://searchfox.org/firefox-main/source/mobile/android/android-components/components/feature/push/src/main/java/mozilla/components/feature/push/)
  * [`browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/webpush/`](https://searchfox.org/firefox-main/source/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/webpush/)
  * [`concept/engine/src/main/java/mozilla/components/concept/engine/webpush`](https://searchfox.org/firefox-main/source/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/webpush/)
* [Rust Push Component](https://github.com/mozilla/application-services/tree/main/components/push)

The following flow diagram describes how different modules interact with each other to provide the push API to consumers.

```{mermaid}
flowchart TD
    subgraph Public API

    W[Third party Web app]-->|imports| P[PushManager.webidl]
    end
    subgraph Browser Code
        P-->|Implemented by| MM
        MM{Main Thread?}-->|Yes| B[Push.sys.mjs]
        MM -->|NO| A[PushManager.cpp]
        B-->|subscribe,getSubscription| D[GeckoViewPush.sys.mjs]
        A-->|subscribe,getSubscription| D
        D-->|PushSubscribe,PushGetSubscription| WPC[WebPushController.java]
        WPC-->|onSubscribe,onGetSubscription| WPEI[WebPushEngineIntegration.kt]
        WPEI-->|subscribe,getSubscription| APF[AutoPushFeature.kt]
        APF-->|start| PS[AbstractFirebasePushService.kt]
        FCM[Firebase Cloud Messaging]-->|onNewToken| PS
        PS-->|onNewToken| APF
        APF-->|subscribe,getSubscription| PRS[push/src/lib.rs]
        PRS-->|subscribe,get_subscription| PM[internal/push_manager.rs]
        PM-->|Storage| S[internal/storage/db.rs]
        PM-->|Network| N[internal/communications.rs]
    end
    subgraph Server
    N-. bridge interface.-> O[Autopush]
    end
    subgraph Local Storage
    S-->|Read,Write| SQL[(SQLite)]
    end
```

---

### Dom Docs WebIdlBindings Index (`dom/docs/webIdlBindings/index.md`)

# Web IDL bindings

<div class="note">
<div class="admonition-title">Note</div>

Need to document the setup for indexed and named
setters/creators/deleters.

</div>

The [Web IDL](https://webidl.spec.whatwg.org/) bindings are generated
at build time based on two things: the actual Web IDL file and a
configuration file that lists some metadata about how the Web IDL should
be reflected into Gecko-internal code.

All Web IDL files should be placed in
[`dom/webidl`](https://searchfox.org/firefox-main/source/dom/webidl/)
and added to the list in the
[moz.build](https://searchfox.org/firefox-main/source/dom/webidl/moz.build)
file in that directory.

Note that if you're adding new interfaces, then the test at
`dom/tests/mochitest/general/test_interfaces.html` will most likely
fail. This is a signal that you need to get a review from a [DOM
peer](https://wiki.mozilla.org/Modules/All#Document_Object_Model).
Resist the urge to just add your interfaces to the
[moz.build](https://searchfox.org/firefox-main/source/dom/webidl/moz.build) list
without the review; it will just annoy the DOM peers and they'll make
you get the review anyway.

The configuration file, `dom/bindings/Bindings.conf`, is basically a
Python dict that maps interface names to information about the
interface, called a _descriptor_. There are all sorts of possible
options here that handle various edge cases, but most descriptors can be
very simple.

All the generated code is placed in the `mozilla::dom` namespace. For
each interface, a namespace whose name is the name of the interface with
`Binding` appended is created, and all the things pertaining to that
interface's binding go in that namespace.

There are various helper objects and utility methods in
[`dom/bindings`](https://searchfox.org/firefox-main/source/dom/bindings)
that are also all in the `mozilla::dom` namespace and whose headers
are all exported into `mozilla/dom` (placed in
`$OBJDIR/dist/include` by the build process).

## Adding Web IDL bindings to a class

To add a Web IDL binding for interface `MyInterface` to a class
`mozilla::dom::MyInterface` that's supposed to implement that
interface, you need to do the following:

1. If your interface doesn't inherit from any other interfaces, inherit
   from `nsWrapperCache` and hook up the class to the cycle collector
   so it will trace the wrapper cache properly. Note that you may not
   need to do this if your objects can only be created, never gotten
   from other objects. If you also inherit from `nsISupports`, make
   sure the `nsISupports` comes before the `nsWrapperCache` in your
   list of parent classes. If your interface _does_ inherit from another
   interface, just inherit from the C++ type that the other interface
   corresponds to.

   If you do need to hook up cycle collection, it will look like this in
   the common case of also inheriting from nsISupports:

   ``` cpp
   // Add strong pointers your class holds here. If you do, change to using
   // NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE.
   NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(MyClass)
   NS_IMPL_CYCLE_COLLECTING_ADDREF(MyClass)
   NS_IMPL_CYCLE_COLLECTING_RELEASE(MyClass)
   NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MyClass)
     NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_END
   ```

1. If your class doesn't inherit from a class that implements
   `GetParentObject`, then add a function of that name that, for a
   given instance of your class, returns the same object every time
   (unless you write explicit code that handles your parent object
   changing by reparenting JS wrappers, as nodes do). The idea is that
   walking the `GetParentObject` chain will eventually get you to a
   Window, so that every Web IDL object is associated with a particular
   Window.
   For example, `nsINode::GetParentObject` returns the node's owner
   document. The return type of `GetParentObject` doesn't matter other
   than it must either singly-inherit from `nsISupports` or have a
   corresponding
   [`ToSupports`](https://searchfox.org/firefox-main/search?q=ToSupports&path=&case=true&regexp=false)
   method that can produce an `nsISupports` from it. (This allows the
   return value to be implicitly converted to a
   [`ParentObject`](https://searchfox.org/firefox-main/search?q=ParentObject&path=&case=true&regexp=false)
   instance by the compiler via one of that class's non-explicit
   constructors.)
   If many instances of `MyInterface` are expected to be created
   quickly, the return value of `GetParentObject` should itself inherit
   from `nsWrapperCache` for optimal performance. Returning null from
   `GetParentObject` is allowed in situations in which it's OK to
   associate the resulting object with a random global object for
   security purposes; this is not usually ok for things that are exposed
   to web content. Again, if you do not need wrapper caching you don't
   need to do this. The actual type returned from `GetParentObject`
   must be defined in a header included from your implementation header,
   so that this type's definition is visible to the binding code.

1. Add the Web IDL for `MyInterface` in `dom/webidl` and to the list
   in `dom/webidl/moz.build`.

1. Add an entry to `dom/bindings/Bindings.conf` that sets some basic
   information about the implementation of the interface. If the C++
   type is not `mozilla::dom::MyInterface`, you need to set the
   `'nativeType'` to the right type. If the type is not in the header
   file one gets by replacing '::' with '/' and appending '`.h`', then
   add a corresponding `'headerFile'` annotation (or
   [`HeaderFile`](#headerfile-path-to-headerfile-h) annotation to the .webidl file). If
   you don't have to set any annotations, then you don't need to add an
   entry either and the code generator will simply assume the defaults
   here. Note that using a `'headerFile'` annotation is generally not
   recommended. If you do use it, you will need to make sure your
   header includes all the headers needed for your [`Func`](#func-funcname)
   annotations.

1. Add external interface entries to `Bindings.conf` for whatever
   non-Web IDL interfaces your new interface has as arguments or return
   values.

1. Implement a `WrapObject` override on `mozilla::dom::MyInterface`
   that just calls through to
   `mozilla::dom::MyInterface_Binding::Wrap`. Note that if your C++
   type is implementing multiple distinct Web IDL interfaces, you need
   to choose which `mozilla::dom::MyInterface_Binding::Wrap` to call
   here. See `AudioContext::WrapObject`, for example.

1. Expose whatever methods the interface needs on
   `mozilla::dom::MyInterface`. These can be inline, virtual, have any
   calling convention, and so forth, as long as they have the right
   argument types and return types. You can see an example of what the
   function declarations should look like by running
   `mach webidl-example MyInterface`. This will produce two files in
   `dom/bindings` in your objdir: `MyInterface-example.h` and
   `MyInterface-example.cpp`, which show a basic implementation of the
   interface using a class that inherits from `nsISupports` and has a
   wrapper cache.

See this [sample patch that migrates window.performance.\* to Web IDL
bindings](https://hg.mozilla.org/mozilla-central/rev/dd08c10193c6).

<div class="note"><div class="admonition-title">Note</div>

If your object can only be reflected into JS by creating it, not by
retrieving it from somewhere, you can skip steps 1 and 2 above and
instead add `'wrapperCache': False` to your descriptor. You will
need to flag the functions that return your object as
[`[NewObject]`](https://webidl.spec.whatwg.org/#NewObject) in
the Web IDL. If your object is not refcounted then the return value of
functions that return it should return a UniquePtr.

</div>

## C++ reflections of Web IDL constructs

### C++ reflections of Web IDL operations (methods)

A Web IDL operation is turned into a method call on the underlying C++
object. The return type and argument types are determined [as described
below](#c-reflections-of-webidl-constructs). In addition to those, all [methods that are
allowed to throw](#throws-getterthrows-setterthrows) will get an `ErrorResult&` argument
appended to their argument list. Non-static methods that use certain
Web IDL types like `any` or `object` will get a `JSContext*`
argument prepended to the argument list. Static methods will be passed a
[`const GlobalObject&`](#globalobject) for the relevant global and
can get a `JSContext*` by calling `Context()` on it.

The name of the C++ method is simply the name of the Web IDL operation
with the first letter converted to uppercase.

Web IDL overloads are turned into C++ overloads: they simply call C++
methods with the same name and different signatures.

For example, this Web IDL:

``` webidl
interface MyInterface
{
  undefined doSomething(long number);
  double doSomething(MyInterface? otherInstance);

  [Throws]
  MyInterface doSomethingElse(optional long maybeNumber);
  [Throws]
  undefined doSomethingElse(MyInterface otherInstance);

  undefined doTheOther(any something);

  undefined doYetAnotherThing(optional boolean actuallyDoIt = false);

  static undefined staticOperation(any arg);
};
```

will require these method declarations:

``` cpp
class MyClass
{
  void DoSomething(int32_t a number);
  double DoSomething(MyClass* aOtherInstance);

  already_AddRefed<MyInterface> DoSomethingElse(Optional<int32_t> aMaybeNumber,
                                                ErrorResult& rv);
  void DoSomethingElse(MyClass& aOtherInstance, ErrorResult& rv);

  void DoTheOther(JSContext* cx, JS::Handle<JS::Value> aSomething);

  void DoYetAnotherThing(bool aActuallyDoIt);

  static void StaticOperation(const GlobalObject& aGlobal, JS::Handle<JS::Value> aSomething);
}
```

### C++ reflections of Web IDL attributes

A Web IDL attribute is turned into a pair of method calls for the getter
and setter on the underlying C++ object. A readonly attribute only has a
getter and no setter.

The getter's name is the name of the attribute with the first letter
converted to uppercase. This has `Get` prepended to it if any of these
conditions hold:

1. The type of the attribute is nullable.
1. The getter can throw.
1. The return value of the attribute is returned via an out parameter in
   the C++.

The method signature for the getter looks just like an operation with no
arguments and the attribute's type as the return type.

The setter's name is `Set` followed by the name of the attribute with
the first letter converted to uppercase. The method signature looks just
like an operation with an undefined return value and a single argument
whose type is the attribute's type.

### C++ reflections of Web IDL constructors

A Web IDL constructor is turned into a static class method named
`Constructor`. The arguments of this method will be the arguments of
the Web IDL constructor, with a
[`const GlobalObject&`](#globalobject) for the relevant global
prepended. For the non-worker case, the global is typically the inner
window for the DOM Window the constructor function is attached to. If a
`JSContext*` is also needed due to some of the argument types, it will
come after the global. The return value of the constructor for
`MyInterface` is exactly the same as that of a method returning an
instance of `MyInterface`. Constructors are always allowed to throw.

For example, this IDL:

``` webidl
interface MyInterface {
  constructor();
  constructor(unsigned long someNumber);
};
```

will require the following declarations in `MyClass`:

``` cpp
class MyClass {
  // Various nsISupports stuff or whatnot
  static
  already_AddRefed<MyClass> Constructor(const GlobalObject& aGlobal,
                                        ErrorResult& rv);
  static
  already_AddRefed<MyClass> Constructor(const GlobalObject& aGlobal,
                                        uint32_t aSomeNumber,
                                        ErrorResult& rv);
};
```

### C++ reflections of Web IDL types

The exact C++ representation for Web IDL types can depend on the precise
way that they're being used (e.g., return values, arguments, and
sequence or dictionary members might all have different
representations).

Unless stated otherwise, a type only has one representation. Also,
unless stated otherwise, nullable types are represented by wrapping
[`Nullable<>`](#nullable-t) around the base type.

In all cases, optional arguments which do not have a default value are
represented by wrapping [`const Optional<>&`](#optional-t) around the
representation of the argument type. If the argument type is a C++
reference, it will also become a [`NonNull<>`](#nonnull-t) around the
actual type of the object in the process. Optional arguments which do
have a default value are just represented by the argument type itself,
set to the default value if the argument was not in fact passed in.

Variadic Web IDL arguments are treated as a
[`const Sequence<>&`](#sequence-t) around the actual argument type.

Here's a table, see the specific sections below for more details and
explanations.

| Web IDL Type                | Argument Type                     | Return Type                                                                                                      | Dictionary/Member Type                 |
| -------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| any                        | `JS::Handle<JS::Value>`           | `JS::MutableHandle<JS::Value>`                                                                                   | `JS::Value`                            |
| boolean                    | `bool`                            | `bool`                                                                                                           | `bool`                                 |
| byte                       | `int8_t`                          | `int8_t`                                                                                                         | `int8_t`                               |
| ByteString                 | `const nsACString&`               | `nsCString&` _(outparam)_<br>`nsACString&` _(outparam)_                                                          | `nsCString`                            |
| Date                       |                                   |                                                                                                                  | `mozilla::dom::Date`                   |
| DOMString                  | `const nsAString&`                | [`mozilla::dom::DOMString&`](#domstring-c) _(outparam)_<br>`nsAString&` _(outparam)_<br>`nsString&` _(outparam)_ | `nsString`                             |
| UTF8String                 | `const nsACString&` _(outparam)_  | `nsACString&`                                                                                                    | `nsCString`                            |
| double                     | `double`                          | `double`                                                                                                         | `double`                               |
| float                      | `float`                           | `float`                                                                                                          | `float`                                |
| interface:<br>non-nullable | `Foo&`                            | `already_addRefed<Foo>`                                                                                          | [`OwningNonNull<Foo>`](#owningnonnull-t) |
| interface:<br>nullable     | `Foo*`                            | `already_addRefed<Foo>`<br>`Foo*`                                                                                | `RefPtr<Foo>`                          |
| long                       | `int32_t`                         | `int32_t`                                                                                                        | `int32_t`                              |
| long long                  | `int64_t`                         | `int64_t`                                                                                                        | `int64_t`                              |
| object                     | `JS::Handle<JSObject*>`           | `JS::MutableHandle<JSObject*>`                                                                                   | `JSObject*`                            |
| octet                      | `uint8_t`                         | `uint8_t`                                                                                                        | `uint8_t`                              |
| sequence                   | [`const Sequence<T>&`](#sequence-t) | `nsTArray<T>&` _(outparam)_                                                                                      |                                        |
| short                      | `int16_t`                         | `int16_t`                                                                                                        | `int16_t`                              |
| unrestricted double        | `double`                          | `double`                                                                                                         | `double`                               |
| unrestricted float         | `float`                           | `float`                                                                                                          | `float`                                |
| unsigned long              | `uint32_t`                        | `uint32_t`                                                                                                       | `uint32_t`                             |
| unsigned long long         | `uint64_t`                        | `uint64_t`                                                                                                       | `uint64_t`                             |
| unsigned short             | `uint16_t`                        | `uint16_t`                                                                                                       | `uint16_t`                             |
| USVString                  | `const nsAString&`                | [`mozilla::dom::DOMString&`](#domstring-c) _(outparam)_<br>`nsAString&` _(outparam)_<br>`nsString&` _(outparam)_ | `nsString`                             |

#### `any`

`any` is represented in three different ways, depending on use:

- `any` arguments become `JS::Handle<JS::Value>`. They will be in
  the compartment of the passed-in JSContext.
- `any` return values become a `JS::MutableHandle<JS::Value>` out
  param appended to the argument list. This comes after all IDL
  arguments, but before the `ErrorResult&`, if any, for the method.
  The return value is allowed to be in any compartment; bindings will
  wrap it into the context compartment as needed.
- `any` dictionary members and sequence elements become
  `JS::Value`. The dictionary members and sequence elements are
  guaranteed to be marked by whomever puts the sequence or dictionary
  on the stack, using `SequenceRooter` and `DictionaryRooter`.

Methods using `any` always get a `JSContext*` argument.

For example, this Web IDL:

``` webidl
interface Test {
  attribute any myAttr;
  any myMethod(any arg1, sequence<any> arg2, optional any arg3);
};
```

will correspond to these C++ function declarations:

``` cpp
void MyAttr(JSContext* cx, JS::MutableHandle<JS::Value> retval);
void SetMyAttr(JSContext* cx, JS::Handle<JS::Value> value);
void MyMethod(JSContext* cx, JS::Handle<JS::Value> arg1,
              const Sequence<JS::Value>& arg2,
              const Optional<JS::Handle<JS::Value>>& arg3,
              JS::MutableHandle<JS::Value> retval);
```

#### `boolean`

The `boolean` Web IDL type is represented as a C++ `bool`.

For example, this Web IDL:

``` webidl
interface Test {
  attribute boolean myAttr;
  boolean myMethod(optional boolean arg);
};
```

will correspond to these C++ function declarations:

``` cpp
bool MyAttr();
void SetMyAttr(bool value);
bool MyMethod(const Optional<bool>& arg);
```

#### Integer types

Integer Web IDL types are mapped to the corresponding C99 stdint types.

For example, this Web IDL:

``` webidl
interface Test {
  attribute short myAttr;
  long long myMethod(unsigned long? arg);
};
```

will correspond to these C++ function declarations:

``` cpp
int16_t MyAttr();
void SetMyAttr(int16_t value);
int64_t MyMethod(const Nullable<uint32_t>& arg);
```

#### Floating point types

Floating point Web IDL types are mapped to the C++ type of the same
name. So `float` and `unrestricted float` become a C++ `float`,
while `double` and `unrestricted double` become a C++ `double`.

For example, this Web IDL:

``` webidl
interface Test {
  float myAttr;
  double myMethod(unrestricted double? arg);
};
```

will correspond to these C++ function declarations:

``` cpp
float MyAttr();
void SetMyAttr(float value);
double MyMethod(const Nullable<double>& arg);
```

#### `DOMString`

Strings are reflected in three different ways, depending on use:

- String arguments become `const nsAString&`.
- String return values become a
  [`mozilla::dom::DOMString&`](#domstring-c) out param
  appended to the argument list. This comes after all IDL arguments,
  but before the `ErrorResult&`, if any, for the method. Note that
  this allows callees to declare their methods as taking an
  `nsAString&` or `nsString&` if desired.
- Strings in sequences, dictionaries, owning unions, and variadic
  arguments become `nsString`.

Nullable strings are represented by the same types as non-nullable ones,
but the string will return true for `DOMStringIsNull()`. Returning
null as a string value can be done using `SetDOMStringToNull` on the
out param if it's an `nsAString` or calling `SetNull()` on a
`DOMString`.

For example, this Web IDL:

``` webidl
interface Test {
  DOMString myAttr;
  [Throws]
  DOMString myMethod(sequence<DOMString> arg1, DOMString? arg2, optional DOMString arg3);
};
```

will correspond to these C++ function declarations:

``` cpp
void GetMyAttr(nsString& retval);
void SetMyAttr(const nsAString& value);
void MyMethod(const Sequence<nsString>& arg1, const nsAString& arg2,
              const Optional<nsAString>& arg3, nsString& retval, ErrorResult& rv);
```

#### `USVString`

`USVString` is reflected just like `DOMString`.

#### `UTF8String`

`UTF8String` is a string with guaranteed-valid UTF-8 contents. It is
not a standard in the Web IDL spec, but its observables are the same as
those of `USVString`.

It is a good fit for when the specification allows a `USVString`, but
you want to process the string as UTF-8 rather than UTF-16.

It is reflected in three different ways, depending on use:

- Arguments become `const nsACString&`.
- Return values become an `nsACString&` out param appended to the
  argument list. This comes after all IDL arguments, but before the
  `ErrorResult&`, if any, for the method.
- In sequences, dictionaries owning unions, and variadic arguments it
  becomes `nsCString`.

Nullable `UTF8String`s are represented by the same types as
non-nullable ones, but the string will return true for `IsVoid()`.
Returning null as a string value can be done using `SetIsVoid()` on
the out param.

#### `ByteString`

`ByteString` is reflected in three different ways, depending on use:

- `ByteString` arguments become `const nsACString&`.
- `ByteString` return values become an `nsCString&` out param
  appended to the argument list. This comes after all IDL arguments,
  but before the `ErrorResult&`, if any, for the method.
- `ByteString` in sequences, dictionaries, owning unions, and
  variadic arguments becomes `nsCString`.

Nullable `ByteString` are represented by the same types as
non-nullable ones, but the string will return true for `IsVoid()`.
Returning null as a string value can be done using `SetIsVoid()` on
the out param.

#### `object`

`object` is represented in three different ways, depending on use:

- `object` arguments become `JS::Handle<JSObject*>`. They will be
  in the compartment of the passed-in JSContext.
- `object` return values become a `JS::MutableHandle<JSObject*>`
  out param appended to the argument list. This comes after all IDL
  arguments, but before the `ErrorResult&`, if any, for the method.
  The return value is allowed to be in any compartment; bindings will
  wrap it into the context compartment as needed.
- `object` dictionary members and sequence elements become
  `JSObject*`. The dictionary members and sequence elements are
  guaranteed to be marked by whoever puts the sequence or dictionary on
  the stack, using `SequenceRooter` and `DictionaryRooter`.

Methods using `object` always get a `JSContext*` argument.

For example, this Web IDL:

``` webidl
interface Test {
  object myAttr;
  object myMethod(object arg1, object? arg2, sequence<object> arg3, optional object arg4,
                  optional object? arg5);
};
```

will correspond to these C++ function declarations:

``` cpp
void GetMyAttr(JSContext* cx, JS::MutableHandle<JSObject*> retval);
void SetMyAttr(JSContext* cx, JS::Handle<JSObject*> value);
void MyMethod(JSContext* cx, JS::Handle<JSObject*> arg1, JS::Handle<JSObject*> arg2,
              const Sequence<JSObject*>& arg3,
              const Optional<JS::Handle<JSObject*>>& arg4,
              const Optional<JS::Handle<JSObject*>>& arg5,
              JS::MutableHandle<JSObject*> retval);
```

#### Interface types

There are four kinds of interface types in the Web IDL bindings. Callback
interfaces are used to represent script objects that browser code can
call into. External interfaces are used to represent objects that have
not been converted to the Web IDL bindings yet. Web IDL interfaces are
used to represent Web IDL binding objects. "SpiderMonkey" interfaces are
used to represent objects that are implemented natively by the
JavaScript engine (e.g., typed arrays).

##### Callback interfaces

Callback interfaces are represented in C++ as objects inheriting from
[`mozilla::dom::CallbackInterface`](#callbackinterface), whose
name, in the `mozilla::dom` namespace, matches the name of the
callback interface in the Web IDL. The exact representation depends on
how the type is being used.

- Nullable arguments become `Foo*`.
- Non-nullable arguments become `Foo&`.
- Return values become `already_AddRefed<Foo>` or `Foo*` as
  desired. The pointer form is preferred because it results in faster
  code, but it should only be used if the return value was not addrefed
  (and so it can only be used if the return value is kept alive by the
  callee until at least the binding method has returned).
- Web IDL callback interfaces in sequences, dictionaries, owning unions,
  and variadic arguments are represented by `RefPtr<Foo>` if nullable
  and [`OwningNonNull<Foo>`](#owningnonnull-t) otherwise.

If the interface is a single-operation interface, the object exposes two
methods that both invoke the same underlying JS callable. The first of
these methods allows the caller to pass in a `this` object, while the
second defaults to `undefined` as the `this` value. In either case,
the `this` value is only used if the callback interface is implemented
by a JS callable. If it's implemented by an object with a property whose
name matches the operation, the object itself is always used as
`this`.

If the interface is not a single-operation interface, it just exposes a
single method for every IDL method/getter/setter.

The signatures of the methods correspond to the signatures for throwing
IDL methods/getters/setters with an additional trailing
`mozilla::dom::CallbackObject::ExceptionHandling aExceptionHandling`
argument, defaulting to `eReportExceptions`.
If `aReportExceptions` is set to `eReportExceptions`, the methods
will report JS exceptions before returning. If `aReportExceptions` is
set to `eRethrowExceptions`, JS exceptions will be stashed in the
`ErrorResult` and will be reported when the stack unwinds to wherever
the `ErrorResult` was set up.

For example, this Web IDL:

``` webidl
callback interface MyCallback {
  attribute long someNumber;
  short someMethod(DOMString someString);
};
callback interface MyOtherCallback {
  // single-operation interface
  short doSomething(Node someNode);
};
interface MyInterface {
  attribute MyCallback foo;
  attribute MyCallback? bar;
};
```

will lead to these C++ class declarations in the `mozilla::dom`
namespace:

``` cpp
class MyCallback : public CallbackInterface
{
  int32_t GetSomeNumber(ErrorResult& rv, ExceptionHandling aExceptionHandling = eReportExceptions);
  void SetSomeNumber(int32_t arg, ErrorResult& rv,
                     ExceptionHandling aExceptionHandling = eReportExceptions);
  int16_t SomeMethod(const nsAString& someString, ErrorResult& rv,
                     ExceptionHandling aExceptionHandling = eReportExceptions);
};

class MyOtherCallback : public CallbackInterface
{
public:
  int16_t
  DoSomething(nsINode& someNode, ErrorResult& rv,
              ExceptionHandling aExceptionHandling = eReportExceptions);

  template<typename T>
  int16_t
  DoSomething(const T& thisObj, nsINode& someNode, ErrorResult& rv,
              ExceptionHandling aExceptionHandling = eReportExceptions);
};
```

and these C++ function declarations on the implementation of
`MyInterface`:

``` cpp
already_AddRefed<MyCallback> GetFoo();
void SetFoo(MyCallback&);
already_AddRefed<MyCallback> GetBar();
void SetBar(MyCallback*);
```

A consumer of MyCallback would be able to use it like this:

``` cpp
void
SomeClass::DoSomethingWithCallback(MyCallback& aCallback)
{
  ErrorResult rv;
  int32_t number = aCallback.GetSomeNumber(rv);
  if (rv.Failed()) {
    // The error has already been reported to the JS console; you can handle
    // things however you want here.
    return;
  }

  // For some reason we want to catch and rethrow exceptions from SetSomeNumber, say.
  aCallback.SetSomeNumber(2*number, rv, eRethrowExceptions);
  if (rv.Failed()) {
    // The exception is now stored on rv. This code MUST report
    // it usefully; otherwise it will assert.
  }
}
```

##### External interfaces

External interfaces are represented in C++ as objects that XPConnect
knows how to unwrap to. This can mean XPCOM interfaces (whether declared
in XPIDL or not) or it can mean some type that there's a castable native
unwrapping function for. The C++ type to be used should be the
`nativeType` listed for the external interface in the
[`Bindings.conf`](#bindings-conf-details) file. The exact representation
depends on how the type is being used.

- Arguments become `nsIFoo*`.
- Return values can be `already_AddRefed<nsIFoo>` or `nsIFoo*` as
  desired. The pointer form is preferred because it results in faster
  code, but it should only be used if the return value was not addrefed
  (and so it can only be used if the return value is kept alive by the
  callee until at least the binding method has returned).
- External interfaces in sequences, dictionaries, owning unions, and
  variadic arguments are represented by `RefPtr<nsIFoo>`.

##### Web IDL interfaces

Web IDL interfaces are represented in C++ as C++ classes. The class
involved must either be refcounted or must be explicitly annotated in
`Bindings.conf` as being directly owned by the JS object. If the class
inherits from `nsISupports`, then the canonical `nsISupports` must
be on the primary inheritance chain of the object. If the interface has
a parent interface, the C++ class corresponding to the parent must be on
the primary inheritance chain of the object. This guarantees that a
`void*` can be stored in the JSObject which can then be
`reinterpret_cast` to any of the classes that correspond to interfaces
the object implements. The C++ type to be used should be the
`nativeType` listed for the interface in the
[`Bindings.conf`](#bindings-conf-details) file, or
`mozilla::dom::InterfaceName` if none is listed. The exact
representation depends on how the type is being used.

- Nullable arguments become `Foo*`.
- Non-nullable arguments become `Foo&`.
- Return values become `already_AddRefed<Foo>` or `Foo*` as
  desired. The pointer form is preferred because it results in faster
  code, but it should only be used if the return value was not addrefed
  (and so it can only be used if the return value is kept alive by the
  callee until at least the binding method has returned).
- Web IDL interfaces in sequences, dictionaries, owning unions, and
  variadic arguments are represented by `RefPtr<Foo>` if nullable and
  [`OwningNonNull<Foo>`](#owningnonnull-t) otherwise.

For example, this Web IDL:

``` webidl
interface MyInterface {
  attribute MyInterface myAttr;
  undefined passNullable(MyInterface? arg);
  MyInterface? doSomething(sequence<MyInterface> arg);
  MyInterface doTheOther(sequence<MyInterface?> arg);
  readonly attribute MyInterface? nullableAttr;
  readonly attribute MyInterface someOtherAttr;
  readonly attribute MyInterface someYetOtherAttr;
};
```

Would correspond to these C++ function declarations:

``` cpp
already_AddRefed<MyClass> MyAttr();
void SetMyAttr(MyClass& value);
void PassNullable(MyClass* arg);
already_AddRefed<MyClass> doSomething(const Sequence<OwningNonNull<MyClass>>& arg);
already_AddRefed<MyClass> doTheOther(const Sequence<RefPtr<MyClass>>& arg);
already_Addrefed<MyClass> GetNullableAttr();
MyClass* SomeOtherAttr();
MyClass* SomeYetOtherAttr(); // Don't have to return already_AddRefed!
```

##### "SpiderMonkey" interfaces

Typed array, array buffer, and array buffer view arguments are
represented by the objects in [`TypedArray.h`](#typed-arrays-arraybuffers-array-buffer-views). For
example, this Web IDL:

``` webidl
interface Test {
  undefined passTypedArrayBuffer(ArrayBuffer arg);
  undefined passTypedArray(ArrayBufferView arg);
  undefined passInt16Array(Int16Array? arg);
}
```

will correspond to these C++ function declarations:

``` cpp
void PassTypedArrayBuffer(const ArrayBuffer& arg);
void PassTypedArray(const ArrayBufferView& arg);
void PassInt16Array(const Nullable<Int16Array>& arg);
```

Typed array return values become a `JS::MutableHandle<JSObject*>` out
param appended to the argument list. This comes after all IDL arguments,
but before the `ErrorResult&`, if any, for the method. The return
value is allowed to be in any compartment; bindings will wrap it into
the context compartment as needed.

Typed arrays store a `JSObject*` and hence need to be rooted
properly. On-stack typed arrays can be declared as
`RootedTypedArray<TypedArrayType>` (e.g.
`RootedTypedArray<Int16Array>`). Typed arrays on the heap need to be
traced.

#### Dictionary types

A dictionary argument is represented by a const reference to a struct
whose name is the dictionary name in the `mozilla::dom` namespace.
The struct has one member for each of the dictionary's members with the
same name except the first letter uppercased and prefixed with "m". The
members that are required or have default values have types as described
under the corresponding Web IDL type in this document. The members that
are not required and don't have default values have those types wrapped
in [`Optional<>`](#optional-t).

Dictionary return values are represented by an out parameter whose type
is a non-const reference to the struct described above, with all the
members that have default values preinitialized to those default values.

Note that optional dictionary arguments are always forced to have a
default value of an empty dictionary by the IDL parser and code
generator, so dictionary arguments are never wrapped in `Optional<>`.

If necessary, dictionaries can be directly initialized from a
`JS::Value` in C++ code by invoking their `Init()` method. Consumers
doing this should declare their dictionary as
`RootedDictionary<DictionaryName>`. When this is done, passing in a
null `JSContext*` is allowed if the passed-in `JS::Value` is
`JS::NullValue()`. Likewise, a dictionary struct can be converted to a
`JS::Value` in C++ by calling `ToJSValue` with the dictionary as the
second argument. If `Init()` or `ToJSValue()` returns false, they
will generally set a pending exception on the JSContext; reporting those
is the responsibility of the caller.

For example, this Web IDL:

``` text
dictionary Dict {
  long foo = 5;
  DOMString bar;
};

interface Test {
  undefined initSomething(optional Dict arg = {});
};
```

will correspond to this C++ function declaration:

``` cpp
void InitSomething(const Dict& arg);
```

and the `Dict` struct will look like this:

``` cpp
struct Dict {
  bool Init(JSContext* aCx, JS::Handle<JS::Value> aVal, const char* aSourceDescription = "value");

  Optional<nsString> mBar;
  int32_t mFoo;
}
```

Note that the dictionary members are sorted in the struct in
alphabetical order.

##### API for working with dictionaries

There are a few useful methods found on dictionaries and dictionary
members that you can use to quickly determine useful things.

- **member.WasPassed()** - as the name suggests, was a particular
  member passed?
  (e.g., `if (arg.foo.WasPassed() { /* do nice things!*/ }`)
- **dictionary.IsAnyMemberPresent()** - great for checking if you need
  to do anything.
  (e.g., `if (!arg.IsAnyMemberPresent()) return; // nothing to do`)
- **member.Value()** - getting the actual data/value of a member that
  was passed.
  (e.g., `mBar.Assign(args.mBar.value())`)

Example implementation using all of the above:

``` cpp
void
MyInterface::InitSomething(const Dict& aArg){
  if (!aArg.IsAnyMemberPresent()) {
    return; // nothing to do!
  }
  if (aArg.mBar.WasPassed() && !mBar.Equals(aArg.mBar.value())) {
    mBar.Assign(aArg.mBar.Value());
  }
}
```

#### Enumeration types

Web IDL enumeration types are represented as C++ enum classes. The values
of the C++ enum are named by taking the strings in the Web IDL
enumeration, replacing all non-alphanumerics with underscores, and
uppercasing the first letter, with a special case for the empty string,
which becomes the value `_empty`.

For a Web IDL enum named `MyEnum`, the C++ enum is named `MyEnum` and
placed in the `mozilla::dom` namespace, while the values are placed in
the `mozilla::dom::MyEnum` namespace.

The type of the enum class is automatically selected to be the smallest
unsigned integer type that can hold all the values. In practice, this
is always uint8_t, because Web IDL enums tend to not have more than 255
values.

For example, this Web IDL:

``` webidl
enum MyEnum {
  "something",
  "something-else",
  "",
  "another"
};
```

would lead to this C++ enum declaration:

``` cpp
enum class MyEnum : uint8_t {
  Something,
  Something_else,
  _empty,
  Another
};
```

`mozilla::dom::GetEnumString` is a templated helper function declared in
[`BindingUtils.h`](https://searchfox.org/firefox-main/source/dom/bindings/BindingUtils.h)
and exported to `mozilla/dom/BindingUtils.h` that can be used to convert an enum
value to its corresponding string value. It returns a `const nsCString&`
containing the string value.

`mozilla::dom::StringToEnum` is a templated helper function in
[`BindingUtils.h`](https://searchfox.org/firefox-main/source/dom/bindings/BindingUtils.h)
and exported to `mozilla/dom/BindingUtils.h` that can be used to convert a
string to the corresponding enum value. It needs to be supplied with the enum
class as a template argument, and returns a `mozilla::Maybe<Enum>`. If the string
value passed to it as an argument is not one of the string values for the enum
then it returns `mozilla::Nothing()`, else it returns the right enum value in
the `mozilla::Maybe`.

`mozilla::dom::WebIDLEnumSerializer` is a templated alias in
[`BindingIPCUtils.h`](https://searchfox.org/firefox-main/source/dom/bindings/BindingIPCUtils.h)
exported to `mozilla/dom/BindingIPCUtils.h` to implement an IPC serializer with
the right validation for WebIDL enums. It uses a
`mozilla::MaxContinuousEnumValue` that is generated for every WebIDL enum to
implement the validation.

`mozilla::dom::MakeWebIDLEnumeratedRange` is a templated helper function in
[`BindingUtils.h`](https://searchfox.org/firefox-main/source/dom/bindings/BindingUtils.h)
and exported to `mozilla/dom/BindingUtils.h` that can be used to create a
`mozilla::EnumeratedRange` for a WebIDL enum.

#### Callback function types

Callback functions are represented as an object, inheriting from
[`mozilla::dom::CallbackFunction`](#callbackfunction), whose name,
in the `mozilla::dom` namespace, matches the name of the callback
function in the Web IDL. If the type is nullable, a pointer is passed in;
otherwise a reference is passed in.

The object exposes two `Call` methods, which both invoke the
underlying JS callable. The first `Call` method has the same signature
as a throwing method declared just like the callback function, with an
additional trailing `mozilla::dom::CallbackObject::ExceptionHandling aExceptionHandling`
argument, defaulting to `eReportExceptions`,
and calling it will invoke the callable with `undefined` as the
`this` value. The second `Call` method allows passing in an explicit
`this` value as the first argument. This second call method is a
template on the type of the first argument, so the `this` value can be
passed in in whatever form is most convenient, as long as it's either a
type that can be wrapped by XPConnect or a Web IDL interface type.

If `aReportExceptions` is set to `eReportExceptions`, the `Call`
methods will report JS exceptions before returning. If
`aReportExceptions` is set to `eRethrowExceptions`, JS exceptions
will be stashed in the `ErrorResult` and will be reported when the
stack unwinds to wherever the `ErrorResult` was set up.

For example, this Web IDL:

``` webidl
callback MyCallback = long (MyInterface arg1, boolean arg2);
interface MyInterface {
  attribute MyCallback foo;
  attribute MyCallback? bar;
};
```

will lead to this C++ class declaration, in the `mozilla::dom`
namespace:

``` cpp
class MyCallback : public CallbackFunction
{
public:
  int32_t
  Call(MyInterface& arg1, bool arg2, ErrorResult& rv,
       ExceptionHandling aExceptionHandling = eReportExceptions);

  template<typename T>
  int32_t
  Call(const T& thisObj, MyInterface& arg1, bool arg2, ErrorResult& rv,
       ExceptionHandling aExceptionHandling = eReportExceptions);
};
```

and these C++ function declarations in the `MyInterface` class:

``` cpp
already_AddRefed<MyCallback> GetFoo();
void SetFoo(MyCallback&);
already_AddRefed<MyCallback> GetBar();
void SetBar(MyCallback*);
```

A consumer of MyCallback would be able to use it like this:

``` cpp
void
SomeClass::DoSomethingWithCallback(MyCallback& aCallback, MyInterface& aInterfaceInstance)
{
  ErrorResult rv;
  int32_t number = aCallback.Call(aInterfaceInstance, false, rv);
  if (rv.Failed()) {
    // The error has already been reported to the JS console; you can handle
    // things however you want here.
    return;
  }

  // Now for some reason we want to catch and rethrow exceptions from the callback,
  // and use "this" as the this value for the call to JS.
  number = aCallback.Call(*this, true, rv, eRethrowExceptions);
  if (rv.Failed()) {
    // The exception is now stored on rv.  This code MUST report
    // it usefully; otherwise it will assert.
  }
}
```

#### Sequences

Sequence arguments are represented by
[`const Sequence<T>&`](#sequence-t), where `T` depends on the type
of elements in the Web IDL sequence.

Sequence return values are represented by an `nsTArray<T>` out param
appended to the argument list, where `T` is the return type for the
elements of the Web IDL sequence. This comes after all IDL arguments, but
before the `ErrorResult&`, if any, for the method.

#### Arrays

IDL array objects are not supported yet. The spec on these is likely to
change drastically anyway.

#### Union types

Union types are reflected as a struct in the `mozilla::dom` namespace.
There are two kinds of union structs: one kind does not keep its members
alive (is "non-owning"), and the other does (is "owning"). Const
references to non-owning unions are used for plain arguments. Owning
unions are used in dictionaries, sequences, and for variadic arguments.
Union return values become a non-const owning union out param. The name
of the struct is the concatenation of the names of the types in the
union, with "Or" inserted between them, and for an owning struct
"Owning" prepended. So for example, this IDL:

``` text
undefined passUnion((object or long) arg);
(object or long) receiveUnion();
undefined passSequenceOfUnions(sequence<(object or long)> arg);
undefined passOtherUnion((HTMLDivElement or ArrayBuffer or EventInit) arg);
```

would correspond to these C++ function declarations:

``` cpp
void PassUnion(const ObjectOrLong& aArg);
void ReceiveUnion(OwningObjectObjectOrLong& aArg);
void PassSequenceOfUnions(const Sequence<OwningObjectOrLong>& aArg);
void PassOtherUnion(const HTMLDivElementOrArrayBufferOrEventInit& aArg);
```

Union structs expose accessors to test whether they're of a given type
and to get hold of the data of that type. They also expose setters that
set the union as being of a particular type and return a reference to
the union's internal storage where that type could be stored. The one
exception is the `object` type, which uses a somewhat different form
of setter where the `JSObject*` is passed in directly. For example,
`ObjectOrLong` would have the following methods:

``` cpp
bool IsObject() const;
JSObject* GetAsObject() const;
void SetToObject(JSContext*, JSObject*);
bool IsLong() const;
int32_t GetAsLong() const;
int32_t& SetAsLong()
```

Owning unions used on the stack should be declared as a
`RootedUnion<UnionType>`, for example,
`RootedUnion<OwningObjectOrLong>`.

#### `Date`

Web IDL `Date` types are represented by a `mozilla::dom::Date`
struct.

### C++ reflections of Web IDL declarations

Web IDL declarations (maplike/setlike/iterable) are turned into a set of
properties and functions on the interface they are declared on. Each has
a different set of helper functions it comes with. In addition, for
iterable, there are requirements for C++ function implementation by the
interface developer.

#### Maplike

Example Interface:

``` webidl
interface StringToLongMap {
  maplike<DOMString, long>;
};
```

The bindings for this interface will generate the storage structure for
the map, as well as helper functions for accessing that structure from
C++. The generated C++ API will look as follows:

``` cpp
namespace StringToLongMapBinding {
namespace MaplikeHelpers {
void Clear(mozilla::dom::StringToLongMap* self, ErrorResult& aRv);
bool Delete(mozilla::dom::StringToLongMap* self, const nsAString& aKey, ErrorResult& aRv);
bool Has(mozilla::dom::StringToLongMap* self, const nsAString& aKey, ErrorResult& aRv);
void Set(mozilla::dom::StringToLongMap* self, const nsAString& aKey, int32_t aValue, ErrorResult& aRv);
} // namespace MaplikeHelpers
} // namespace StringToLongMapBindings
```

#### Setlike

Example Interface:

``` webidl
interface StringSet {
  setlike<DOMString>;
};
```

The bindings for this interface will generate the storage structure for
the set, as well as helper functions for accessing that structure from
c++. The generated C++ API will look as follows:

``` cpp
namespace StringSetBinding {
namespace SetlikeHelpers {
void Clear(mozilla::dom::StringSet* self, ErrorResult& aRv);
bool Delete(mozilla::dom::StringSet* self, const nsAString& aKey, ErrorResult& aRv);
bool Has(mozilla::dom::StringSet* self, const nsAString& aKey, ErrorResult& aRv);
void Add(mozilla::dom::StringSet* self, const nsAString& aKey, ErrorResult& aRv);
} // namespace SetlikeHelpers
}
```

#### Iterable

Unlike maplike and setlike, iterable does not have any C++ helpers, as
the structure backing the iterable data for the interface is left up to
the developer. With that in mind, the generated iterable bindings expect
the wrapper object to provide certain methods for the interface to
access.

Iterable interfaces have different requirements, based on if they are
single or pair value iterators.

Example Interface for a single value iterator:

``` webidl
interface LongIterable {
  iterable<long>;
  getter long(unsigned long index);
  readonly attribute unsigned long length;
};
```

For single value iterator interfaces, we treat the interface as an
[indexed getter](#indexed-getters), as required by the spec. See the
[indexed getter implementation section](#indexed-getters) for more
information on building this kind of structure.

Example Interface for a pair value iterator:

``` webidl
interface StringAndLongIterable {
  iterable<DOMString, long>;
};
```

The bindings for this pair value iterator interface require the
following methods be implemented in the C++ object:

``` cpp
class StringAndLongIterable {
public:
  // Returns the number of items in the iterable storage
  size_t GetIterableLength();
  // Returns key of pair at aIndex in iterable storage
  nsAString& GetKeyAtIndex(uint32_t aIndex);
  // Returns value of pair at aIndex in iterable storage
  uint32_t& GetValueAtIndex(uint32_t aIndex);
}
```

### Stringifiers

Named stringifiers operations in Web IDL will just invoke the
corresponding C++ method.

Anonymous stringifiers in Web IDL will invoke the C++ method called
`Stringify`. So, for example, given this IDL:

``` webidl
interface FirstInterface {
  stringifier;
};

interface SecondInterface {
  stringifier DOMString getStringRepresentation();
};
```

the corresponding C++ would be:

``` cpp
class FirstInterface {
public:
  void Stringify(nsAString& aResult);
};

class SecondInterface {
public:
  void GetStringRepresentation(nsAString& aResult);
};
```

### Legacy Callers

Only anonymous legacy callers are supported, and will invoke the C++
method called `LegacyCall`. This will be passed the JS "this" value as
the first argument, then the arguments to the actual operation. A
`JSContext` will be passed if any of the operation arguments need it.
So for example, given this IDL:

``` webidl
interface InterfaceWithCall {
  legacycaller long (float arg);
};
```

the corresponding C++ would be:

``` cpp
class InterfaceWithCall {
public:
  int32_t LegacyCall(JS::Handle<JS::Value> aThisVal, float aArgument);
};
```

### Named getters

If the interface has a named getter, the binding will expect several
methods on the C++ implementation:

- A `NamedGetter` method. This takes a property name and returns
  whatever type the named getter is declared to return. It also has a
  boolean out param for whether a property with that name should exist
  at all.
- A `NameIsEnumerable` method. This takes a property name and
  returns a boolean that indicates whether the property is enumerable.
- A `GetSupportedNames` method. This takes an unsigned integer which
  corresponds to the flags passed to the `iterate` proxy trap and
  returns a list of property names. For implementations of this method,
  the important flags is `JSITER_HIDDEN`. If that flag is set, the
  call needs to return all supported property names. If it's not set,
  the call needs to return only the enumerable ones.

The `NameIsEnumerable` and `GetSupportedNames` methods need to agree
on which names are and are not enumerable. The `NamedGetter` and
`GetSupportedNames` methods need to agree on which names are
supported.

So for example, given this IDL:

``` webidl
interface InterfaceWithNamedGetter {
  getter long(DOMString arg);
};
```

the corresponding C++ would be:

``` cpp
class InterfaceWithNamedGetter
{
public:
  int32_t NamedGetter(const nsAString& aName, bool& aFound);
  bool NameIsEnumerable(const nsAString& aName);
  undefined GetSupportedNames(unsigned aFlags, nsTArray<nsString>& aNames);
};
```

### Indexed getters

If the interface has a indexed getter, the binding will expect the
following methods on the C++ implementation:

- A `IndexedGetter` method. This takes an integer index value and
  returns whatever type the indexed getter is declared to return. It
  also has a boolean out param for whether a property with that index
  should exist at all. The implementation must set this out param
  correctly. The return value is guaranteed to be ignored if the out
  param is set to false.

So for example, given this IDL:

``` webidl
interface InterfaceWithIndexedGetter {
  getter long(unsigned long index);
  readonly attribute unsigned long length;
};
```

the corresponding C++ would be:

``` cpp
class InterfaceWithIndexedGetter
{
public:
  uint32_t Length() const;
  int32_t IndexedGetter(uint32_t aIndex, bool& aFound) const;
};
```

## Throwing exceptions from Web IDL methods, getters, and setters

Web IDL methods, getters, and setters that are [explicitly marked as
allowed to throw](#throws-getterthrows-setterthrows) have an `ErrorResult&` argument as their
last argument. To throw an exception, simply call `Throw()` on the
`ErrorResult&` and return from your C++ back into the binding code.

In cases when the specification calls for throwing a `TypeError`, you
should use `ErrorResult::ThrowTypeError()` instead of calling
`Throw()`.

## Custom extended attributes

Our Web IDL parser and code generator recognize several extended
attributes that are not present in the Web IDL spec.

### `[AllowLarge]`

Can be specified on buffer source types (`ArrayBuffer`, `ArrayBufferView`,
typed arrays) to skip the default 2 GB size check. This allows
incremental migration of consumers to support buffers larger than 2 GB.
Can be combined with `[AllowShared]`. On the C++ side, use
`ProcessData<true>(...)` or `ProcessFixedData<true>(...)` to access the
data.

### `[Alias=propName]`

This extended attribute can be specified on a method and indicates that
another property with the specified name will also appear on the
interface prototype object and will have the same Function object value
as the property for the method. For example:

``` webidl
interface MyInterface {
  [Alias=performSomething] undefined doSomething();
};
```

`MyInterface.prototype.performSomething` will have the same Function
object value as `MyInterface.prototype.doSomething`.

Multiple `[Alias]` extended attribute can be used on the one method.
`[Alias]` cannot be used on a static method, nor on methods on a
global interface (such as `Window`).

Aside from regular property names, the name of an alias can be
[Symbol.iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator).
This is specified by writing `[Alias="@@iterator"]`.

### `[BindingAlias=propName]`

This extended attribute can be specified on an attribute and indicates
that another property with the specified name will also appear on the
interface prototype object and will call the same underlying C++
implementation for the getter and setter. This is more efficient than
using the same `BinaryName` for both attributes, because it shares the
binding glue code between them. The properties still have separate
getter/setter functions in JavaScript, so from the point of view of web
consumers it's as if you actually had two separate attribute
declarations on your interface. For example:

``` webidl
interface MyInterface {
  [BindingAlias=otherAttr] readonly attribute boolean attr;
};
```

`MyInterface.prototype.otherAttr` and `MyInterface.prototype.attr`
will both exist, have separate getter/setter functions, but call the
same binding glue code and implementation function on the objects
implementing `MyInterface`.

Multiple `[BindingAlias]` extended attributes can be used on a single
attribute.

### `[BindingTemplate=(name, type, value)]`

This extended attribute can be specified on an attribute, and causes the getter
and setter for this attribute to forward to a common generated implementation,
shared with all other attributes that have a `[BindingTemplate]` with the same
value for the `name` argument. The `TemplatedAttributes` dictionary in
Bindings.conf needs to contain a definition for the template with the name
`name`. The argument `type::value` will be passed when calling the common
generated implementation.

This is aimed at very specialized use cases where an interface has a
large number of attributes that all have the same type, and for which we have a
native implementation that's common to all these attributes, and typically uses
some id based on the attribute's name in the implementation. All the attributes
that use the same template need to mostly have the same extended attributes,
except form a small number that are allowed to differ (`[BindingTemplate]`,
`[BindingAlias]`, `[Pure]`, [`Pref`] and [`Func`], and the annotations for
whether the getter and setter throws exceptions).

### `[ChromeOnly]`

This extended attribute can be specified on any method, attribute, or
constant on an interface or on an interface as a whole. It can also be
specified on dictionary members.

Interface members flagged as `[ChromeOnly]` are only exposed in chrome
Windows (and in particular, are not exposed to webpages). From the point
of view of web content, it's as if the interface member were not there
at all. These members _are_ exposed to chrome script working with a
content object via Xrays.

If specified on an interface as a whole, this functions like
[`[Func]`](#func-funcname) except that the binding code will automatically
check whether the caller script has the system principal (is chrome or a
worker started from a chrome page) instead of calling into the C++
implementation to determine whether to expose the interface object on
the global. This means that accessing a content global via Xrays will
show `[ChromeOnly]` interface objects on it.

If specified on a dictionary member, then the dictionary member will
only appear to exist in system-privileged code.

This extended attribute can be specified together with `[Func]`, and
`[Pref]`. If more than one of these is specified, all conditions will
need to test true for the interface or interface member to be exposed.

### `[Pref=prefname]`

This extended attribute can be specified on any method, attribute, or
constant on an interface or on an interface as a whole. It can also be
specified on dictionary members. It takes a value, which must be the
name of a boolean preference exposed from `StaticPrefs`. The
`StaticPrefs` function that will be called is calculated from the
value of the extended attribute, with dots replaced by underscores
(`StaticPrefs::my_pref_name()` in the example below).

If specified on an interface member, the interface member involved is
only exposed if the preference is set to `true`. An example of how
this can be used:

``` webidl
interface MyInterface {
  attribute long alwaysHere;
  [Pref="my.pref.name"] attribute long onlyHereIfEnabled;
};
```

If specified on an interface as a whole, this functions like
[`[Func]`](#func-funcname) except that the binding will check the value of
the preference directly without calling into the C++ implementation of
the interface at all. This is useful when the enable check is simple and
it's desirable to keep the prefname with the Web IDL declaration.

If specified on a dictionary member, the web-observable behavior when
the pref is set to false will be as if the dictionary did not have a
member of that name defined. That means that on the JS side no
observable get of the property will happen. On the C++ side, the
behavior would be as if the passed-in object did not have a property
with the relevant name: the dictionary member would either be
`!Passed()` or have the default value if there is a default value.

> An example of how this can be used:

``` webidl
[Pref="my.pref.name"]
interface MyConditionalInterface {
};
```

This extended attribute can be specified together with `[ChromeOnly]`,
and `[Func]`. If more than one of these is specified, all conditions
will need to test true for the interface or interface member to be
exposed.

### `[Func="funcname"]`

This extended attribute can be specified on any method, attribute, or
constant on an interface or on an interface as a whole. It can also be
specified on dictionary members. It takes a value, which must be the
name of a static function.

If specified on an interface member, the interface member involved is
only exposed if the specified function returns `true`. An example of
how this can be used:

``` webidl
interface MyInterface {
  attribute long alwaysHere;
  [Func="MyClass::StuffEnabled"] attribute long onlyHereIfEnabled;
};
```

The function is invoked with two arguments: the `JSContext` that the
operation is happening on and the `JSObject` for the global of the
object that the property will be defined on if the function returns
true. In particular, in the Xray case the `JSContext` is in the caller
compartment (typically chrome) but the `JSObject` is in the target
compartment (typically content). This allows the method implementation
to select which compartment it cares about in its checks.

The above IDL would also require the following C++:

``` cpp
class MyClass {
  static bool StuffEnabled(JSContext* cx, JSObject* obj);
};
```

If specified on an interface as a whole, then lookups for the interface
object for this interface on a DOM Window will only find it if the
specified function returns true. For objects that can only be created
via a constructor, this allows disabling the functionality altogether
and making it look like the feature is not implemented at all.

If specified on a dictionary member, the web-observable behavior when
the function returns false will be as if the dictionary did not have a
member of that name defined. That means that on the JS side no
observable get of the property will happen. On the C++ side, the
behavior would be as if the passed-in object did not have a property
with the relevant name: the dictionary member would either be
`!Passed()` or have the default value if there is a default value.

An example of how `[Func]` can be used:

``` webidl
[Func="MyClass::MyConditionalInterfaceEnabled"]
interface MyConditionalInterface {
};
```

In this case, the C++ function is passed a `JS::Handle<JSObject*>`. So
the C++ in this case would look like this:

``` cpp
class MyClass {
  static bool MyConditionalInterfaceEnabled(JSContext* cx, JS::Handle<JSObject*> obj);
};
```

Just like in the interface member case, the `JSContext` is in the
caller compartment but the `JSObject` is the actual object the
property would be defined on. In the Xray case that means obj is in the
target compartment (typically content) and `cx` is typically chrome.

This extended attribute can be specified together with `[ChromeOnly]`,
and `[Pref]`. If more than one of these is specified, all conditions
will need to test true for the interface or interface member to be
exposed.

Binding code will include the headers necessary for a `[Func]`, unless
the interface is using a non-default header file. If a non-default
header file is used, that header file needs to do any header inclusions
necessary for `[Func]` annotations.

### `[Throws]`, `[GetterThrows]`, `[SetterThrows]`

Used to flag methods or attributes as allowing the C++ callee to throw.
This causes the binding generator, and in many cases the JIT, to
generate extra code to handle possible exceptions. Possibly-throwing
methods and attributes get an `ErrorResult&` argument.

`[Throws]` applies to both methods and attributes; for attributes it
means both the getter and the setter can throw. `[GetterThrows]`
applies only to attributes. `[SetterThrows]` applies only to
non-readonly attributes.

For interfaces flagged with `[JSImplementation]`, all methods and
properties are assumed to be able to throw and do not need to be flagged
as throwing.

### `[DependsOn]`

Used for a method or attribute to indicate what the return value depends
on. Possible values are:

- `Everything`

   This value can't actually be specified explicitly; this is the
   default value you get when `[DependsOn]` is not specified. This
   means we don't know anything about the return value's dependencies
   and hence can't rearrange other code that might change values around
   the method or attribute.

- `DOMState`

   The return value depends on the state of the "DOM", by which we mean
   all objects specified via Web IDL. The return value is guaranteed to
   not depend on the state of the JS heap or other JS engine data
   structures, and is guaranteed to not change unless some function with
   [`[Affects=Everything]`](#affects) is executed.

- `DeviceState`

   The return value depends on the state of the device we're running on
   (e.g., the system clock). The return value is guaranteed to not be
   affected by any code running inside Gecko itself, but we might get a
   new value every time the method or getter is called even if no Gecko
   code ran between the calls.

- `Nothing`

   The return value is a constant that never changes. This value cannot
   be used on non-readonly attributes, since having a non-readonly
   attribute whose value never changes doesn't make sense.

Values other than `Everything`, when used in combination with
[`[Affects=Nothing]`](#affects), can used by the JIT to
perform loop-hoisting and common subexpression elimination on the return
values of IDL attributes and methods.

### `[Affects]`

Used for a method or attribute getter to indicate what sorts of state
can be affected when the function is called. Attribute setters are, for
now, assumed to affect everything. Possible values are:

- `Everything`

   This value can't actually be specified explicitly; this is the
   default value you get when `[Affects]` is not specified. This means
   that calling the method or getter might change any mutable state in
   the DOM or JS heap.

- `Nothing`

   Calling the method or getter will have no side-effects on either the
   DOM or the JS heap.

Methods and attribute getters with `[Affects=Nothing]` are allowed to
throw exceptions, as long as they do so deterministically. In the case
of methods, whether an exception is thrown is allowed to depend on the
arguments, as long as calling the method with the same arguments will
always either throw or not throw.

The `Nothing` value, when used with `[DependsOn]` values other than
`Everything`, can used by the JIT to perform loop-hoisting and common
subexpression elimination on the return values of IDL attributes and
methods, as well as code motion past DOM methods that might depend on
system state but have no side effects.

### `[Pure]`

This is an alias for `[Affects=Nothing, DependsOn=DOMState]`.
Attributes/methods flagged in this way promise that they will keep
returning the same value as long as nothing that has
`[Affects=Everything]` executes.

### `[Constant]`

This is an alias for `[Affects=Nothing, DependsOn=Nothing]`. Used to
flag readonly attributes or methods that could have been annotated with
`[Pure]` and also always return the same value. This should only be
used when it's absolutely guaranteed that the return value of the
attribute getter will always be the same from the JS engine's point of
view.

The spec's `[SameObject]` extended attribute is an alias for
`[Constant]`, but can only be applied to things returning objects,
whereas `[Constant]` can be used for any type of return value.

### `[NeedResolve]`

Used to flag interfaces which have a custom resolve hook. This
annotation will cause the `DoResolve` method to be called on the
underlying C++ class when a property lookup happens on the object. The
signature of this method is:
`bool DoResolve(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>)`.
Here the passed-in object is the object the property lookup is happening
on (which may be an Xray for the actual DOM object) and the jsid is the
property name. The value that the property should have is returned in
the `MutableHandle<Value>`, with `UndefinedValue()` indicating that
the property does not exist.

If this extended attribute is used, then the underlying C++ class must
also implement a method called `GetOwnPropertyNames` with the
signature
`void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames, ErrorResult& aRv)`.
This method will be called by the JS engine's enumerate hook and must
provide a superset of all the property names that `DoResolve` might
resolve. Providing names that `DoResolve` won't actually resolve is
OK.

### `[HeaderFile="path/to/headerfile.h"]`

Indicates where the implementation can be found. Similar to the
headerFile annotation in Bindings.conf. Just like headerFile in
Bindings.conf, should be avoided.

### `[JSImplementation="@mozilla.org/some-contractid;1"]`

Used on an interface to provide the contractid of the [JavaScript
component implementing the
interface](#implementing-webidl-using-javascript).

### `[StoreInSlot]`

Used to flag attributes that can be gotten very quickly from the JS
object by the JIT. Such attributes will have their getter called
immediately when the JS wrapper for the DOM object is created, and the
returned value will be stored directly on the JS object. Later gets of
the attribute will not call the C++ getter and instead use the cached
value. If the value returned by the attribute needs to change, the C++
code should call the `ClearCachedFooValue` method in the namespace of
the relevant binding, where `foo` is the name of the attribute. This
will immediately call the C++ getter and cache the value it returns, so
it needs a `JSContext` to work on. This extended attribute can only be
used on attributes whose getters are [`[Pure]`](#pure) or
[`[Constant]`](#constant) and which are not
[`[Throws]`](#throws-getterthrows-setterthrows) or [`[GetterThrows]`](#throws-getterthrows-setterthrows).

So for example, given this IDL:

``` webidl
interface MyInterface {
  [Pure, StoreInSlot] attribute long myAttribute;
};
```

the C++ implementation of MyInterface would clear the cached value by
calling
`mozilla::dom::MyInterface_Binding::ClearCachedMyAttributeValue(cx, this)`.
This function will return false on error and the caller is responsible
for handling any JSAPI exception that is set by the failure.

If the attribute is not readonly, setting it will automatically clear
the cached value and reget it again before the setter returns.

### `[Cached]`

Used to flag attributes that, when their getter is called, will cache
the returned value on the JS object. This can be used to implement
attributes whose value is a sequence or dictionary (which would
otherwise end up returning a new object each time and hence not be
allowed in Web IDL).

Unlike [`[StoreInSlot]`](#storeinslot) this does _not_ cause the
getter to be eagerly called at JS wrapper creation time; the caching is
lazy. `[Cached]` attributes must be [`[Pure]`](#pure) or
[`[Constant]`](#constant), because otherwise not calling the C++
getter would be observable, but are allowed to have throwing getters.
Their cached value can be cleared by calling the `ClearCachedFooValue`
method in the namespace of the relevant binding, where `foo` is the
name of the attribute. Unlike `[StoreInSlot]` attributes, doing so
will not immediately invoke the getter, so it does not need a
`JSContext`.

So for example, given this IDL:

``` webidl
interface MyInterface {
  [Pure, Cached] attribute long myAttribute;
};
```

the C++ implementation of MyInterface would clear the cached value by
calling
`mozilla::dom::MyInterface_Binding::ClearCachedMyAttributeValue(this)`.
JS-implemented Web IDL can clear the cached value by calling
`this.__DOM_IMPL__._clearCachedMyAttributeValue()`.

If the attribute is not readonly, setting it will automatically clear
the cached value.

### `[Frozen]`

Used to flag attributes that, when their getter is called, will call
[`Object.freeze`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)
on the return value before returning it. This extended attribute is only
allowed on attributes that return sequences, dictionaries and
`MozMap`, and corresponds to returning a frozen `Array` (for the
sequence case) or `Object` (for the other two cases).

### `[BinaryName]`

`[BinaryName]` can be specified on method or attribute to change the
C++ function name that will be used for the method or attribute. It
takes a single string argument, which is the name you wish the method or
attribute had instead of the one it actually has.

For example, given this IDL:

``` webidl
interface InterfaceWithRenamedThings {
  [BinaryName="renamedMethod"]
  undefined someMethod();
  [BinaryName="renamedAttribute"]
  attribute long someAttribute;
};
```

the corresponding C++ would be:

``` cpp
class InterfaceWithRenamedThings
{
public:
  void RenamedMethod();
  int32_t RenamedAttribute();
  void SetRenamedAttribute(int32_t);
};
```

### `[Deprecated="tag"]`

When deprecating an interface or method, the `[Deprecated]` annotation
causes the Web IDL compiler to insert code that generates deprecation
warnings. This annotation can be added to interface methods or
interfaces. Adding this to an interface causes a warning to be issued
the first time the object is constructed, or any static method on the
object is invoked.

The complete list of valid deprecation tags is maintained in
[nsDeprecatedOperationList.inc](https://searchfox.org/firefox-main/source/dom/base/nsDeprecatedOperationList.inc).
Each new tag requires that a localized string be defined, containing the
deprecation message to display.

### `[CrossOriginReadable]`

Used to flag an attribute that, when read, will not have the same-origin
constraint tested: it can be read from a context with a different
origin.

### `[CrossOriginWrite]`

Used to flag an attribute that, when written, will not have the
same-origin constraint tested: it can be written from a context with a
different origin.

### `[CrossOriginCallable]`

Used to flag a method that, when called, will not have the same-origin
constraint tested: it can be called from a context with a different
origin.

### `[SecureContext]`

We implement the [standard extended
attribute](https://webidl.spec.whatwg.org/#SecureContext) with a few
details specific to Gecko:

- System principals are considered secure.
- An extension poking at non-secured DOM objects will see APIs marked
  with `[SecureContext]`.
- XPConnect sandboxes don't see `[SecureContext]` APIs, except if
  they're created with `isSecureContext: true`.

### `[NeedsSubjectPrincipal]`, `[GetterNeedsSubjectPrincipal]`, `[SetterNeedsSubjectPrincipal]`

Used to flag a method or an attribute that needs to know the subject
principal. This principal will be passed as argument. The argument
will be a `nsIPrincipal&` because a subject principal is always
available.

`[NeedsSubjectPrincipal]` applies to both methods and attributes; for
attributes it means both the getter and the setter need a subject
principal. `[GetterNeedsSubjectPrincipal]` applies only to attributes.
`[SetterNeedsSubjectPrincipal]` applies only to non-readonly
attributes.

These attributes may also be constrained to non-system principals using
`[{Getter,Setter,}NeedsSubjectPrincipal=NonSystem]`. This changes the argument
type to `nsIPrincipal*`, and passes `nullptr` when called with a system
principal.

### `[NeedsCallerType]`

Used to flag a method or an attribute that needs to know the caller
type, in the `mozilla::dom::CallerType` sense. This can be safely
used for APIs exposed in workers; there it will indicate whether the
worker involved is a `ChromeWorker` or not. At the moment the only
possible caller types are `System` (representing system-principal
callers) and `NonSystem`.

### `[GenerateInit]`

When set on a dictionary it will add two `Init` methods to the generated C++
class with the following signatures:

``` cpp
bool Init(BindingCallContext& cx, JS::Handle<JS::Value> val, const char* sourceDescription="Value", bool passedToJSImpl=false);
bool Init(JSContext* cx_, JS::Handle<JS::Value> val, const char* sourceDescription="Value", bool passedToJSImpl=false);
```

These methods will initialize the dictionary from `val` by following WebIDL's
[JavaScript type mapping](https://webidl.spec.whatwg.org/#js-dictionary).

### `[GenerateInitFromJSON]`

When set on a dictionary it will add `Init` methods to the generated C++
class with the following signatures:

``` cpp
bool Init(const nsAString& aJSON);
bool Init(const nsACString& aJSON);
```

This extended attribute will only have an effect if all of the types of the
dictionary's members are representable in JSON (they are a string type, a
primitive type that's not an unrestricted float/double, a void type, or a
sequence, union, dictionary or record containing these types).

The method is expected to be called with a JSON string as input. The JSON string
will be parsed into a JavaScript value, and then the dictionary is initialized
with this value by following WebIDL's
[JavaScript type mapping](https://webidl.spec.whatwg.org/#js-dictionary).

Note: As a side-effect of how this is implemented it will also add the two
`Init` methods that would be added by a [`[GenerateInit]`](#generateinit)
extended attribute.

### `[GenerateToJSON]`

When set on a dictionary it will add `ToJSON` methods to the generated C++
class with the following signatures:

``` cpp
bool ToJSON(nsAString& aJSON);
bool ToJSON(nsACString& aJSON);
```

The method will generate a JSON representation of the dictionary members' values
in `aJSON` by converting the dictionary to a JavaScript object by following
WebIDL's [JavaScript type mapping](https://webidl.spec.whatwg.org/#js-dictionary)
and then converting that object to a JSON string.

The same restrictions on types applies as on
[`[GenerateInitFromJSON]`](#generateinitfromjson).

Note: As a side-effect of how this is implemented it will also add the
`ToObjectInternal` method that would be added by a
[`[GenerateConversionToJS]`](#generateconversiontojs) extended attribute.

### `[GenerateConversionToJS]`

When set on a dictionary it will add a `ToObjectInternal` method to the
generated C++ class with the following signature:

``` cpp
bool ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval);
```

The method will create a JavaScript object by following WebIDL's
[JavaScript type mapping](https://webidl.spec.whatwg.org/#js-dictionary).

### `[GenerateEqualityOperator]`

When set on a dictionary it will add an equality operator to the generated C++
class.

This is only allowed on dictionaries who only have members (own or inherited)
with string, primitive or enum types.

### `[Unsorted]`

When set on a dictionary the dictionary's members will not be sorted in
lexicographic order (which is specified by WebIDL).

This should only ever be used on internal APIs that are not exposed to the Web!

### `[ReflectedHTMLAttributeReturningFrozenArray]`

Used to flag a HTML reflected IDL attribute as having a `FrozenArray<T>?` type,
where `T` is either `Element` or an interface that inherits from `Element`. This
should only be used to implement the algorithms for that kind of reflected IDL
attributes.

When this attribute's getter is called, it will cache the JS reflection of the
returned value on the JS object. The C++ getter will be passed an additional
`bool*` argument before the result argument. If this argument is not `null` then
the implementation is supposed to set the `bool` that this argument is pointing
to to whether the
[attr-associated elements](https://html.spec.whatwg.org/#attr-associated-elements)
and the
[cached attr-associated elements](https://html.spec.whatwg.org/#cached-attr-associated-elements)
are equal. If it is not `null`, and the getter sets the pointee to `true` then
the cached JS value will be returned, and the result value from the C++ getter
will be ignored (so there is no need to set the result's value). If it is
`null`, or the getter sets the pointee to `false`, then the cached value will be
set to the JS reflection of the result value from the C++ getter, and that JS
value will then be returned.

Note that this will not cause the JIT to directly get the cached value from the
slot (as `[StoreInSlot]` or `[Cached]` would). The setter will also not clear
the cached value from the slot.

For example, this IDL:

``` webidl
interface Element {
  [Frozen, ReflectedHTMLAttributeReturningFrozenArray]
  attribute sequence<Element>? reflectedHTMLAttribute;
};
```

will require the following declarations in `Element`:

``` cpp
class Element {
  // …
  void GetReflectedHTMLAttribute(
    bool* aUseCachedValue, Nullable<nsTArray<RefPtr<Element>>>& aResult);
  void SetReflectedHTMLAttribute(
    const Nullable<Sequence<OwningNonNull<Element>>>& aValue);
};
```

## Helper objects

The C++ side of the bindings uses a number of helper objects.

### `Nullable<T>`

`Nullable<>` is a struct declared in
[`Nullable.h`](https://searchfox.org/firefox-main/source/dom/bindings/Nullable.h)
and exported to `mozilla/dom/Nullable.h` that is used to represent
nullable values of types that don't have a natural way to represent
null.

`Nullable<T>` has an `IsNull()` getter that returns whether null is
represented and a `Value()` getter that returns a `const T&` and can
be used to get the value when it's not null.

`Nullable<T>` has a `SetNull()` setter that sets it as representing
null and two setters that can be used to set it to a value:
`void SetValue(T)` (for setting it to a given value) and
`T& SetValue()` for directly modifying the underlying `T&`.

### `Optional<T>`

`Optional<>` is a struct declared in
[`BindingDeclarations.h`](https://searchfox.org/firefox-main/source/dom/bindings/BindingDeclarations.h)
and exported to `mozilla/dom/BindingDeclarations.h` that is used to
represent optional arguments and dictionary members, but only those that
have no default value.

`Optional<T>` has a `WasPassed()` getter that returns true if a
value is available. In that case, the `Value()` getter can be used to
get a `const T&` for the value.

### `NonNull<T>`

`NonNull<T>` is a struct declared in
[`BindingUtils.h`](https://searchfox.org/firefox-main/source/dom/bindings/BindingUtils.h)
and exported to `mozilla/dom/BindingUtils.h` that is used to represent
non-null C++ objects. It has a conversion operator that produces `T&`.

### `OwningNonNull<T>`

`OwningNonNull<T>` is a struct declared in
[`OwningNonNull.h`](https://searchfox.org/firefox-main/source/xpcom/base/OwningNonNull.h)
and exported to `mozilla/OwningNonNull.h` that is used to represent
non-null C++ objects and holds a strong reference to them. It has a
conversion operator that produces `T&`.

### Typed arrays, arraybuffers, array buffer views

`TypedArray.h` is exported to `mozilla/dom/TypedArray.h` and exposes
structs that correspond to the various typed array types, as well as
`ArrayBuffer` and `ArrayBufferView`, all in the `mozilla::dom`
namespace. Each struct has a `Data()` method that returns a pointer to
the relevant type (`uint8_t` for `ArrayBuffer` and
`ArrayBufferView`) and a `Length()` method that returns the length
in units of `*Data()`. So for example, `Int32Array` has a `Data()`
returning `int32_t*` and a `Length()` that returns the number of
32-bit ints in the array.

By default, the generated bindings reject typed arrays, `ArrayBuffer`,
and `ArrayBufferView` objects larger than 2 GB. To allow larger buffers,
use the [`[AllowLarge]`](#allowlarge) extended attribute.

### `Sequence<T>`

`Sequence<>` is a type declared in
[`BindingDeclarations.h`](https://searchfox.org/firefox-main/source/dom/bindings/BindingDeclarations.h)
and exported to `mozilla/dom/BindingDeclarations.h` that is used to
represent sequence arguments. It's some kind of typed array, but which
exact kind is opaque to consumers. This allows the binding code to
change the exact definition (e.g., to use auto arrays of different sizes
and so forth) without having to update all the callees.

### `CallbackFunction`

`CallbackFunction` is a type declared in
[CallbackFunction.h](https://searchfox.org/firefox-main/source/dom/bindings/CallbackFunction.h)
and exported to `mozilla/dom/CallbackFunction.h` that is used as a
common base class for all the generated callback function
representations. This class inherits from `nsISupports`, and consumers
must make sure to cycle-collect it, since it keeps JS objects alive.

### `CallbackInterface`

`CallbackInterface` is a type declared in
[CallbackInterface.h](https://searchfox.org/firefox-main/source/dom/bindings/CallbackInterface.h)
and exported to `mozilla/dom/CallbackInterface.h` that is used as a
common base class for all the generated callback interface
representations. This class inherits from `nsISupports`, and consumers
must make sure to cycle-collect it, since it keeps JS objects alive.

### `DOMString`

`DOMString` is a class declared in
[BindingDeclarations.h](https://searchfox.org/firefox-main/source/dom/bindings/BindingDeclarations.h)
and exported to `mozilla/dom/BindingDeclarations.h` that is used for
Web IDL `DOMString` return values. It has a conversion operator to
`nsString&` so that it can be passed to methods that take that type or
`nsAString&`, but callees that care about performance, have an
`StringBuffer` available, and promise to hold on to the
`StringBuffer` at least until the binding code comes off the stack
can also take a `DOMString` directly for their string return value and
call its `SetStringBuffer` method with the `StringBuffer` and its
length. This allows the binding code to avoid extra reference-counting
of the string buffer in many cases, and allows it to take a faster
codepath even if it does end up having to addref the `StringBuffer`.

### `GlobalObject`

`GlobalObject` is a class declared in
[BindingDeclarations.h](https://searchfox.org/firefox-main/source/dom/bindings/BindingDeclarations.h)
and exported to `mozilla/dom/BindingDeclarations.h` that is used to
represent the global object for static attributes and operations
(including constructors). It has a `Get()` method that returns the
`JSObject*` for the global and a `GetAsSupports()` method that
returns an `nsISupports*` for the global on the main thread, if such
is available. It also has a `Context()` method that returns the
`JSContext*` the call is happening on. A caveat: the compartment of
the `JSContext` may not match the compartment of the global!

### `Date`

`Date` is a class declared in
[BindingDeclarations.h](https://searchfox.org/firefox-main/source/dom/bindings/BindingDeclarations.h)
and exported to `mozilla/dom/BindingDeclarations.h` that is used to
represent Web IDL Dates. It has a `TimeStamp()` method returning a
double which represents a number of milliseconds since the epoch, as
well as `SetTimeStamp()` methods that can be used to initialize it
with a double timestamp or a JS `Date` object. It also has a
`ToDateObject()` method that can be used to create a new JS `Date`.

### `ErrorResult`

`ErrorResult` is a class declared in
[ErrorResult.h](https://searchfox.org/firefox-main/source/dom/bindings/ErrorResult.h)
and exported to `mozilla/ErrorResult.h` that is used to represent
exceptions in Web IDL bindings. This has the following methods:

- `Throw`: allows throwing an `nsresult`. The `nsresult` must be
  a failure code.
- `ThrowTypeError`: allows throwing a `TypeError` with the given
  error message. The list of allowed `TypeError`s and corresponding
  messages is in
  [`dom/bindings/Errors.msg`](https://searchfox.org/firefox-main/source/dom/bindings/Errors.msg).
- `ThrowJSException`: allows throwing a preexisting JS exception
  value. However, the `MightThrowJSException()` method must be called
  before any such exceptions are thrown (even if no exception is
  thrown).
- `Failed`: checks whether an exception has been thrown on this
  `ErrorResult`.
- `ErrorCode`: returns a failure `nsresult` representing (perhaps
  incompletely) the state of this `ErrorResult`.
- `operator=`: takes an `nsresult` and acts like `Throw` if the
  result is an error code, and like a no-op otherwise (unless an
  exception has already been thrown, in which case it asserts). This
  should only be used for legacy code that has nsresult everywhere; we
  would like to get rid of this operator at some point.

## Events

Simple `Event` interfaces can be automatically generated by adding the
interface file to GENERATED_EVENTS_WEBIDL_FILES in the
appropriate dom/webidl/moz.build file. You can also take a simple
generated C++ file pair and use it to build a more complex event (i.e.,
one that has methods).

### Event handler attributes

A lot of interfaces define event handler attributes, like:

``` webidl
attribute EventHandler onthingchange;
```

If you need to implement an event handler attribute for an interface, in
the definition (header file), you use the handy
"IMPL_EVENT_HANDLER" macro:

``` cpp
IMPL_EVENT_HANDLER(onthingchange);
```

The "onthingchange" needs to be added to the StaticAtoms.py file:

``` py
Atom("onthingchange", "onthingchange")
```

The actual implementation (.cpp) for firing the event would then look
something like:

``` cpp
nsresult
MyInterface::DispatchThingChangeEvent()
{
  NS_NAMED_LITERAL_STRING(type, "thingchange");
  EventInit init;
  init.mBubbles = false;
  init.mCancelable = false;
  RefPtr<Event> event = Event::Constructor(this, type, init);
  event->SetTrusted(true);
  ErrorResult rv;
  DispatchEvent(*event, rv);
  return rv.StealNSResult();  // Assuming the caller cares about the return code.
}
```

## `Bindings.conf` details

Write me. In particular, need to describe at least use of `concrete`,
`prefable`, and `addExternalInterface`.

### How to get a JSContext passed to a given method

In some rare cases you may need a `JSContext*` argument to be passed
to a C++ method that wouldn't otherwise get such an argument. To see how
to achieve this, search for `implicitJSContext` in
[dom/bindings/Bindings.conf](#bindings-conf-details).

## Implementing Web IDL using Javascript

<div class="warning"><div class="admonition-title">Warning</div>

Implementing Web IDL using Javascript is deprecated. New interfaces
should always be implemented in C++!

</div>

It is possible to implement Web IDL interfaces in JavaScript within Gecko
-- however, **this is limited to interfaces that are not exposed in Web
Workers**. When the binding occurs, two objects are created:

- _Content-exposed object:_ what gets exposed to the web page.
- _Implementation object:_ running as a chrome-privileged script. This
  allows the implementation object to have various APIs that the
  content-exposed object does not.

Because there are two types of objects, you have to be careful about
which object you are creating.

### Creating JS-implemented Web IDL objects

To create a JS-implemented Web IDL object, one must create both the
chrome-side implementation object and the content-side page-exposed
object. There are three ways to do this.

#### Using the Web IDL constructor

If the interface has a constructor, a content-side object can be created
by getting that constructor from the relevant content window and
invoking it. For example:

``` js
var contentObject = new contentWin.RTCPeerConnection();
```

The returned object will be an Xray wrapper for the content-side object.
Creating the object this way will automatically create the chrome-side
object using its contractID.

This method is limited to the constructor signatures exposed to
webpages. Any additional configuration of the object needs to be done
methods on the interface.

Creating many objects this way can be slow due to the createInstance
overhead involved.

#### Using a `_create` method

A content-side object can be created for a given chrome-side object by
invoking the static `_create` method on the interface. This method
takes two arguments: the content window in which to create the object
and the chrome-side object to use. For example:

``` js
var contentObject = RTCPeerConnection._create(contentWin, new
MyPeerConnectionImpl());
```

However, if you are in a JS component, you may only be able to get to
the correct interface object via some window object. In this case, the
code would look more like:

``` js
var contentObject = contentWin.RTCPeerConnection._create(contentWin,
new MyPeerConnectionImpl());
```

Creating the object this way will not invoke its `__init` method or
`init` method.

#### By returning a chrome-side object from a JS-implemented Web IDL method

If a JS-implemented Web IDL method is declared as returning a
JS-implemented interface, then a non-Web IDL object returned from that
method will be treated as the chrome-side part of a JS-implemented
WebIdL object and the content-side part will be automatically created.

Creating the object this way will not invoke its `__init` method or
`init` method.

### Implementing a Web IDL object in JavaScript

To implement a Web IDL interface in JavaScript, first add a Web IDL file,
in the same way as you would for a C++-implemented interface. To support
implementation in JS, you must add an extended attribute
`JSImplementation="CONTRACT_ID_STRING"` on your interface, where
CONTRACT_ID_STRING is the XPCOM component contract ID of the JS
implementation -- note ";1" is just a Mozilla convention for versioning
APIs. Here's an example:

``` webidl
[JSImplementation="@mozilla.org/my-number;1"]
interface MyNumber {
  constructor(optional long firstNumber);
  attribute long value;
  readonly attribute long otherValue;
  undefined doNothing();
};
```

Next, create an XPCOM component that implements this interface. Use
the same contract ID as you specified in the Web IDL file. The class
ID doesn't matter, except that it should be a newly generated one. For
`QueryInterface`, you only need to implement `nsISupports`, not
anything corresponding to the Web IDL interface. The name you use for
the XPCOM component should be distinct from the name of the interface,
to avoid confusing error messages.

Web IDL attributes are implemented as properties on the JS object or its
prototype chain, whereas Web IDL methods are implemented as methods on
the object or prototype. Note that any other instances of the interface
that you are passed in as arguments are the full web-facing version of
the object, and not the JS implementation, so you currently cannot
access any private data.

The Web IDL constructor invocation will first create your object. If the
XPCOM component implements `nsIDOMGlobalPropertyInitializer`, then
the object's `init` method will be invoked with a single argument:
the content window the constructor came from. This allows the JS
implementation to know which content window it's associated with.
The `init` method should not return anything. After this, the
content-side object will be created. Then,if there are any constructor
arguments, the object's `__init` method will be invoked, with the
constructor arguments as its arguments.

### Static Members

Static attributes and methods are not supported on JS-implemented Web IDL
(see [bug
863952](https://bugzilla.mozilla.org/show_bug.cgi?id=863952)).
However, with the changes in [bug
1172785](https://bugzilla.mozilla.org/show_bug.cgi?id=1172785) you
can route static methods to a C++ implementation on another object using
a `StaticClassOverride` annotation. This annotation includes the
full, namespace-qualified name of the class that contains an
implementation of the named method. The include for that class must be
found in a directory based on its name.

``` webidl
[JSImplementation="@mozilla.org/dom/foo;1"]
interface Foo {
  [StaticClassOverride="mozilla::dom::OtherClass"]
  static Promise<undefined> doSomething();
};
```

Rather than calling into a method on the JS implementation; calling
`Foo.doSomething()` will result in calling
`mozilla::dom::OtherClass::DoSomething()`.

### Checking for Permissions or Preferences

With JS-implemented Web IDL, the `init` method should only return
undefined. If any other value, such as `null`, is returned, the
bindings code will assert or crash. In other words, it acts like it has
an "undefined" return type. Preference or permission checking should be
implemented by adding an extended attribute to the Web IDL interface.
This has the advantage that if the check fails, the constructor or
object will not show up at all.

For preference checking, add an extended attribute
`Pref="myPref.enabled"` where `myPref.enabled` is the preference
that should be checked. `SettingsLock` is an example of this.

For permissions or other kinds of checking, add an extended attribute
`Func="MyPermissionChecker"` where `MyPermissionChecker` is a
function implemented in C++ that returns true if the interface should be
enabled. This function can do whatever checking is needed. One example
of this is `PushManager`.

### Example

Here's an example JS implementation of the above interface. The
`invisibleValue` field will not be accessible to web content, but is
usable by the doNothing() method.

``` js
function MyNumberInner() {
  this.value = 111;
  this.invisibleValue = 12345;
}

MyNumberInner.prototype = {
  classDescription: "Get my number XPCOM Component",
  contractID: "@mozilla.org/my-number;1",
  QueryInterface: ChromeUtils.generateQI([]),
  doNothing: function() {},
  get otherValue() { return this.invisibleValue - 4; },
  __init: function(firstNumber) {
    if (arguments.length > 0) {
      this.value = firstNumber;
    }
  }
}
```

Finally, add a component and a contract and whatever other manifest
stuff you need to implement an XPCOM component.

### Guarantees provided by bindings

When implementing a Web IDL interface in JavaScript, certain guarantees
will be provided by the binding implementation. For example, string or
numeric arguments will actually be primitive strings or numbers.
Dictionaries will contain only the properties that they are declared to
have, and they will have the right types. Interface arguments will
actually be objects implementing that interface.

What the bindings will NOT guarantee is much of anything about
`object` and `any` arguments. They will get cross-compartment
wrappers that make touching them from chrome code not be an immediate
security bug, but otherwise they can have quite surprising behavior if
the page is trying to be malicious. Try to avoid using these types if
possible.

### Accessing the content object from the implementation

If the JS implementation of the Web IDL interface needs to access the
content object, it is available as a property called `__DOM_IMPL__` on
the chrome implementation object. This property only appears after the
content-side object has been created. So it is available in `__init`
but not in `init`.

### Determining the principal of the caller that invoked the Web IDL API

This can be done by calling
`Component.utils.getWebIDLCallerPrincipal()`.

### Throwing exceptions from JS-implemented APIs

There are two reasons a JS implemented API might throw. The first reason
is that some unforeseen condition occurred and the second is that a
specification requires an exception to be thrown.

When throwing for an unforeseen condition, the exception will be
reported to the console, and a sanitized NS_ERROR_UNEXPECTED exception
will be thrown to the calling content script, with the file/line of the
content code that invoked your API. This will avoid exposing chrome URIs
and other implementation details to the content code.

When throwing because a specification requires an exception, you need to
create the exception from the window your Web IDL object is associated
with (the one that was passed to your `init` method). The binding code
will then rethrow that exception to the web page. An example of how
this could work:

``` js
if (!isValid(passedInObject)) {
  throw new this.contentWindow.TypeError("Object is invalid");
}
```

or

``` js
if (!isValid(passedInObject)) {
  throw new this.contentWindow.DOMException("Object is invalid", "InvalidStateError");
}
```

depending on which exact exception the specification calls for throwing
in this situation.

In some cases you may need to perform operations whose exception message
you just want to propagate to the content caller. This can be done like
so:

``` js
try {
  someOperationThatCanThrow();
} catch (e) {
  throw new this.contentWindow.Error(e.message);
}
```

### Inheriting from interfaces implemented in C++

It's possible to have an interface implemented in JavaScript inherit
from an interface implemented in C++. To do so, simply have one
interface inherit from the other and the bindings code will
auto-generate a C++ object inheriting from the implementation of the
parent interface. The class implementing the parent interface will need
a constructor that takes an `nsPIDOMWindow*` (though it doesn't have
to do anything with that argument).

If the class implementing the parent interface is abstract and you want
to use a specific concrete class as the implementation to inherit from,
you will need to add a `defaultImpl` annotation to the descriptor for
the parent interface in `Bindings.conf`. The value of the annotation
is the C++ class to use as the parent for JS-implemented descendants; if
`defaultImpl` is not specified, the `nativeType` will be used.

For example, consider this interface that we wish to implement in
JavaScript:

``` webidl
[JSImplementation="some-contract"]
interface MyEventTarget : EventTarget {
  attribute EventHandler onmyevent;
  undefined dispatchTheEvent(); // Sends a "myevent" event to this EventTarget
}
```

The implementation would look something like this, ignoring most of the
XPCOM boilerplate:

``` js
function MyEventTargetImpl() {
}
MyEventTargetImpl.prototype = {
  // QI to nsIDOMGlobalPropertyInitializer so we get init() called on us.
  QueryInterface: ChromeUtils.generateQI(["nsIDOMGlobalPropertyInitializer"]),

  init: function(contentWindow) {
    this.contentWindow = contentWindow;
  },

  get onmyevent() {
    return this.__DOM_IMPL__.getEventHandler("onmyevent");
  },

  set onmyevent(handler) {
    this.__DOM_IMPL__.setEventHandler("onmyevent", handler);
  },

  dispatchTheEvent: function() {
    var event = new this.contentWindow.Event("myevent");
    this.__DOM_IMPL__.dispatchEvent(event);
  },
};
```

The implementation would automatically support the API exposed on
`EventTarget` (so, for example, `addEventListener`). Calling the
`dispatchTheEvent` method would cause dispatch of an event that
content script can see via listeners it has added.

Note that in this case the chrome implementation is relying on some
`[ChromeOnly]` methods on EventTarget that were added specifically to
make it possible to easily implement event handlers. Other cases can do
similar things as needed.

---

### Browser Components Pagedata Docs Index (`browser/components/pagedata/docs/index.md`)

# PageDataService

The page data service is responsible for collecting additional data about a page. This could include
information about the media on a page, product information, etc. When enabled it will automatically
try to find page data for pages that the user browses or it can be directed to asynchronously look
up the page data for a url.

The `PageDataService` is an EventEmitter and listeners can subscribe to its notifications via the
`on` and `once` methods.

The service can be enabled by setting `browser.pagedata.enabled` to true. Additional logging can be
enabled by setting `browser.pagedata.log` to true.

## PageData Data Structure

At a high level the page data service can collect many different kinds of data. When queried the
service will respond with a `PageData` structure which holds some general information about the
page, the time when the data was discovered and a map of the different types of data found. This map
will be empty if no specific data was found. The key of the map is from the
`PageDataSchema.DATA_TYPE` enumeration. The value is the JSON data which differs in structure
depending on the data type.

```
{
  "url": <url of the page as a string>,
  "date": <epoch based timestamp>,
  "siteName": <a friendly name for the website>,
  "image": <url for an image for the page as a string>,
  "data": <map of data types>,
}
```

## PageData Collection

Page data is gathered in one of two ways.

Page data is automatically gathered for webpages the user visits. This collection is trigged after
a short delay and then updated when necessary. Any data is cached in memory for a period of time.
When page data has been found a `page-data` event is emitted. The event's argument holds the
`PageData` structure. The `getCached` function can be used to access any cached data for a url.

## Supported Types of page data

The following types of page data (`PageDataSchema.DATA_TYPE`) are currently supported:

- `PRODUCT`
- `DOCUMENT`
- `ARTICLE`
- `AUDIO`
- `VIDEO`

---

### Devtools Docs Contributor Files README (`devtools/docs/contributor/files/README.md`)

# Directories Overview

This page provides a very top level overview of what is on each directory in the DevTools source code:

* `devtools/shared`: Code shared by both the client (front-end UI) and server. If we are using any third party libraries, or importing external repositories into our tree, those libraries generally live here (eg, `devtools/shared/jsbeautify`), assuming they are used by both client and server.
  * `devtools/shared/client`: Code for the [Remote Debugging Protocol](../backend/protocol.md) (RDP) client. You may wonder why this is not in `devtools/client` below: it's mainly because tests in server also need access to the RDP client.
  * `devtools/shared/locales`: Strings used in either the server only, or shared with both the client and server.
* `devtools/server`: Code for the [RDP](../backend/protocol.md) server and transport layer.
  * `devtools/server/actors`: [RDP Actors](../backend/protocol.md#actors). Note that if you're modifying actors, you may need to worry about [backwards compatibility](../backend/backward-compatibility.md) with older clients.
* `devtools/client`: Code for the front-end side of our tools. In theory, each directory corresponds to a panel, but this is not always the case. This directory is only shipped with desktop Firefox, as opposed to other directories above, which are shipped with all Gecko products (Firefox for Android, etc.)
  * `devtools/client/locales`: Strings used in the client front-end.
  * `devtools/client/themes`: CSS and images used in the client front-end.

---

### Devtools Docs Contributor Tests README (`devtools/docs/contributor/tests/README.md`)

# Automated tests

When working on a patch for DevTools, there's almost never a reason not to add a new test. If you are fixing a bug, you probably should write a new test to prevent this bug from occurring again. If you're implementing a new feature, you should write new tests to cover the aspects of this new feature.

Ask yourself:

* Are there enough tests for my patch?
* Are they the right types of tests?

We use three suites of tests:

* [`xpcshell`](xpcshell.md): Unit-test style of tests. No browser window, only a JavaScript shell. Mostly testing APIs directly.
* [Chrome mochitests](mochitest-chrome.md): Unit-test style of tests, but with a browser window. Mostly testing APIs that interact with the DOM.
* [DevTools mochitests](mochitest-devtools.md): Integration style of tests. Fires up a whole browser window with every test and you can test clicking on buttons, etc.

To run all DevTools tests, regardless of suite type:

```bash
./mach test devtools/*
```

Have a look at the child pages for more specific commands for running only a single suite or single test in a suite.

---

### Devtools Docs Contributor Tests Performance Tests Overview (`devtools/docs/contributor/tests/performance-tests-overview.md`)

# DevTools Performance Tests overview

This page provides a short overview of the various DevTools performance tests.

## damp

DAMP (short for DevTools At Maximum Performance) is the main DevTools performance test suite, based on the talos framework. It mostly runs end to end scenarios, opening the toolbox, various panels and interacting with the UI. It might regress for a wide variety of reasons: DevTools frontend changes, DevTools server changes, platform changes etc. To investigate DAMP regressions or improvements, it is usually necessary to analyze DAMP subtests individually.

See [DAMP Performance tests](performance-tests-damp.md) for more details on how to run DAMP, analyze results or add new tests.

## debugger-metrics

debugger-metrics measures the number of modules and the overall size of modules loaded when opening the Debugger in DevTools. This test is a mochitest which can be executed locally with:

```bash
./mach test devtools/client/framework/test/metrics/browser_metrics_debugger.js --headless
```

At the end of the test, logs should contain a `PERFHERDER_DATA` entry containing 4 measures. `debugger-modules` is the number of debugger-specific modules loaded, `debugger-chars` is the number of characters in said modules. `all-modules` is the number of modules loaded including shared modules, `all-chars` is the number of characters in said modules.

A significant regression or improvement to this test can indicate that modules are no longer lazy loaded, or a new part of the UI is now loaded upfront.

## inspector-metrics

See the description for debugger-metrics. This test is exactly the same but applied to the inspector panel. It can be executed locally with:

```bash
./mach test devtools/client/framework/test/metrics/browser_metrics_inspector.js --headless
```

## netmonitor-metrics

See the description for debugger-metrics. This test is exactly the same but applied to the netmonitor panel. It can be executed locally with:

```bash
./mach test devtools/client/framework/test/metrics/browser_metrics_netmonitor.js --headless
```

## webconsole-metrics

See the description for debugger-metrics. This test is exactly the same but applied to the webconsole panel. It can be executed locally with:

```bash
./mach test devtools/client/framework/test/metrics/browser_metrics_webconsole.js --headless
```

## server.pool

server.pool measures the performance of the DevTools `Pool` [class](https://searchfox.org/firefox-main/source/devtools/shared/protocol/Pool.js) which is intensively used by the DevTools server. This test is a mochitest which can be executed with:

```bash
./mach test devtools/client/framework/test/metrics/browser_metrics_pool.js --headless
```

At the end of the test, logs should contain a `PERFHERDER_DATA` entry which contain values corresponding to various APIs of the `Pool` class.

A regression or improvement in this test is most likely linked to a change in a file from devtools/shared/protocol.

## toolbox:parent-process

toolbox:parent-process measures the number of objects allocated by DevTools after opening and closing a DevTools toolbox. This test is a mochitest which can be executed with:

```bash
./mach test devtools/client/framework/test/allocations/browser_allocations_toolbox.js --headless
```

The test will record allocations while opening and closing the Toolbox several times. The `PERFHERDER_DATA` entry in the logs will contain 3 measures. objects-with-stacks is the number of allocated objects for which the allocation site is known and should be easy to fix for developers. You can refer to the [allocation tests documentation](https://searchfox.org/firefox-main/source/devtools/client/framework/test/allocations/docs/index.md) for a more detailed description of this test and how to use it to investigate and fix memory issues.

A regression here may indicate a leak, for instance a module which no longer cleans its dependencies. It can also indicate that DevTools is loading more singletons or other objects which are not tied to the lifecycle of the DevTools objects.

## target:parent-process

target:parent-process measures the number of objects created by DevTools to create a tab target. It does not involve DevTools frontend. This test is a mochitest which can be executed with:

```bash
./mach test devtools/client/framework/test/allocations/browser_allocations_target.js --headless
```

See the description for toolbox:parent-process for more information.

## reload:parent-process

target:parent-process measures the number of objects created by DevTools when reloading a page inspected by a DevTools Toolbox. This test is a mochitest which can be executed with:

```bash
./mach test devtools/client/framework/test/allocations/browser_allocations_reload.js --headless
```

See the description for toolbox:parent-process for more information. Note that this test also records another suite, reload:content-process.

## reload:content-process

See the description for reload:parent-process.

## browser-console:parent-process

browser-console:parent-process measures the number of objects created by DevTools when opening and closing the Browser Console. This test is a mochitest which can be executed with:

```bash
./mach test devtools/client/framework/test/allocations/browser_allocations_browser_console.js --headless
```

See the description for toolbox:parent-process for more information.

---

### Devtools Client Framework Test Allocations Docs Index (`devtools/client/framework/test/allocations/docs/index.md`)

# Allocation tests

The [allocations](https://searchfox.org/firefox-main/source/devtools/client/framework/test/allocations) folder contains special mochitests which are meant to record data about the memory usage of DevTools.
This uses Spidermonkey's Memory API implemented next to the debugger API.
For more info, see the following doc:
<https://searchfox.org/firefox-main/source/js/src/doc/Debugger/Debugger.Memory.md>

# Test example

```javascript
add_task(async function() {
  // Execute preliminary setup in order to be able to run your scenario
  // You would typicaly load modules, open a tab, a toolbox, ...
  ...

  // Run the test scenario first before recording in order to load all the
  // modules. Otherwise they get reported as "still allocated" objects,
  // whereas we do expect them to be kept in memory as they are loaded via
  // the main DevTools loader, which keeps the module loaded until the
  // shutdown of Firefox
  await testScript();

  // Pass alsoRecordContentProcess if you want to record the content process
  // of the current tab. Otherwise it will only record parent process objects.
  await startRecordingAllocations({ alsoRecordContentProcess: true });

  // Now, run the test script. This time, we record this run.
  await testScript(toolbox);

  // This will stop the record and also publish the results to Talos database
  // Second argument will be the name of the test displayed in Talos.
  // Many tests will be recorded, but all of them will be prefixed with this string.
  await stopRecordingAllocations("reload", { alsoRecordContentProcess: true });

  // Then, here you can execute cleanup.
  // You would typically close the tab, toolbox, ...
});
```

# How to run them locally

```bash
$ ./mach mochitest --headless devtools/client/framework/test/allocations/
```

And to only see the results:
```bash
$ ./mach mochitest --headless devtools/client/framework/test/allocations/ | grep " test leaked "
```

# Debug leaks

If you are seeing a regression or an improvement, only seeing the number of objects being leaked isn't super helpful.
The tests includes some special debug modes which are printing lots of data to figure out what is leaking and why.

You may run the test with the following env variable to turn debug mode on:
```bash
DEBUG_DEVTOOLS_ALLOCATIONS=leak|allocations $ ./mach mochitest --headless devtools/client/framework/test/allocations/the-fault-test.js
```

**DEBUG_DEVTOOLS_ALLOCATIONS** can enable two distinct debug output. (Only one can be enabled at a given time)

**DEBUG_DEVTOOLS_ALLOCATIONS=allocations** will report all allocation sites that have been made
while running your test. This will include allocations which has been freed.
This view is especially useful if you want to reduce allocations in order to reduce GC overload.

**DEBUG_DEVTOOLS_ALLOCATIONS=leak** will report only the allocations which are still allocated
at the end of your test. Sometimes it will only report allocations with missing stack trace.
Thus making the preview view helpful.

## Example

Let's assume we have the following code:

```javascript
 1:  exports.MyModule = {
 2:    globalArray: [],
 3:    test() {
 3:      // The following object will be allocated but not leaked,
 5:      // as we keep no reference to it anywhere
 6:      const transientObject = {};
 7:
 8:      // The following object will be allocated on this line,
 9:      // but leaked on the following one. By storing a reference
10:      // to it in the global array which is never cleared.
11:      const leakedObject = {};
12:      this.globalArray.push(leakedObject);
13:    },
14:  };
```

And that, we have a memory test doing this:

```javascript
  const { MyModule } = require("devtools/my-module");

  await startRecordingAllocations();

  MyModule.test();

  await stopRecordingAllocations("target");
```

We can first review all the allocations by running:

```bash
DEBUG_DEVTOOLS_ALLOCATIONS=allocations $ ./mach mochitest --headless devtools/client/framework/test/allocations/browser_allocation_myTest.js

```

which will print at the end:

```javascript
DEVTOOLS ALLOCATION: all allocations (which may be freed or are still allocated):
[
   {
     "src": "UNKNOWN",
     "count": 80,
     "lines": [
       "?: 80"
     ]
   },
   {
     "src": "resource://devtools/my-module.js",
     "count": 2,
     "lines": [
       "11: 1"
       "6: 1"
     ]
   }
]
```

The first part, with `UNKNOWN` can be ignored. This is about objects with missing allocation sites.
The second part of this logs tells us that 2 objects were allocated from my-module.js when running the test.
One has been allocated at line 6, it is `transcientObject`.
Another one has been allocated at line 11, it is `leakedObject`.

Now, we can use the second view to focus only on objects that have been kept allocated:

```bash
DEBUG_DEVTOOLS_ALLOCATIONS=leaks $ ./mach mochitest --headless devtools/client/framework/test/allocations/browser_allocation_myTest.js

```

which will print at the end:

```javascript
DEVTOOLS ALLOCATION: allocations which leaked:
[
   {
     "src": "UNKNOWN",
     "count": 80,
     "lines": [
       "?: 80"
     ]
   },
   {
     "src": "resource://devtools/shared/commands/commands-factory.js",
     "count": 1,
     "lines": [
       "11: 1"
     ]
   }
]
```

Similarly, we can focus only on the second part, which tells us that only one object is being leaked
and this object has been originally created from line 11, this is `leakedObject`.
This doesn't tell us why the object is being kept allocated, but at least we know which one is being kept in memory.


## Debug leaks via dominators

This last feature might be the most powerful and isn't bound to DEBUG_DEVTOOLS_ALLOCATIONS.
This is always enabled.
Also, it requires to know which particular object is being leaked and also require to hack
the codebase in order to pass a reference of the suspicious object to the test helper.

You can instruct the test helper to track a given object by doing this:

```javascript
 1: // Let's say it is some code running from "my-module.js"
 2:
 3: // From a DevTools CommonJS module:
 4: const { track } = require("devtools/shared/test-helpers/tracked-objects.sys.mjs");
 5: // From anything else, JSM, XPCOM module,...:
 6: const { track } = ChromeUtils.importESModule("resource://devtools/shared/test-helpers/tracked-objects.sys.mjs");
 7:
 8: const g = [];
 9: function someFunctionInDevToolsCalledBySomething() {
10:   const myLeakedObject = {};
11:   track(myLeakedObject);
12:
13:   // Simulate a leak by holding a reference to the object in a global `g` array
14:   g.push({ seeMyCustomAttributeHere: myLeakedObject });
15: }
```

Then, when running the test you will get such output:

```bash
 0:41.26 GECKO(644653)  # Tracing: Object@my-module:10
 0:40.65 GECKO(644653) ### Path(s) from root:
 0:41.26 GECKO(644653) - other@no-stack:undefined.WeakMap entry value
 0:41.26 GECKO(644653)  \--> LexicalEnvironment@base-loader.sys.mjs:160.**UNKNOWN SLOT 1**
 0:41.26 GECKO(644653)  \--> Object@base-loader.sys.mjs:155.g
 0:41.26 GECKO(644653)  \--> Array@my-module.js:8.objectElements[0]
 0:41.26 GECKO(644653)  \--> Object@my-module.js:14.seeMyCustomAttributeHere
 0:41.26 GECKO(644653)  \--> Object@my-module.js:10
```

This output means that `myLeakedObject` was originally allocated from my-module.js at line 10.
And is being held allocated because it is kept in an Object allocated from my-module.js at line 14.
This is our custom object we stored in `g` global Array.
This custom object it hold by the Array allocated at line 8 of my-module.js.
And this array is held allocated from an Object, itself allocated by base-loader.sys.mjs at line 155.
This is the global of the my-module.js's module, created by DevTools loader.
Then we see some more low level object up to another global object, which misses its allocation site.

# How to easily get data from try run

```bash
$ ./mach try fuzzy devtools/client/framework/test/allocations/ --query "'linux 'chrome-e10s 'opt '64-qr/opt"
```

You might also pass `--rebuild 3` if the test result is having some noise and you want more test runs.

# Following trends for these tests

You may try looking at:
<https://firefox-dev.tools/performance-dashboard/tools/memory.html>

Or at:
<https://treeherder.mozilla.org/perfherder/graphs?highlightAlerts=1&highlightChangelogData=1&series=autoland,3887143,1,12&series=mozilla-central,3887737,1,12&series=mozilla-central,3887740,1,12&series=mozilla-central,3887743,1,12&series=mozilla-central,3896204,1,12&timerange=2592000&zoom=1630504360002,1632239562424,0,123469.11111111111>

Link that you get from: <https://treeherder.mozilla.org/perfherder/graphs>
by looking at last year data for "DevTools" in the first dropdown,
and double clicking on the relevant line in "Tests" menulist.

Significant improvements and regressions will be notified through [the following dashboard](https://treeherder.mozilla.org/perfherder/alerts?hideDwnToInv=1&page=1&framework=12).

---

### Dom Webgpu Tests Cts Checkout Docs Intro README (`dom/webgpu/tests/cts/checkout/docs/intro/README.md`)

# Introduction

These documents contains guidelines for contributors to the WebGPU CTS (Conformance Test Suite)
on how to write effective tests, and on the testing philosophy to adopt.

The WebGPU CTS is arguably more important than the WebGPU specification itself, because
it is what forces implementation to be interoperable by checking they conform to the specification.
However writing a CTS is hard and requires a lot of effort to reach good coverage.

More than a collection of tests like regular end2end and unit tests for software artifacts, a CTS
needs to be exhaustive. Contrast for example the WebGL2 CTS with the ANGLE end2end tests: they
cover the same functionality (WebGL 2 / OpenGL ES 3) but are structured very differently:

- ANGLE's test suite has one or two tests per functionality to check it works correctly, plus
  regression tests and special tests to cover implementation details.
- WebGL2's CTS can have thousands of tests per API aspect to cover every combination of
  parameters (and global state) used by an operation.

Below are guidelines based on our collective experience with graphics API CTSes like WebGL's.
They are expected to evolve over time and have exceptions, but should give a general idea of what
to do.

## Contributing

Testing tasks are tracked in the [CTS project tracker](https://github.com/orgs/gpuweb/projects/3).
Go here if you're looking for tasks, or if you have a test idea that isn't already covered.

If contributing conformance tests, the directory you'll work in is [`src/webgpu/`](../src/webgpu/).
This directory is organized according to the goal of the test (API validation behavior vs
actual results) and its target (API entry points and spec areas, e.g. texture sampling).

The contents of a test file (`src/webgpu/**/*.spec.ts`) are twofold:

- Documentation ("test plans") on what tests do, how they do it, and what cases they cover.
  Some test plans are fully or partially unimplemented:
  they either contain "TODO" in a description or are `.unimplemented()`.
- Actual tests.

**Please read the following short documents before contributing.**

### 0. [Developing](developing.md)

- Reviewers should also read [Review Requirements](../reviews.md).

### 1. [Life of a Test Change](life_of.md)

### 2. [Adding or Editing Test Plans](plans.md)

### 3. [Implementing Tests](tests.md)

## [Additional Documentation](../)

## Examples

### Operation testing of vertex input id generation

This section provides an example of the planning process for a test.
It has not been refined into a set of final test plan descriptions.
(Note: this predates the actual implementation of these tests, so doesn't match the actual tests.)

Somewhere under the `api/operation` node are tests checking that running `GPURenderPipelines` on
the device using the `GPURenderEncoderBase.draw` family of functions works correctly. Render
pipelines are composed of several stages that are mostly independent so they can be split in
several parts such as `vertex_input`, `rasterization`, `blending`.

Vertex input itself has several parts that are mostly separate in hardware:

- generation of the vertex and instance indices to run for this draw
- fetching of vertex data from vertex buffers based on these indices
- conversion from the vertex attribute `GPUVertexFormat` to the datatype for the input variable
  in the shader

Each of these are tested separately and have cases for each combination of the variables that may
affect them. This means that `api/operation/render/vertex_input/id_generation` checks that the
correct operation is performed for the cartesian product of all the following dimensions:

- for encoding in a `GPURenderPassEncoder` or a `GPURenderBundleEncoder`
- whether the draw is direct or indirect
- whether the draw is indexed or not
- for various values of the `firstInstance` argument
- for various values of the `instanceCount` argument
- if the draw is not indexed:
    - for various values of the `firstVertex` argument
    - for various values of the `vertexCount` argument
- if the draw is indexed:
    - for each `GPUIndexFormat`
    - for various values of the indices in the index buffer including the primitive restart values
    - for various values for the `offset` argument to `setIndexBuffer`
    - for various values of the `firstIndex` argument
    - for various values of the `indexCount` argument
    - for various values of the `baseVertex` argument

"Various values" above mean several small values, including `0` and the second smallest valid
value to check for corner cases, as well as some large value.

An instance of the test sets up a `draw*` call based on the parameters, using point rendering and
a fragment shader that outputs to a storage buffer. After the draw the test checks the content of
the storage buffer to make sure all expected vertex shader invocation, and only these ones have
been generated.

---

### Index (`docs/index.rst`)

=================================
Firefox Source Tree Documentation
=================================

.. toctree::
   :caption: Overview
   :maxdepth: 2

   {overview_doc}

.. toctree::
   :caption: Getting Started
   :maxdepth: 1

   {setup_doc}

.. toctree::
   :caption: Working On Firefox
   :maxdepth: 2

   {contributing_doc}

.. toctree::
   :caption: Firefox User Guide
   :maxdepth: 2

   {user_guide}

.. toctree::
   :caption: Source Code Documentation
   :maxdepth: 2

   {source_doc}

.. toctree::
   :caption: The Firefox Build System
   :maxdepth: 1

   {build_doc}

.. toctree::
   :caption: Testing & Test Infrastructure
   :maxdepth: 1

   {testing_doc}

.. toctree::
   :caption: AI Agent Tools
   :maxdepth: 1

   {ai_agent_tools_doc}

.. toctree::
   :caption: Releases & Updates
   :maxdepth: 1

   {release_doc}

.. toctree::
   :caption: Localization & Internationalization
   :maxdepth: 2

   {l10n_doc}

.. toctree::
   :caption: Firefox and Python
   :maxdepth: 1

   {python_doc}

.. toctree::
   :caption: Metrics Collected in Firefox
   :maxdepth: 1

   {metrics_doc}


Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

---

### Accessible Docs Architecture (`accessible/docs/Architecture.md`)

# Architecture

This document provides a high-level overview of how the accessibility code is structured. See [the Document Accessibility Lifecycle page](DocumentAccessibilityLifecycle.md#docaccessible-creation) for a lower level description of the code.

## Process Model

The accessibility component spans multiple processes. In the parent process, it creates an accessibility tree of the Firefox UI and responds to requests from accessibility clients such as screen readers, magnifiers and voice control tools. In content processes, the accessibility component creates accessibility trees from web content.

To respond to accessibility client requests quickly, the accessibility tree from each content process is cached in the parent process.

## Accessibility Trees

Accessibility trees can carry different kinds of information: informally, there are "local trees" that represent a document in the current process and "remote trees" that mirror a local tree created in a separate process.

A local tree can only contain nodes in the current process, i.e. you can visit any node in the tab document and its in-process iframes. However, out-of-process iframes appear as a separate local tree in a different process.

A remote tree, on the other hand, unifies these trees: you can visit any node in the tab document and both its in-process and out-of-process iframes.

This means there are multiple accessibility trees for a single tab: one local tree in the content process, one local tree for each out-of-process iframe, and one remote tree in the parent process that mirrors these local trees. The Firefox UI is represented by a single local tree in the parent process.

An accessibility client communicates only with the parent process.
It sees the local tree for the Firefox UI and the remote trees for tabs and iframes as a single, unified tree.

### Tree Nodes

An accessibility tree is composed of nodes represented by the `Accessible` class and its subtypes. Below is an example local accessibility tree from [example.com](https://example.com), as printed by `a11y::logging::Tree` (unfortunately, without type information):



```
A11Y TREE: Initial subtree; 44:14.388
  {
    : 0x107077a00; role: document, name: 'Example Domain', idx: 0, node: 0x105f84800, #document
      : 0x105fb8b30; role: heading, name: 'Example Domain', idx: 0, node: 0x107b048b0, h1
        : 0x105fb8c90; role: text leaf, name: 'Example Domain', idx: 0, node: 0x107b05600, #text
      : 0x105fb8d40; role: paragraph, idx: 1, node: 0x107b04940, p
        : 0x105fb8df0; role: text leaf, name: 'This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.', idx: 0, node: 0x107b05700, #text
      : 0x105fb8ea0; role: paragraph, idx: 2, node: 0x107b049d0, p
        : 0x107922030; role: link, name: 'More information...', idx: 0, node: 0x107b030e0, a [ href="https://www.iana.org/domains/example" ]
          : 0x1079220e0; role: text leaf, name: 'More information...', idx: 0, node: 0x107b05800, #text
  }
```


Accessible has a direct subtype for different kinds of accessibility trees: `LocalAccessible` for nodes of local trees and `RemoteAccessible` for nodes of remote trees. For example, `LocalAccessible` can be used in content processes for web content and in the parent process for the Firefox UI. The descendants of these two types diverge.


LocalAccessible's direct descendant is `AccessibleWrap`. By convention, a class that ends in `Wrap` is a platform-specific implementation so `AccessibleWrap` contains the platform-specific implementations of `Accessible` and `LocalAccessible`. `AccessibleWrap's` direct and indirect subtypes are representations of HTML and XUL nodes such as `HTMLButtonAccessible` and `HTMLListBulletAccessible`. The Document and the root node of the accessibility tree are also represented by the `Accessible` class: `DocAccessible` and `DocAccessibleWrap` as well as `RootAccessible` and `RootAccessibleWrap` extend `AccessibleWrap`.


RemoteAccessible doesn’t have such an extensive type hierarchy. Its primary descendant is `DocAccessibleParent` which is the Document node of a remote tree located in the parent process: its local tree counterpart in a content process is `DocAccessible`.

Below is a graph that displays the same relationships described above. In the graph, solid lines represent direct descendants while dotted lines represent indirect descendants:

```{mermaid}
flowchart TD
accTitle: Graph of the class hierarchy described above
Accessible --> LocalAccessible[LocalAccessible: local tree] & RemoteAccessible[RemoteAccessible: remote tree]
LocalAccessible --> AccessibleWrap[AccessibleWrap: platform-specific implementation]
AccessibleWrap -.-> DocAccessible & HTMLButtonAccessible & HTMLListBulletAccessible
DocAccessible --> DocAccessibleWrap --> RootAccessible --> RootAccessibleWrap
RemoteAccessible -.-> DocAccessibleParent
```

### Platform-Specific Behavior

Accessibility trees differ by platform. The platform-independent tree, composed of types like `LocalAccessible` and `RemoteAccessible`, is marshalled into a platform-specific tree that makes it easier to implement the platform's accessibility API (or APIs). The platform tree is composed of the following node types:

- Windows: [MsaaAccessible], [ia2Accessible] and [uiaRawElmProvider]
- macOS: [mozAccessible]
- Linux: [ATKObjects and MaiAtkObjects](https://searchfox.org/mozilla-central/rev/d7d2cc647772de15c4c5aa47f74d25d0e379e404/accessible/atk/nsMai.h#87)

[MsaaAccessible]: https://searchfox.org/mozilla-central/rev/d7d2cc647772de15c4c5aa47f74d25d0e379e404/accessible/windows/msaa/MsaaAccessible.h
[ia2Accessible]: https://searchfox.org/mozilla-central/rev/d7d2cc647772de15c4c5aa47f74d25d0e379e404/accessible/windows/ia2/ia2Accessible.h#21
[uiaRawElmProvider]: https://searchfox.org/firefox-main/rev/dab03896ede1413be148884e054b311767bcf1a0/accessible/windows/uia/uiaRawElmProvider.h#34
[mozAccessible]: https://searchfox.org/mozilla-central/rev/d7d2cc647772de15c4c5aa47f74d25d0e379e404/accessible/mac/mozAccessible.mm

---

### Accessible Docs ColorsAndHighContrastMode (`accessible/docs/ColorsAndHighContrastMode.md`)

# Colors and High Contrast Mode

Firefox offers several customisations to improve the accessibility of colors used to render web content and Firefox chrome. This document describes the customisation options available and their behaviour across platforms. It also describes how these options interact with one another. It is intended for developer reference :)

## The Contrast Control Settings

In `about:preferences > Language and Appearance`, you'll find a subsection labeled "Contrast Control". The radio group in this section determines if high contrast mode (HCM) will be used. HCM can either be enabled on the platform level (OS HCM), or forced on in the browser (FF HCM)

The radio buttons alter `browser.display.document_color_use`. HCM can be enabled automatically with OS settings (OS HCM, `document_color_use=0`), it can be forced off (`document_color_use=1`), or forced on (FF HCM, `document_color_use=2`). When HCM is enabled, either automatically or explicitly, web content is rendered with a predetermined palette to give the user full control of the content's color contrast.
> Note: FF HCM only affects web content, so changing the option in this select will only alter color usage for web pages. It will not change FF chrome. Current behaviour on chrome pages (ie. `about:` pages) is undefined.

### User-customisable Colors Dialog

If the user has chosen to explicitly turn on Firefox HCM (`document_color_use=2`), they may customize the palette in a modal dialog. Users can choose to override background color, foreground color, visited link color, and/or unvisited link color by selecting a new color from the color inputs in the dialog. Modifications to these colors are stored in their corresponding user preference:

- `browser.background_color`
- `browser.foreground_color`
- `browser.visited_color`
- `browser.anchor_color`

## Color Usage and System Colors

Before we render any Firefox/web content, we need to select a color palette to render that content _with_. There are three different sets of colors we can use to style Firefox and/or web content:

- Stand-in colors
- System colors
- Colors-dialog colors

> Note: Web pages may supply their palette through style sheets. When FF HCM is set to "On", or set to "Use platform's contrast settings" and OS HCM is enabled, the chosen color palette is _forced_, meaning it cannot be overridden by web pages.

We decide which set of colors to use in `PreferenceSheet::Load`. If `resistFingerprinting` is enabled, we use stand-in colors. These colors are pre-defined constants and are not dynamically fetched from the operating system. Check out `nsXPLookAndFeel::GetStandinForNativeColor` for more information, as well as the constants themselves.

If we aren't using stand-in colors, we'll check the `browser.display.document_color_use` pref. If HCM is explicitly off (`1`), or automatically off (`0`), we will use the system colors as default text and link colors.

System colors are colors queried from the operating system. They help Firefox adapt to OS-level changes that aren't strictly HCM (ie. light/dark themeing). Because these colors are OS-dependent, a user operating Firefox on a Windows machine with system colors enabled will see Firefox differently than a user with system colors enabled on MacOS.

 So, how do we _get_ system colors? Our style system has a set of pre-defined `ColorID`'s in `ServoStyleConsts.h`, which are  mapped to platform-specific colors in  `widget/[cocoa | android | windows | gtk]/LookAndFeel.cpp`. Depending on the `ColorID` queried, we may do a dynamic fetch or simply return a constant. On MacOS, for example, `ColorID::TextForeground` and `ColorID::TextBackground` are hard-coded to return black and white respectively. `ColorID::Highlight`, on the other hand, queries the OS for `NSColor.selectedTextBackgroundColor`, which is set based on the accent color a user has selected in System Preferences.
 > Note: The colors we fetch here are theme-relative. If a user has set their OS to a dark theme, we'll fetch colors from that palette, and likewise for a light theme. Windows HCM, though not strictly a "theme", overrides the colors stored for Windows' light theme, leading to [some confusing code, like this](https://searchfox.org/mozilla-central/rev/b462b11e71b500e084f51e61fbd9e19ea0122c78/layout/style/PreferenceSheet.cpp#202-210).

Lastly, if we explicitly turn on HCM (`document_color_use=2`) AND we are _not_ styling Firefox chrome AND we are _not_ `resistFingerprinting`, we'll use colors-dialog colors to style web content.

By default, `browser.display.document_color_use` is set to `2` on Windows. If a user turns on the OS HCM Firefox will automatically go into HCM mode as well.
 > Note: This is intentional. Windows HCM is the most robust HCM offered among the operating systems we support, and so we cater to it here :)

Users on non-Windows platforms have HCM disabled by default (`document_color_use=1`). In order to enable Firefox HCM, they will either need to turn
it on explicitly (`document_color_use=2`), or set it to use the OS HCM mode and palette (`document_color_use=0`).

For a simplified flow chart of this decision tree, check out our [HCM Settings page](HCMSettings.html)

## High Contrast Mode

### Operating System High Contrast Mode (OS HCM)

Operating System HCM (or OS HCM) describes a high contrast customisation that is enabled outside of Firefox, in the settings of a user's operating system. Each of our major desktop operating systems has an OS HCM variant:

- Windows: Settings > Accessibility > Increase Contrast > (select theme) > Apply
- MacOS: System Preferences > Accessibility > Display > Increase Contrast
- Linux: Settings > Themes > High Contrast

The presence of an OS HCM is stored in `IntID::UseAccessibilityTheme`.

---

### Accessible Docs DocumentAccessibilityLifecycle (`accessible/docs/DocumentAccessibilityLifecycle.md`)

# Document Accessibility Lifecycle

## 1. DocAccessible creation

When a DocAccessible is created, it is initially empty.
A DocAccessible can be created in one of several ways:

### Scenario 1: Accessibility service is already started, layout fires an a11y notification for a new document

1. The layout [PresShell gets initialized (PresShell::Initialize)](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/layout/base/PresShell.cpp#1820).
2. As part of that, layout [inserts content from the root content object down](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/layout/base/PresShell.cpp#1885).
3. This [fires an accessibility insertion notification (nsAccessibilityService::ContentRangeInserted)](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/layout/base/nsCSSFrameConstructor.cpp#6863).
4. That [gets the DocAccessible (DocManager::GetDocAccessible)](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/accessible/base/nsAccessibilityService.cpp#463).
5. Because it doesn't exist yet, [the DocAccessible gets created (DocManager::CreateDocOrRootAccessible)](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/accessible/base/DocManager.cpp#62).

### Scenario 2: Accessibility service is already started, DOM loading completes for a new document

For top level content documents, if the accessibility service is started, layout should fire an a11y notification, resulting in scenario 1 above.
For child documents (e.g. in-process iframes), this might not happen because the container Accessible for the child document might not be created yet.
In that case, we can't create a DocAccessible when the layout notification is fired.
If the container Accessible is created when DOM loading completes for the child document, this scenario can occur.

1. [a11y::DocManager gets notified that the document has stopped loading (DocManager::OnStateChange)](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/accessible/base/DocManager.cpp#238).
2. It tries to get an existing DocAccessible, but it doesn't exist yet, so it [creates a DocAccessible (DocManager::CreateDocOrRootAccessible)](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/accessible/base/DocManager.cpp#395).

### Scenario 3: Accessibility service is already started, child document is reached while building accessibility tree for parent document

Child document here refers to a child document in the same process; i.e. an in-process iframe or a parent process document such as an about: page.
Note that scenario 1 or 2 could happen for a child document as well.

1. While building the accessibility tree for the parent document, an OuterDocAccessible is created (e.g. for a XUL browser or iframe).
2. The [OuterDocAccessible constructor gets the DocAccessible for the child document (DocManager::GetDocAccessible)](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/generic/OuterDocAccessible.cpp#56).
3. Because it doesn't exist yet, [the DocAccessible gets created (DocManager::CreateDocOrRootAccessible)](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/accessible/base/DocManager.cpp#62).

### Scenario 4: Accessibility service starts after top level document is loaded

1. When the accessibility service starts, it [initializes the ApplicationAccessible (ApplicationAccessible::Init)](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/base/nsAccessibilityService.cpp#1219).
2. As part of that, all documents are iterated.
3. For each top level document, [the DocAccessible is retrieved (DocManager::GetDocAccessible)](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/generic/ApplicationAccessible.cpp#130) and [thus created (DocManager::CreateDocOrRootAccessible)](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/accessible/base/DocManager.cpp#62).

Scenario 3 would then apply for any child documents encountered while building the accessibility trees for these top level DocAccessibles.

### Scenario 5: Document gets focus before layout begins

It is possible for a document to get focus before layout has begun and before DOM loading is complete.
In that case, there will be a PresShell, but it will have no root frame.
Despite this, it is necessary to create the document because otherwise, a11y focus would go nowhere while the document had DOM focus.

1. [a11y::FocusManager gets notified of a DOM focus change (FocusManager::NotifyOfDOMFocus)](https://searchfox.org/mozilla-central/rev/04dbb1a865894aec20eb02585aa75acccc0b72d5/accessible/base/FocusManager.cpp#126).
2. It gets the DocAccessible for the child document (DocManager::GetDocAccessible).
3. Because it doesn't exist yet, [the DocAccessible gets created (DocManager::CreateDocOrRootAccessible)](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/accessible/base/DocManager.cpp#62).

## 2. Initial tree creation

1. When a DocAccessible is created, it [creates a refresh observer (NotificationController)](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/generic/DocAccessible.cpp#368) which performs various processing asynchronously.
2. When the NotificationController is created, it [schedules processing for the next possible refresh tick](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/base/NotificationController.cpp#39).
3. Once a refresh tick occurs, [while there is not an interruptible reflow in progress](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/base/NotificationController.cpp#615) and there is an initialized PresShell, the DocAccessible's [initial update is triggered (DocAccessible::DoInitialUpdate)](https://searchfox.org/firefox-main/source/accessible/base/NotificationController.cpp#649).
4. For a top level document, the [DocAccessibleChild IPC actor is created](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/generic/DocAccessible.cpp#1752). See the section on IPC actor creation below.
5. The [DOM tree is walked and the accessibility tree is built for the document down (DocAccessible::CacheChildrenInSubtree)](https://searchfox.org/mozilla-central/rev/36f79bed679ad7ec46f7cd05868a8f6dc823e1be/accessible/generic/DocAccessible.cpp#1789).

Note that the document might still have no layout frame if the PresShell still has no frame; see scenario 5 in DocAccessible creation above.
Nevertheless, DoInitialUpdate must be called because otherwise, we wouldn't create the IPC actor, which would in turn mean remote documents in this state couldn't get a11y focus.

## 3. Child document binding

Child document here refers to a child document in the same process; e.g. an in-process iframe or a parent process document such as an about: page.

Child documents need to be a child of their OuterDocAccessible; e.g. the iframe.
However, the child document might be ready before the parent document is.
To deal with this:

1. When a DocAccessible is created for a child document (DocManager::CreateDocOrRootAccessible), it is [scheduled for binding to its parent (DocAccessible::BindChildDocument)](https://searchfox.org/mozilla-central/rev/1758450798ae14492ba28b695f48143840ad6c5b/accessible/base/DocManager.cpp#505).
2. NotificationController [does not handle any updates for child documents until they are bound to their parent](https://searchfox.org/mozilla-central/rev/1758450798ae14492ba28b695f48143840ad6c5b/accessible/base/NotificationController.cpp#638).
3. After the initial tree creation for the parent document, NotificationController [binds the document scheduled in 1)](https://searchfox.org/firefox-main/source/accessible/base/NotificationController.cpp#783).

## 4. IPC actor (DocAccessibleChild/Parent) creation

### Scenario 1: Top level document

1. As the first part of the DocAccessible's initial update (DocAccessible::DoInitialUpdate), if the document is a top level document, it [creates a DocAccessibleChild](https://searchfox.org/mozilla-central/rev/1758450798ae14492ba28b695f48143840ad6c5b/accessible/generic/DocAccessible.cpp#1757).
   - There is also a [code path to handle the case where the DocAccessibleChild has already been created](https://searchfox.org/firefox-main/source/accessible/generic/DocAccessible.cpp#1755). However, it doesn't seem like this should happen and code coverage information suggests that it doesn't.
2. It then [sends a message to the parent process to construct the DocAccessibleParent (BrowserChild::SendPDocAccessibleConstructor)](https://searchfox.org/firefox-main/source/accessible/generic/DocAccessible.cpp#1771).

### Scenario 2: Child document

The [DocAccessibleChild for a child document is created](https://searchfox.org/firefox-main/source/accessible/base/NotificationController.cpp#909) when the child document is bound to its parent by NotificationController.
There is also a [code path to handle the case where the DocAccessibleChild has already been created](https://searchfox.org/firefox-main/source/accessible/base/NotificationController.cpp#905).
However, it doesn't seem like this should happen and code coverage information suggests that it doesn't.

## 5. Document load events

### Scenario 1: DocAccessible is already created, DOM loading completes

1. [a11y::DocManager gets notified that the document has stopped loading (DocManager::OnStateChange)](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/accessible/base/DocManager.cpp#238).
2. It [notifies the DocAccessible (DocAccessible::NotifyOfLoad](https://searchfox.org/firefox-main/source/accessible/base/DocManager.cpp#399), passing EVENT_DOCUMENT_LOAD_COMPLETE.
3. That [sets the eDOMLoaded LoadState](https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/accessible/generic/DocAccessible-inl.h#93) and mLoadEventType on the DocAccessible.
4. Something schedules NotificationController processing. This could be the initial update, an insertion, etc.
5. Because the DocAccessible has been marked as loaded, the initial tree has been built and all child documents are loded, [NotificationController calls DocAccessible::ProcessLoad](https://searchfox.org/firefox-main/source/accessible/base/NotificationController.cpp#815).
6. ProcessLoad [fires the EVENT_DOCUMENT_LOAD_COMPLETE event](https://searchfox.org/firefox-main/source/accessible/generic/DocAccessible.cpp#1841) as set in 3).

### Scenario 2: DocAccessible is created some time after DOM loading completed

This can happen if the accessibility service is started late.
It can also happen if a DocAccessible couldn't be created earlier because the PresShell or containre Accessible wasn't created yet.

1. The [DocAccessible is initialized (DocAccessible::Init)](https://searchfox.org/mozilla-central/rev/8db61933e64b13c4a0ae456bcaccbd86a519ccc5/accessible/generic/DocAccessible.cpp#359).
2. It [detects that DOM loading is already complete](https://searchfox.org/mozilla-central/rev/8db61933e64b13c4a0ae456bcaccbd86a519ccc5/accessible/generic/DocAccessible.cpp#379).
3. In response, it [sets the eDOMLoaded state and mLoadEventType on the DocAccessible](https://searchfox.org/mozilla-central/rev/8db61933e64b13c4a0ae456bcaccbd86a519ccc5/accessible/generic/DocAccessible.cpp#381).
4. Something schedules NotificationController processing. This could be the initial update, an insertion, etc.
5. Because the DocAccessible has been marked as loaded, the initial tree has been built and all child documents are loded, [NotificationController calls DocAccessible::ProcessLoad](https://searchfox.org/firefox-main/source/accessible/base/NotificationController.cpp#815).
6. ProcessLoad [fires the EVENT_DOCUMENT_LOAD_COMPLETE event](https://searchfox.org/firefox-main/source/accessible/generic/DocAccessible.cpp#1841) as set in 3).

### Suppression of document load events for parent process iframes

Note that for documents loaded directly in the parent process, ProcessLoad won't fire a load event for a child document whose parent is still loading.
This is old behavior which does not work in the content process and will probably be removed in future.
See [bug 1700362](https://bugzilla.mozilla.org/show_bug.cgi?id=1700362).

---

### Accessible Docs GeckoViewThreadTopography (`accessible/docs/GeckoViewThreadTopography.md`)

# GeckoView Thread Topography

Unlike conventional Gecko, GeckoView utilizes two main threads in the parent process. A thread called the "UI" thread that runs the native Java event loop, and a "Gecko" thread that spawns an instance of Gecko. Note, this "Gecko" thread is considered the main thread in conventional Gecko and throughout the source is referred to as such. For example `NS_IsMainThread()` returns `true` when called on the Gecko thread.

Android's accessibility API's entry point is the UI thread. The most common methods for an accessibility service to query and interact with Gecko have a return value and thus must be performed synchronously. For example [performAction()](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeProvider#performAction(int,%20int,%20android.os.Bundle)) and [createAccessibilityNodeInfo()](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeProvider#createAccessibilityNodeInfo(int)).

## Thread Safety Concerns

As a rule, every data structure and method in Gecko should be considered unsafe to access from GeckoView's UI thread. For example the default reference counting implementation is not thread safe and should not be used outside the Gecko thread. Cross-process messaging must be done from the Gecko thread as well.

Since the accessibility consumer is in the UI thread we need to either call into the Gecko thread while blocking the UI thread, or make a limited subset of the accessibility API thread safe. We employ both methods for different types of content.

## In-Process Content

Content that is rendered in the top-level process is rare and mostly consists of "about" pages that give insight to browser internals, like `about:support`.

Since our Gecko accessibility API queries DOM and Layout, and includes many complex, thread-unsafe data structures, we call into the Gecko thread to retrieve what is needed and block the UI until we get a response from the Gecko thread. For example, to retrieve a "class name" enum that is calculated for a certain accessible the method will look something like this:

```cpp
int SessionAccessibility::GetNodeClassName(int32_t aID) {
  int32_t classNameEnum = java::SessionAccessibility::CLASSNAME_VIEW;
  RefPtr<SessionAccessibility> self(this);
  nsAppShell::SyncRunEvent([this, self, aID, &classNameEnum] {
    if (Accessible* acc = GetAccessibleByID(aID)) {
      classNameEnum = AccessibleWrap::AndroidClass(acc);
    }
  });

  return classNameEnum;
}
```

## Out-of-Process Content

Most web content will be rendered in a child process. Historically, we would cache the accessible tree hierarchy and object roles in the parent process and use synchronous IPC to query individual objects for more properties. We are transitioning to a fully cached approach where all fields are either stored or calculated in remote proxy objects in the parent process.

The "cache" in our definition is any data member associated with the remote `Accessible` or its subclasses, such as `mParent`, `mChildren` and `mCachedFields` in `RemoteAccessibleBase`, or `mAccessibles` in `DocAccessibleParent`. In addition to all those members the cache includes the accessible/id table in `SessionAccessibility`.

The cache is initialized and modified exclusively by messages from the child process to the parent process. Since the cache is limited to our module and is relatively well scoped, it is possible to synchronize access to it and allow it to be consumed by the UI thread.

### Global Accessibility Thread Monitor

We have global thread monitor that can be acquired by calling `nsAccessibilityService::GetAndroidMonitor()`. For example, if we were to retrieve the class name enum we would use an RAII wrapped monitor to exclusively access the cache:

```cpp
int SessionAccessibility::GetNodeClassName(int32_t aID) {
  MonitorAutoLock mal(nsAccessibilityService::GetAndroidMonitor());
  if (Accessible* acc = GetAccessibleByID(aID)) {
    return AccessibleWrap::AndroidClass(acc);
  }
}
```

#### Gecko Thread Access

As a rule, all incoming IPC messages (ie. all `DocAccessibleParent::Recv` methods) should hold the global monitor. This is because any `Recv` method may indirectly modify the cache, for example a certain event might invalidate or update a cached property. There are currently no deferred tasks that happen as a result of a `Recv` method, so holding the monitor at the start of these methods will assure that the cache is being read or written in a synchronized fashion.

#### UI Thread Access

All methods that are called in via JNI should be assumed are in the UI thread and should acquire the monitor, unless the are annotated with `@WrapForJNI(dispatchTo = "gecko")`. This assures us that they are synchronized with any potential modifications to the cache happening in the Gecko thread.

---

### Accessible Docs GuidelinesForNewContributors (`accessible/docs/GuidelinesForNewContributors.md`)

# Guidelines for New Contributors

Thank you for your interest in contributing to the Gecko accessibility module.
This document provides some brief, high level guidelines to get you started.

## Local and Remote Accessibility Trees

Accessibility clients communicate with Gecko's parent process, but web content is isolated in its own content processes.
Therefore, in order for accessibility clients to access web content, the accessibility tree from each content process is cached in the parent process.
See the [Architecture](Architecture.md) page for more details.

This means that when writing patches to change what is exposed to accessibility clients, you need to ensure that:

1. The data is included in the cache sent to the parent process.
   This might already be the case if you are modifying an existing property, but it most likely won't be if you are adding something new.
   The cache is built in [`LocalAccessible::BundleFieldsForCache`](https://searchfox.org/firefox-main/rev/dab03896ede1413be148884e054b311767bcf1a0/accessible/generic/LocalAccessible.cpp#3538).
2. An event is fired when the data is changed, if appropriate.
   This is necessary both to update the parent process cache and to notify clients of the change.
   However, not all properties have associated events.
   See [the `EVENT_*` constants in nsIAccessibleEvent](https://searchfox.org/firefox-main/rev/dab03896ede1413be148884e054b311767bcf1a0/accessible/interfaces/nsIAccessibleEvent.idl#31) for the supported events.
3. A cache update is queued when the data is changed, if there is no associated event.
   See [`DocAccessible::QueueCacheUpdate`](https://searchfox.org/firefox-main/rev/dab03896ede1413be148884e054b311767bcf1a0/accessible/generic/DocAccessible.h#114).
4. The data can be queried via both `LocalAccessible` and `RemoteAccessible` methods.

## Tests

Ideally, any change to code in this module should be covered by automated tests.

To run a test directory or file, use the command:

`./mach test accessible/tests/path`

### Browser Tests

Browser tests are located in `accessible/tests/browser`.
This is our preferred test suite, as it supports testing across multiple processes, is supported by our linters, allows for OS specific testing, etc.
Any new tests should be added to this test suite, in the folder which best approximates their behavior.
The one exception is changes related to XUL, as XUL can only run in the parent process.

Test tasks are defined using [`addAccessibleTask`](https://searchfox.org/firefox-main/rev/ad5f057320ecc6b934dfa1e3ec361f87712806cc/accessible/tests/browser/shared-head.js#694).
`addAccessibleTask` can be given a markup snippet (normally HTML) to load.
You also pass it an async test function, which should be named to make debugging easier, though many older tests have unnamed functions.
The same test can then optionally be run in a top level remote document (`{ topLevel: true }`), in the parent process (`{ chrome: true }`), in a remote in-process iframe (`{ iframe: true }`) and an out-of-process iframe (`{ remoteIframe: true }`).
This makes it easy to test both `LocalAccessible` and `RemoteAccessible` using the same code.

Tests in `accessible/tests/browser/atk` and `accessible/tests/browser/windows` exercise OS specific APIs.
Like all browser tests, they are primarily written in JS, but the `runPython` function is used to execute snippets of Python code in a separate process, simulating a real accessibility client.
ATK tests use the pyatspi library to make AT-SPI calls.
Windows tests use the Python ctypes and comtypes libraries to make MSAA, IAccessible2 and UI Automation calls.

Tests in `accessible/tests/browser/telemetry` and `accessible/tests/browser/performance` are non-standard.
Please do not use them as examples for general test writing.
If you believe your work requires a telemetry or performance test, please reach out to :morgan on matrix or bugzilla.

### Mochitests

Mochitests are located in `accessible/tests/mochitest`.
This is an older, legacy test suite which only supports testing `LocalAccessible` in a single process.
However, because of the massive number of tests here, many have not yet been ported to browser tests.
Mochitests are also necessary for testing XUL accessibility.
New tests should not be added in this directory except for those related to XUL.
However, any failures introduced in these tests must still be fixed.

### Crash Tests

There is another suite of tests located in `accessible/tests/crashtests`.
However, this test suite is unreliable and thus legacy.
Because the accessibility module runs asynchronously from DOM, it is difficult to guarantee that any potential crash is hit before the test exits.
New tests should not be added in this directory.

To verify a crash fix, you should instead write a browser test as outlined above.
`addAccessibleTask` explicitly waits until the document's accessibility tree has been built before running the test function.
If the crash was caused by a change to the accessibility tree, you can also wait for a specific accessibility event (or events) to ensure the change has been processed by the accessibility code before the test exits.

---

### Accessible Docs HCMCSSChecklist (`accessible/docs/HCMCSSChecklist.md`)

# HCM CSS Self-Check Guide

Use these checks when writing or reviewing CSS that targets high contrast mode (HCM) or Increase Contrast (IC) users.

For background on the media queries and colour systems referenced here, see the documentation on [HCM Media Queries](HCMMediaQueries.md) and [Colors and High Contrast Mode](ColorsAndHighContrastMode.md). You should read and understand these documents before moving forward with the checks below.

Note: These checks are ordered intentionally, please complete them in order.

---

## Architecture

### Check 1: Have I identified all places where HCM overrides are necessary?

**When writing HCM-specific CSS, our goal is to write as little CSS as possible.** Our design system is a huge help here. The design system token layer system (`toolkit/themes/shared/design-system/dist/tokens-shared.css`) includes three cascade layers — `tokens-foundation`, `tokens-prefers-contrast`, and `tokens-forced-colors` — that automatically override token values in contrast modes. Any variable whose value is (or cascades to) a design system token gets HCM adaptation for free.

In addition to the `.css` files above, you can view the [design system tokens table here](https://firefoxux.github.io/firefox-desktop-components/?path=/story/docs-tokens-table--default). Make sure to select "Chrome" or "Content" as is appropriate for your work.

**Variables that use design system tokens generally do NOT need explicit `forced-colors` overrides.** For example:

```css
/* These adapt automatically in HCM — no override needed */
color: var(--button-text-color);               /* → ButtonText in forced-colors */
background: var(--button-background-color);    /* → ButtonFace in forced-colors */
border-color: var(--button-border-color);      /* → ButtonText in forced-colors */
```

**Variables with raw custom values DO need explicit `forced-colors` overrides.** These are those holding hardcoded hex colors, `light-dark()` calls, `rgba()` values, gradients, or references to brand palette tokens (like `--color-violet-80`) which do not resolve to system colors.

```css
/* These do NOT adapt — explicit forced-colors overrides required */
--my-bg: light-dark(var(--color-gray-0), var(--color-gray-80));
--my-accent: var(--color-violet-90);
--my-gradient: linear-gradient(83deg, #5119dc 0.73%, var(--color-violet-30) 98.05%);
--my-hover-bg: rgba(191, 143, 204, 0.2);
```

**Audit step:** Scan all CSS custom properties in your `:root` / `:host` block. For each one, ask: does this value ultimately resolve to a [CSS system color keyword](https://www.w3.org/TR/css-color-4/#css-system-colors) in `tokens-forced-colors`? If yes, verify the token is appropriate (other checks below still apply). If no, it needs an override. Note that only the keywords listed in the spec are valid system colors — values like `inherit`, named colors like `teal`, or `transparent` are not CSS system colors and will not adapt correctly in HCM. If your component uses no design system tokens at all, pay particularly close attention to ensuring every color property has an explicit override.

---

### Check 2: Am I using the right media query for the right audience?

`forced-colors` and `prefers-contrast` are not interchangeable. You can read more about their differences, with examples, in our [HCM Media Query documentation](HCMMediaQueries.md).

| Query | Fires for |
|---|---|
| `forced-colors: active` | Windows HCM, Firefox HCM |
| `prefers-contrast: more` | macOS Increase Contrast **and** most `forced-colors` users (contrast ratio > 7:1) |

**It is important to note:**: most HCM users also trigger `prefers-contrast`. A bare `@media (prefers-contrast)` block applies to *both* IC and HCM users. If that is not your intent, you must use a more specific media query.

macOS "Increase Contrast" and Linux HCM alone do **not** trigger `forced-colors`.

When a component needs distinct treatment for IC and HCM users, the recommended split is:

```css
:root {
  @media (prefers-contrast) {
    /* Applies to ALL contrast users (IC + HCM).
       Safe to use here: borders, border-width increases.
       Do NOT use CSS system color keywords here — IC users keep the
       default Firefox color scheme. */
  }

  @media (prefers-contrast) and (not (forced-colors)) {
    /* IC users only.
       Keep original colors. You may optionally improve a foreground
       color for readability here, but only using non-system colors. */
  }

  @media (forced-colors) {
    /* HCM users only.
       Design system tokens that resolve to CSS system colors are
       required here. Do not use system color keywords directly. */
  }
}
```
A rule that belongs in both IC and HCM (e.g. removing child outlines from a button with both an icon and a label so only the button wrapper shows a focus ring) should use bare `@media (prefers-contrast)` without the `not (forced-colors)` exclusion.

**IC-specific color improvements:** IC users on macOS keep the default Firefox color scheme and should not receive a reduced-palette experience. If a foreground color modification on a control could meaningfully improve contrast for IC users, it can go in the `prefers-contrast and (not (forced-colors))` block — but only using non-system color tokens. There are currently no design system tokens specifically for IC color improvements beyond borders.

If you are uncertain which media query applies to your use case, reach out to the accessibility team in #Accessibility for guidance.

---

### Check 3: Am I overriding tokens in the correct places?

Two main rules govern how HCM overrides should be written:

**Nest media queries inside `:root` / `:host`, not on specific elements.** Do not create a separate top-level `@media` rule wrapping a new `:root` declaration. Nesting inside the existing block keeps all variable definitions for a component in one place and makes the full cascade visible at a glance.

```css
/* WRONG — separate top-level @media rule instead of nesting inside :root */
:root {
  --my-wrong-text-color: rgb(123, 123, 123);
}

@media (forced-colors) {
  :root {
    --my-wrong-text-color: var(--text-color-design-system-token);
  }
}

/* WRONG — @media nested at element level instead of in :root */
.myWrongClass {
  color: var(--my-wrong-text-color);
  @media (forced-colors) {
    color: var(--text-color-design-system-token);
  }
}

/* CORRECT */
:root {
  --my-bg: #ffffff;
  --my-text-color: rgb(123, 123, 123);

  @media (forced-colors) {
    --my-bg: var(--background-design-system-token);
    --my-text-color: var(--text-color-design-system-token);
  }
}

.myClass {
  background-color: var(--my-bg);
  color: var(--my-text-color);
}
```

**Override the existing variable; do not introduce new HCM-specific ones.** Do not create `-hcm-`-suffixed variables or other HCM-specific names. Overriding the existing variable means the element rule can stay simple and clean.

```css
/* WRONG — introduces an HCM-specific variable; --my-btn-text-color still resolves to the
   light-dark() value in forced-colors, so the element must also carry its own override */
:root {
  --my-wrong-btn-text-color: light-dark(var(--color-violet-80), var(--color-white));

  @media (forced-colors) {
    --my-wrong-btn-hcm-text-color: var(--button-text-color);
  }
}
.myWrongBtn {
  color: var(--my-wrong-btn-text-color); /* still unresolved in forced-colors */

  @media (forced-colors) {
    color: var(--my-wrong-btn-HCM-text-color); /* element-level override now required */
  }
}

/* CORRECT — element-level CSS is unchanged; HCM is handled entirely at :root */
:root {
  --my-btn-text-color: light-dark(var(--color-violet-80), var(--color-white));

  @media (forced-colors) {
    --my-btn-text-color: var(--button-text-color);
  }
}
.myBtn {
  color: var(--my-btn-text-color);
}
```

---

## Token Selection

These checks apply when you're writing `forced-colors` overrides. They ensure you pick tokens that are correct, consistent, and safe across all HCM themes.

---

### Check 4: Are my foreground/background pairs correct, and am I mapping them semantically?

When choosing tokens for an element in HCM, identify the semantic role of the element (interactive control, selected item, static page content, link text, disabled content), find the appropriate token family in the [tokens table](https://firefoxux.github.io/firefox-desktop-components/?path=/story/docs-tokens-table--default), then use that family consistently across background, text, and border. Do not mix component-specific tokens with generic ones, or tokens from unrelated components.


```css
/* WRONG — mixing component families */
--my-wrong-bg: var(--button-background-color-primary);
--my-wrong-text: var(--text-color); /* generic, not button family */
--my-wrong-border var(--border-color-interactive); /* evaluates to a button color, but a better match exists */

/* WRONG — mixing component family types (button general, primary button, ghost button) */
--my-wrong-bg: var(--button-background-color);
--my-wrong-text: var(--button-text-color-primary);
--my-wrong-border: var(--button-border-color-ghost);

/* CORRECT — same family throughout */
--my-bg: var(--button-background-color-primary);
--my-text: var(--button-text-color-primary);
--my-border: var(--button-border-color-primary);
```


**Token families inside our design system tokens set have already been audited for HCM compliance**. By sticking with one family, you're guaranteed to avoid pair mismatches.

#### What is a pair mismatch?

CSS system colors come in guaranteed-contrast pairs. Contrast is only guaranteed *within* a pair. Mixing a foreground from one pair with a background from another removes that guarantee and can produce unreadable combinations on some themes.

Do not use CSS system color keywords directly. Use design system tokens — they resolve to the correct system colors through the `tokens-forced-colors` layer. Consult the [Firefox design system tokens table](https://firefoxux.github.io/firefox-desktop-components/?path=/story/docs-tokens-table--default) to identify which tokens are available and what they resolve to in forced-colors mode.

---

### Check 5: Are my tokens semantically appropriate for the property they set?

A token named `background-color` should only be used to set backgrounds. A token named `text-color` should only be used for text (foreground). Do not use a background token to set a text color variable, even if it happens to resolve to the right system color in a specific theme.

```css
/* WRONG — background token used to set text color */
--my-wrong-btn-text: var(--button-background-color-primary);
/* In HCM this resolves to ButtonText via --color-accent-primary,
   but the token name says "background" and the usage says "text" */

/* CORRECT */
--my-btn-text: var(--button-text-color-primary);
/* This also resolves to ButtonText, and the token name is
   appropriate and consistent */
```

Beyond property type, also verify that the token's component matches your use case. When multiple tokens resolve to the same CSS system color, they are not interchangeable — prefer the one whose name most accurately describes the element being styled. A token that resolves correctly but names the wrong component is still a semantic mismatch, and makes the code harder to audit in future.

```css
/* WRONG — despite being a background token, this token describes a list item;
   it is not appropriate for a button background */
--my-wrong-button-background: var(--background-color-list-item);

/* CORRECT */
--my-button-background: var(--button-background-color);
```

If no token exists whose name is a good semantic match for your use case, that is worth noting — it may indicate the design system doesn't yet cover your component. Please reach out to the accessibility team directly in #Accessibility for guidance.

---

### Check 6: Are my tokens from matching interaction states?

Background, text, and border tokens for a given state (hover, active, focus, selected, current, etc.) must all carry the same state suffix. Mixing states produces pairs that may be unreadable on some HCM themes — hover backgrounds and default-state text colors can resolve to the same system color, making content invisible.

```css
/* WRONG — hover-state background paired with default-state text */
--my-btn-bg: var(--button-background-color-hover); /* hover state */
--my-wrong-btn-text: var(--button-text-color); /* default state ← mismatch */

/* CORRECT — both hover state */
--my-btn-bg: var(--button-background-color-hover);
--my-btn-text: var(--button-text-color-hover);
```

---

### Check 7: Does any information rely on color alone to communicate meaning?

HCM reduces the available palette to a small set of system colors. If any information in the component is conveyed by color alone, it will be lost in HCM. This is also a violation of our general a11y guidelines and [WCAG](https://www.w3.org/TR/WCAG22/#use-of-color). Check that:

- **Selected states remain visually distinct** from unselected states, even when both use system colors. A selected item should use the selection token pair rather than only differing from its neighbor by hue or opacity.
- **Disabled/inactive states remain distinct** from enabled states. Use disabled tokens (ex. `--button-text-color-disabled`) for disabled foreground rather than relying on reduced opacity.
- **Status or severity** (e.g. error, warning, success) is not indicated only by color. If an icon or label is the only indicator, ensure it is present and its text/icon uses an appropriate foreground token.

```css
/* WRONG — selected state differs from default only by color,
   which may become indistinguishable across HCM themes */
:root {
  @media (forced-colors) {
    --my-wrong-item-text: var(--button-text-color);
    --my-wrong-item-bg: var(--button-background-color);
    --my-wrong-item-bg-selected: var(--button-background-color); /* ← no distinction */
    /* no selected foreground color specified */
  }
}

/* CORRECT — selected state uses the dedicated selection token pair */
:root {
  @media (forced-colors) {
    --my-item-text: var(--button-text-color);
    --my-item-bg: var(--button-background-color);
    --my-item-bg-selected: var(--color-accent-primary-selected);
    --my-item-text-selected: var(--text-color-accent-primary-selected);
  }
}
```

---

### Check 8: Have I verified that my chosen tokens actually have `forced-colors` variants?

Not every design system token has an entry in the `tokens-forced-colors` layer. A token without a forced-colors override resolves to its foundation or `tokens-prefers-contrast` value in HCM, which may be a non-system color.

Before using a token in a `forced-colors` block, look it up in the [Firefox design system tokens table](https://firefoxux.github.io/firefox-desktop-components/?path=/story/docs-tokens-table--default). Ensure your chosen token has an entry in the High Contrast Mode column. If it does not, reach out to the accessibility team in #Accessibility for guidance.

In addition, you should build and test your patch on Windows when possible.
Testing chrome patches in Firefox using FF HCM will not produce the same results as testing on Windows with Windows HCM enabled. Please read about the differences between FF HCM and Windows HCM in the [Colors and High Contrast Mode in Firefox](ColorsAndHighContrastMode.md) documentation.



---

### Check 9: Do ghost components have appropriate tokens set in HCM?

The design system's `--button-*-ghost-*` tokens already have `forced-colors` overrides that add a visible border in the default state (ghost buttons are borderless by default) and override hover and active states. If a component uses ghost styling in non-HCM, do not override the ghost tokens to non-ghost values in the `forced-colors` block — that creates a state mismatch between modes. Let the ghost tokens cascade naturally through the design system. If you've chosen custom color values for your ghost component, override those styles with ghost tokens in HCM.

```css
/* WRONG — non-HCM uses ghost state, forced-colors switches to default state */
:host {
  --my-wrong-ghost-btn-bg: var(--button-background-color-ghost);

  @media (forced-colors) {
    --my-wrong-ghost-btn-bg: var(--button-background-color); /* ← this will remove the ghost stylinlg, causing a state mismatch */
  }
}

/* CORRECT */
:host {
  --my-ghost-btn-bg: var(--button-background-color-ghost);
}

/* ALSO CORRECT */
:host {
  --my-ghost-btn-bg: color-mix(in srgb, --button-background-color, #fff, 20%);

  @media (forced-colors) {
    --my-ghost-btn-bg: var(--button-background-color-ghost);
  }
}
```

---

## Elements and Features

These checks address specific UI elements and CSS features that require particular handling in contrast modes.

---

### Check 10: Am I adding borders to all elements that require them, for all contrast users?

Controls, sidebars, toolbars, dialogs, cards, and sections require a solid border of at least 1px in contrast modes. Borders provide visual separation where color alone is insufficient, and are important for both IC and HCM users. Ensure adequate padding around the border so it does not reduce legibility of the content inside.

In HCM, border tokens are supplied by our design system for most token family types and states. In Increase Contrast (IC), border color should match the component's foreground color (often with `currentColor`).

If the same border is appropriate for both IC and HCM, set it in a bare `@media (prefers-contrast)` block. The `forced-colors` block's value will override it for HCM users due to source order:

```css
:root {
  --my-item-border-width: 0px;
  --my-item-border-color: transparent;

  @media (prefers-contrast) {
    /* 1px solid border using the component's foreground color, for all contrast users */
    --my-item-border-width: var(--border-width);
    --my-item-border-color: currentColor;
  }

  @media (forced-colors) {
    /* Override to use the token matching the component family */
    /* Keep the border width token above, as it is appropriate for both modes */
    --my-item-border-color: var(--button-border-color);
  }
}

.my-element {
  border: var(--my-item-border-width) solid var(--my-item-border-color);
  padding: var(--space-small);
}
```


---

### Check 11: Have I removed or replaced visual effects that don't belong in HCM?

Blur effects, drop shadows, semi-opaque surfaces, and gradient backgrounds must be removed or replaced with solid equivalents in HCM. These effects rely on color blending that is meaningless or visually broken against a forced system-color palette.

| Effect | HCM replacement |
|---|---|
| Drop shadow | 1px solid border using the component's foreground color token |
| Gradient background | Solid background using the appropriate `background-color` token |
| Semi-opaque surface | Solid background (`var(--background-color-box)`) with `opacity:1;`|
| Blur | Remove entirely |

```css
:root {
  --my-shadow: drop-shadow(-16px -16px red);
  --my-gradient: linear-gradient(135deg, var(--color-violet-50), var(--color-blue-50));
  --my-overlay-bg: rgba(0, 0, 0, 0.5);
  --my-border-width: 0px;
  --my-custom-opacity: 0.1;

  @media (forced-colors) {
    --my-shadow: none;
    --my-gradient: none;
    --my-overlay-bg: var(--background-color-canvas);
    --my-border-width: var(--border-width); /* border replaces shadow */
    --my-custom-opacity: 1;
  }
}
```

---

### Check 12: Have I handled SVG colors correctly for HCM?

SVGs fall into two categories with different HCM requirements:

**Decorative SVGs**, or SVGs that duplicate information already available in an accessible format (e.g. a triangle icon next to a text label starting with "Warning"). These SVGs may use colors outside the HCM palette. No override is needed.

**Informational or interactive SVGs** — those that uniquely communicate information or function as controls — must use only HCM palette colors. An example of an SVG in this category is the down-chevron on a custom accordian element.
Generally, button tokens are appropriate when these items are interactive and traditional background/text tokens are appropriate when they are static. These components should also gain borders in HCM.

```css
/* Interactive icon SVG — must adapt in HCM */
:root {
  --my-chevron-fill: var(--color-violet-60);
  --my-chevron-stroke: var(--color-violet-80);

  @media (forced-colors) {
    --my-chevron-fill: var(--button-background-color);
    --my-chevron-stroke: var(--button-border-color);
  }
}
```

---

### Accessible Docs HCMMediaQueries (`accessible/docs/HCMMediaQueries.md`)

# High Contrast Mode (HCM) Media Queries

Firefox supports both the `prefers-contrast` and `forced-colors` media queries. These queries detect a user's display settings (in the browser and/or in their OS), and allow authors to adjust content styling accordingly. These queries are not interchangeable, and we should be intentional about using one or the other (or both!) when designing for accessibility.

## What activates these queries?

### Forced Colors

The `forced-colors` media query has two values: `active` and `none`. The resolved value of this media query is determined by the browser based on user settings (OS and Firefox).

* The `none` state indicates documents can use any colors to render content.
* The `active` state indicates a user has OS or browser settings that limit the color palette available to the User Agent.

In Firefox's default configuration, the `active` state is triggered when a user has enabled Windows High Contrast Mode or [Firefox High Contrast Mode](https://firefox-source-docs.mozilla.org/accessible/ColorsAndHighContrastMode.html#the-colors-dialog) (FF HCM). Both of these forced-colors modes offer users a limited amount of color customisation. In Windows, users can override seven colors, and with Firefox High Contrast Mode users can override four. MacOS's "Increase Contrast" setting does **not** trigger `forced-colors: active` because it does not limit the color palette available to UA's.
> **NOTE:** MacOS's "Increase Contrast" setting **will** trigger `forced-colors: active` (in non-chrome web content) if it is enabled in combination with FF HCM's "Only with High Contrast Themes" option. This is also true on Linux. Because [FF HCM defaults to "Never" on non-Windows platforms](https://searchfox.org/mozilla-central/rev/896042a1a71066254ceb5291f016ca3dbca21cb7/modules/libpref/init/StaticPrefList.yaml#1195-1199), enabling "Increase Contrast" or Linux High Contrast Themes alone will not trigger `forced-colors: active`. Similarly, if a user disables FF HCM while Win HCM is enabled, `forced-colors` (in content) will evaluate to `none`.

#### CSS System Colors

Colors that are overridden by the forced-colors modes list above are inherited into the browser's [CSS System Colors](https://www.w3.org/TR/css-color-4/#css-system-colors). Designers must use these colors exclusively in their designs when designing for forced-colors modes. CSS System Colors are intended to be used in pairs: for example the `ButtonFace` and `ButtonText` colors should be used together to create styling for interactive controls. The full pairings are listed in the [system color pairings](https://www.w3.org/TR/css-color-4/#system-color-pairings) section of the CSS spec. Mozilla has additional design guidance for using CSS System Colors in our [HCM Design Guide](https://wiki.mozilla.org/Accessibility/Design_Guide). You can also check out our other docs to [learn more about color overriding](https://firefox-source-docs.mozilla.org/accessible/ColorsAndHighContrastMode.html).

### Prefers Contrast

The `prefers-contrast` media query has four values: `more`, `less`, `custom`, and `no-preference`.

* The `more` state is triggered when a user has macOS's "Increase Contrast" setting enabled, or when a forced-colors mode is active **and** the ratio between a user's [chosen foreground and background](https://searchfox.org/mozilla-central/rev/655f49c541108e3d0a232aa7173fbcb9af88d80b/layout/style/PreferenceSheet.cpp#123-126) is higher than 7:1. This check is done [in our style system](https://searchfox.org/mozilla-central/rev/655f49c541108e3d0a232aa7173fbcb9af88d80b/layout/style/nsMediaFeatures.cpp#287-308).
* The `less` state is triggered when a forced-colors mode is active and the foreground/background ratio is less than 4.5.
* When a forced-colors mode is enabled with a ratio between these two values, we return `custom`.
* Otherwise, if no forced-colors mode is active, and macOS's "Increase Contrast" is off, the media query resolves to `no-preference`.

## So what do I use?

Generally, this boils down to which operating systems you want your styling to apply to. In the past, we've often written code to target _all_ platforms within `prefers-contrast` blocks because the kinds of changes we make to target forced-colors mode also benefit "Increase Contrast" users on macOS; they allow system colors to propagate to the UA. The palette that macOS supplies when "Increase Contrast" is enabled is _also_ inherited to CSS System Colors, and may offer improvements over the standard palette for a design. It is still possible that changes made for forced-colors modes benefit "Increase Contrast" users, however we strongly encourage developers to consider whether diversifying our designs for these modes provides better UX.

On macOS, we aren't limited to the OS palette. Instead of modifying a design to use fewer colors, we can simply increase the contrast ratio of the existing colors to 7:1 to satisfy [the enhanced contrast criterion of Web Content Accessibility Guidelines (WCAG)](https://www.w3.org/WAI/WCAG22/Understanding/contrast-enhanced.html) for better accessibility. Consider the following designs.

Standard UX on macOS:



UX with increased contrast of existing colors on macOS:



Changes present in this example belong in a `prefers-contrast: more` block. This is **assuming these changes are appropriately overridden in the cascade for `forced-colors: active` users**. If they are not overridden, an additional query like `@media (-moz-platform: macos)` or `.. and (not (forced-colors))` should be combined with `prefers-contrast: more` to ensure these changes only apply to macOS.
For users who prefer less contrast, we can supply colors that lower the contrast ratios in the existing design and encase those changes in a `prefers-contrast: less` block.

UX with limited color palette in FF HCM on macOS:



In forced-colors modes, we require that designs reduce their palettes for compatibility. To accomplish this, we use CSS System Colors instead of the original design colors. This allows the overridden palette to "show through", since colors from the various forced-colors modes are inherited into CSS System Colors. It is possible that using CSS System Colors also increases contrast for users on macOS, but this more drastically changes the design at hand, and can detract from the overall user experience for users who are simply looking for more contrast. Designers should consider the additional guidelines on border use, removing gradients, etc. in our [HCM Design Guide](https://wiki.mozilla.org/Accessibility/Design_Guide).

> **NOTE:** Firefox's chrome style sheets are subject to different rules than web-author style sheets.

Firefox's chrome style sheets (including those in our `about:` pages) are not prevented from using colors that aren't system colors, even if a forced colors mode is enabled. In webpages, however, Firefox forces CSS System Colors regardless of the author's original specification. This is a safety mechanism to ensure pages render appropriately even if no `@media (prefers-contrast)` or `@media (forced-colors)` styling was specified. To avoid this overriding, web authors can use the [forced-color-adjust: none;](https://developer.mozilla.org/en-US/docs/Web/CSS/forced-color-adjust) CSS property.

## Writing Maintainable Frontend Code

Where possible, we prefer color overriding for `prefers-contrast` and `forced-colors` take place in one block at the `root` level rather than in many blocks on an element-by-element basis. We encourage developers to use [design systems tokens](https://searchfox.org/mozilla-central/rev/c130c69b7b863d5e28ab9524b65c27c7a9507c48/toolkit/themes/shared/design-system/tokens-shared.css) with semantic naming when overriding. Consider the following.

```text
:root {
  --page-background: #cccccc;
  --page-text-color: #000000;

  @media (forced-colors) {
    --page-background: Canvas;
    --page-text-color: CanvasText;
  }
}

body {
  color: var(--page-text-color);
  background-color: var(--page-background);
}
```

Here, we've defined one set of color variables on `:root` and subsequently overridden them in a `forced-colors` block. We don't need to re-write the styling for `body` within our media query because the vars it references will correctly adapt when `forced-colors` is active.

Though `forced-colors` overriding doesn't happen in Firefox chrome style sheets, our style system _does_ force all instances of `transparent` to the [default color](https://searchfox.org/mozilla-central/rev/655f49c541108e3d0a232aa7173fbcb9af88d80b/servo/components/style/properties/cascade.rs#468-481) for a color attribute (usually `CanvasText`). This allows us to specify styles that appear only in forced-colors mode without an additional CSS keyword. It is also sometimes beneficial to define vars at the `:root` level with an initial value (eg. `transparent`, `0px`, `none`) so the vars exist for HCM overriding later (see: `--dialog-border-width`).

```text
:root {
  /* ... */
  --dialog-background: #ffffff;
  --dialog-color: #bbbbbb;
  --dialog-border-color: transparent;
  --dialog-border-width: 0px;

  @media (forced-colors) {
    /* ... */
    --dialog-background: Canvas;
    --dialog-color: CanvasText;
    /* No override for --dialog-borer-color, since it'll become
    * CanvasText when HCM is enabled, which matches the HCM spec. */
    --dialog-border-width: 1px;
  }
}

.dialog {
  color: var(--dialog-color);
  background-color: var(--dialog-background);
  border: var(--dialog-borer-width) solid var(--dialog-border-color);
}

/* ... */
```

In general, it is best to do overriding at the `:root` level, even if additional variables are required. It is _not_ recommended to do overriding on a class-by-class or element-by-element basis, like below:

```text
:root {
  /* ... */
  --button-background: #ffffff;
  --button-text-color: #bbbbbb;

  @media (forced-colors) {
    /* ... */
    --button-background: ButtonFace;
    --button-text-color: ButtonText;
    --button-border-color: var(--button-text-color);
  }
}

@media (forced-colors) {
  /* BAD: These rules are generic and should be outside of a @media block */
  .destroyButton {
    color: var(--button-text-color);
    background-color: var(--button-background);
    border: 1px solid var(--button-border-color);
  }
}

@media (not (forced-colors)) {
  /* BAD: Element-level styling should not be placed in media query blocks.
   * See "Scoping token overrides with @media (not (forced-colors))" below
   * for when this pattern IS appropriate. */
  .destroyButton {
    color: var(--light-grey-20);
    background-color: var(--red-60);
  }
}
/*...*/
```

## Scoping token overrides with `@media (not (forced-colors))`

When you introduce a custom override for a CSS variable that **already has a `@media (forced-colors)` value in the design system token layer**, wrapping your override in `@media (not (forced-colors))` prevents it from replacing that value. When forced-colors is active, the scoped declaration does not apply at all, leaving the token layer's system-color value as the only one in effect — no extra forced-colors handling required.

Consider a variable that already has a forced-colors override in the token layer:

```css
:root {
  --page-background: #f0f0f0;

  @media (forced-colors) {
    --page-background: Canvas;
  }
}
```

A component author later adds a dark-mode-aware override:

```text
/* BAD: replaces the token layer's Canvas value for forced-colors users */
:root {
  --page-background: light-dark(#f0f0f0, #1a1a1a);
}

/* GOOD: only applies when forced-colors is not active, so forced-colors
 * users still get the Canvas value from the token layer above */
@media (not (forced-colors)) {
  :root {
    --page-background: light-dark(#f0f0f0, #1a1a1a);
  }
}
```

When choosing between `@media (not (forced-colors))` and `@media (not (prefers-contrast))` you need to consider a few things:

* Do defaults exist for the tokens you're overriding in _both_ the prefers-contrast layer and the forced-colors layer? Or are defaults only specified in a single layer? Remember: the goal of this override strategy is to reveal the defeault token values.
* Do your new token values increase contrast? If so, they could be more valuable to `prefers-contrast` users than the existing token defaults. You should consider exempting `forced-colors` users only.

In most cases, `(not (forced-colors))` is the right choice: it leaves the existing token layer's forced-colors handling in effect, while users who have only a contrast preference (and no active forced-colors mode) continue to benefit from non-system-color visual enhancements.

## Putting it all together

Let's walk through an example on this sample website.

<iframe src="https://mreschenberg.com/sample_site.html" style="width: 100%; height: 60vh;"></iframe>

The majority of our site styling is done via color overriding on the root block.

```css
:root {
  /* General */
  --background: #202124;
  --color: #cccccc;
  --border-color: transparent;
  --border-size: 0;
  --table-background: #303134;
  /* Note */
  --note-background: gold;
  --note-color: var(--table-background);
  --note-opacity: .7;
  /* General Controls */
  --control-background: gray;
  --control-color: var(--color);
  --control-border-size: var(--border-size);
  --control-border-color: var(--border-color);
  /* Destructive Button */
  --destructive-button-background: tomato;
  --destructive-button-color: var(--table-background);
}
```

How might we adapt this website for users who prefer increased contrast? What about for users with forced colors?

Let's start with users who prefer increased contrast. We might decide to make the background and foreground easier to read by making the foreground text lighter, increasing the contrast ratio. We might also remove the note's opacity and darken its text color. We don't need to remove the note's golden background, since prefers-contrast doesn't require a reduced color palette.

```text
:root {
  /* ... */
  @media (prefers-contrast) and (not (forced-colors)) {
    /* General */
    --color: white;
    /* Note */
    --note-color: black;
    --note-opacity: 1;
    /* ... */
  }
}
```

To address these same issues in forced-colors mode, we should replace the colors with the semantically appropriate system color. Unlike our work in the `prefers-contrast` block above, we do need to modify the note's background, since `gold` is not a system color. We might end up with something like this:

```text
:root {
  /* ... */
  @media (forced-colors) {
    /* General */
    --background: Canvas;
    --color: CanvasText;
    --table-background: var(--background);
    /* Note */
    --note-background: var(--background);
    --note-color: var(--color);
    --note-opacity: 1;
    /* ... */
  }
}
```

After this change, you'll notice our page background, table background, and note background all share the same color. This makes them difficult to differentiate. To address this, we can add a contrasting border and override the previously transparent `--border-color` variable and its corresponding `--border-size`. This var applies to content areas but not controls.

```text
:root {
  /* ... */
  @media (forced-colors) {
    /* General */
    --background: Canvas;
    --color: CanvasText;
    --border-color: var(--color);
    --border-size: 1px;
    --table-background: var(--background);
    /* Note */
    --note-background: var(--background);
    --note-color: var(--color);
    --note-opacity: 1;
    /* ... */
  }
}
```

Next, let's look at the controls this page uses for the web form. We've got an input, a checkbox, a submit button, and a clear button. In the prefers-contrast case, we should ensure the controls contrast from the background as much as possible. It's possible to do this via color alone, but it can help to add borders for additional contrast. Here, again, we don't need to get rid of the clear button's `tomato` background, but we can update it to something brighter.

```text
:root {
  /* ... */
  @media (prefers-contrast) and (not (forced-colors)) {
    /* ... */
    /* General Controls */
    --control-background: color-mix(in srgb, gray, lightgray);
    --control-color: black;
    --control-border-size: 1px;
    --control-border-color: gray;
    /* Destructive Button */
    --destructive-button-background: red;
    --destructive-button-color: white;
    /* ... */
  }
}
```

Finally, let's style the page's controls for `forced-colors`. Unlike in prefers-contrast, we can't use color to differentiate between the submit button and the clear form button -- both should inherit from our button CSS system colors.

```text
:root {
  /* ... */
  @media (forced-colors) {
    /* General */
    --background: Canvas;
    --color: CanvasText;
    --border-color: var(--color);
    --border-size: 1px;
    --table-background: var(--background);
    /* Note */
    --note-background: var(--background);
    --note-color: var(--color);
    --note-opacity: 1;
    /* General Controls */
    --control-background: ButtonFace;
    --control-color: ButtonText;
    --control-border-color: ButtonText;
    /* Destructive Button */
    --destructive-button-background: var(--control-background);
    --destructive-button-color: var(--control-color);
  }
}
```

If we wanted to make the submit button stand out as a primary button, we could invert the styling on that button in particular. Something like:

```text
:root {
  /* ... */
  @media (forced-colors) {
    /* General */
    --background: Canvas;
    --color: CanvasText;
    --border-color: var(--color);
    --border-size: 1px;
    --table-background: var(--background);
    /* Note */
    --note-background: var(--background);
    --note-color: var(--color);
    --note-opacity: 1;
    /* General Controls */
    --control-background: ButtonFace;
    --control-color: ButtonText;
    --control-border-color: ButtonText;
    /* Destructive Button */
    --destructive-button-background: var(--control-background);
    --destructive-button-color: var(--control-color);
  }

  #submit {
    background: var(--control-color);
    color: var(--control-background);
    border: var(--control-border-size) solid currentColor;
  }
}
```

Now we've got a site that functions in multiple HCM scenerios :) Visit the <a href="https://mreschenberg.com/sample_site.html">live site</a> with HCM or Increase Contrast enabled to test it for yourself.
A few takeaways:

* `prefers-contrast` and `forced-colors` are not mutually exclusive. If you write two independent `forced-colors` and `prefers-contrast` media query blocks, they'll both apply when FF HCM is enabled (assuming your foreground/background contrast ratio is high, which it is by default). Adding an `and (not (forced-colors))` clause to your `@media (prefers-contrast)` declaration can help make the two blocks distinct if you'd like mac-centric styling in one and `forced-colors` styling in the other.
* `prefers-contrast` requires specific, case-by-case overriding, whereas `forced-colors` is largely about inheretince. In the former, page regions that are differentiated with color should stay that way (albeit with more contrasting colors). In `forced-colors` all page regions that aren't interactive should use `Canvas`/`CanvasText` and rely on borders for distinction. Once you've set `--background: Canvas;` at the root level, for ex. subsequent background vars should inherit from it.
* Where possible, aim to do overriding at the `:root` level using CSS variables, this makes it easier to update code in the future.

---

### Accessible Docs HCMSettings (`accessible/docs/HCMSettings.md`)

# HCM Settings

Several Firefox settings work together to determine how web content and browser chrome are rendered. They can be hard to keep track of! Use the flowcharts below for quick reference.

## Settings that control color usage in browser chrome

- OS HCM:
  - Windows: High Contrast Mode in OS accessibility settings
  - macOS: Increase Contrast in OS accessibility settings
  - Linux: High Contrast Theme in OS accessibility settings
- FF Theme (AKA FF Colorway)
Note: OS HCM settings will only trigger HCM color usage in chrome if a user's FF theme is set to "system auto". If they have a pre-selected colorway or other FF theme (including explicit "Dark" or "Light") they will not see color changes upon enabling OS HCM.

```{mermaid}
flowchart TD
A[Is OS HCM enabeld?]
A -->|Yes| B[Is FF's theme set to System Auto?]
B --> |Yes| C[Use OS HCM colors to render browser chrome]
B -->|No| D[Use FF theme colors to render browser chrome]
A -->|No| D
```

## Settings that control color usage in content

- Colors Dialog (about:preferences > Contrast Control)
- Extensions like Dark Reader, or changes to user.css, may override author specified colors independent of HCM.

```{mermaid}
flowchart TD
A[Which option is selected in 'Contrast Control'?]

A -->|Use platform's contrast settings| B[Is a OS HCM enabled?]
A -->|Off| H
A --->|On| I[Use colors dialog colors to render all content &lpar;HCM&rpar;]

B -->|Yes| C[Use OS colors to render all content &lpar;HCM&rpar;]
B -->|No| H[Use system colors for all unstyled content]
```

---

### Accessible Docs TaggedPdfOutput (`accessible/docs/TaggedPdfOutput.md`)

# Tagged PDF Output
Tagged PDF embeds a semantic structure tree alongside the graphical content in a PDF, enabling screen readers and other assistive technology to interpret the document.
Firefox generates tagged PDFs by leveraging its accessibility engine and Skia's SkPDF backend.

The feature is toggled by the pref `accessibility.tagged_pdf_output.enabled`.

## High Level Architecture
The implementation spans several modules:

- **`accessible/base/DocManager`**: `NotifyOfPrintDocument` bootstraps the accessibility engine and builds accessibility trees for print documents.
- **`accessible/base/nsAccessibilityService`**: provides an `ePdfOutput` consumer mode that allows the accessibility engine to run in a stripped-down mode purely for PDF generation.
- **`accessible/pdf/PdfStructTreeBuilder`**: translates the Gecko accessibility tree into an `SkPDF::StructureElementNode` tree for Skia and maps accessibility node IDs to SkPDF node IDs.
- **`gfx/thebes/PrintTargetSkPDF`**: the Skia PDF print target, which calls `PdfStructTreeBuilder` to obtain the structure tree and passes it to `SkPDF::MakeDocument`.
- **`layout/generic/nsIFrame`** + **`layout/painting/nsDisplayList`**: layout emits `nsDisplayAccessibleId` display items to associate painted content with accessibility nodes.
- **`gfx/2d/DrawTarget`** + **`gfx/2d/DrawTargetSkia`**: the `AccessibleId` draw command propagates the association down to Skia, where `SkPDF::SetNodeId` tags subsequent drawing commands.

## Triggering Tagged PDF Generation
When a print job starts, [`nsPrintJob::SetupToPrintContent`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/layout/printing/nsPrintJob.cpp#903) calls [`a11y::DocManager::NotifyOfPrintDocument(doc)`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/base/DocManager.cpp#203).

`NotifyOfPrintDocument` calls [`GetOrCreateAccService(nsAccessibilityService::ePdfOutput)`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/base/nsAccessibilityService.h#553) to ensure the accessibility service is running, then creates a `DocAccessible` for the print document (a static clone of the live document, so `aAllowStatic=true` is passed), and immediately calls [`DoInitialUpdate()`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/generic/DocAccessible.cpp#1835) to build the accessibility tree synchronously.
In-process iframes embedded in the document are also initialized here in the same way.

For a parent process document, `NotifyOfPrintDocument` calls [`PdfStructTreeBuilder::Init`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/pdf/PdfStructTreeBuilder.cpp#36) directly.
For remote documents in content processes, after the local accessibility tree is built, `NotifyOfPrintDocument` arranges for `PdfStructTreeBuilder::Init(browsingContext)` to be called in the parent process (see the next section on IPC).

## IPC: Remote Top Level Documents and OOP Iframes
Content can live in content processes, but a PDF can only be generated in the parent process, regardless of where the content lives or where the print job is initiated.
There are two IPC cases.

### Remote Top Level Document
`nsPrintJob` runs in whatever process owns the document, so for a remote tab, `NotifyOfPrintDocument` runs in the content process.
After building the accessibility tree locally and sending it to the parent process via `PDocAccessible`, [a `PDocAccessible::Printing` IPDL message is sent to the parent process](https://searchfox.org/firefox-main/rev/f3695d1fd8d9f7419576d8e0366069bf2cc576ac/accessible/base/DocManager.cpp#245).
[`DocAccessibleParent::RecvPrinting`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/ipc/DocAccessibleParent.cpp#1500) handles this message and calls `PdfStructTreeBuilder::Init` in the parent process.

### OOP Iframes
Once `PdfStructTreeBuilder::Init` runs in the parent process for the top level document as described above, [`InitInternal`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/pdf/PdfStructTreeBuilder.cpp#138) walks all descendant `BrowserParent`s and sends a `PBrowser::RequestDocAccessibleForPrint` IPDL message to each.
In the content process, [`BrowserChild::RecvRequestDocAccessibleForPrint`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/dom/ipc/BrowserChild.cpp#4248) calls `NotifyOfPrintDocument`.
As above, this builds the accessibility tree, sends it to the parent process, sends `PDocAccessible::Printing` and thus calls `PdfStructTreeBuilder::Init` in the parent process.

`PdfStructTreeBuilder` tracks how many OOP iframes are pending via `mPendingOopIframes`.
Each time an OOP iframe's accessibility tree arrives and is registered with the builder via a further call to `InitInternal`, the counter is decremented.
When it reaches zero, a `ReadyPromise` is resolved.
[The print job awaits this promise before proceeding](https://searchfox.org/firefox-main/rev/f3695d1fd8d9f7419576d8e0366069bf2cc576ac/layout/printing/ipc/RemotePrintJobParent.cpp#45).

SkPDF requires the complete structure tree at the time the document is opened, so this waiting is necessary before `SkPDF::MakeDocument` can be called.

## Building the Structure Tree
Once the `ReadyPromise` resolves, [`PrintTargetSkPDF::BeginPrinting`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/gfx/thebes/PrintTargetSkPDF.cpp#211) calls [`PdfStructTreeBuilder::BuildStructTree`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/pdf/PdfStructTreeBuilder.cpp#170).
This walks the accessibility tree rooted at the top document — using `DocAccessible` for in-process documents and `DocAccessibleParent` for remote ones — and recursively builds a tree of `SkPDF::StructureElementNode` objects.

For each accessible, [`BuildStructSubtree`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/pdf/PdfStructTreeBuilder.cpp#210):
- Assigns an SkPDF integer node ID (via [`GeneratePdfId`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/pdf/PdfStructTreeBuilder.cpp#190)) and records the mapping in `mAccToPdf`.
- Maps the Gecko accessibility role to the corresponding PDF structure type; e.g. `roles::HEADING` → `"H1"`–`"H6"` or `"H"`, `roles::PARAGRAPH` → `"P"`, `roles::TABLE` → `"Table"`, etc.
- Depending on the role, maps Gecko accessibility properties to PDF attributes such as table row/column span, header associations and alt text for figures and headings.

The completed struct tree root is stored in `SkPDF::Metadata::fStructureElementTreeRoot` before `SkPDF::MakeDocument` is called.
SkPDF also derives a PDF bookmark outline from heading nodes; headings' accessible names are set as `fAlt` to provide this text, since Gecko provides glyph indices rather than text runs when drawing.

## Associating Painted Content with Structure Nodes
The struct tree alone is not sufficient: each drawing command in the content stream must be tagged with the SkPDF node ID of the structure element it belongs to.

### Layout: Emitting `nsDisplayAccessibleId`
During display list construction for a print document, [`nsIFrame::BuildDisplayListForChild`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/layout/generic/nsIFrame.cpp#4238) calls the local helper [`MaybeAddAccId`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/layout/generic/nsIFrame.cpp#4223) for each child frame.
`MaybeAddAccId` calls [`PdfStructTreeBuilder::GetAccId(frame)`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/pdf/PdfStructTreeBuilder.cpp#105) which looks up the `Accessible` for the frame's content node and returns a `{browsingContextId, accessibleId}` pair.
If one is found, an [`nsDisplayAccessibleId`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/layout/painting/nsDisplayList.h#6854) display item is prepended to the content list for that frame.

### Painting: The `DrawTarget::AccessibleId` Command
[`nsDisplayAccessibleId::Paint`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/layout/painting/nsDisplayList.cpp#8737) calls [`DrawTarget::AccessibleId(browsingContextId, accId)`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/gfx/2d/2D.h#1459).
For parent process content rendered directly to a `DrawTargetSkia` backed by an SkPDF canvas, [`DrawTargetSkia::AccessibleId`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/gfx/2d/DrawTargetSkia.cpp#2259) translates the Gecko IDs to a SkPDF integer via [`PdfStructTreeBuilder::GetPdfId`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/pdf/PdfStructTreeBuilder.cpp#88), then calls `SkPDF::SetNodeId(mCanvas, pdfId)`.
All drawing commands issued to the canvas after this point are tagged with that node in the PDF.

### Content Process: `DrawTargetRecording`
When content is painted in a content process, it goes through `DrawTargetRecording`.
[`DrawTargetRecording::AccessibleId`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/gfx/2d/DrawTargetRecording.cpp#991) emits a [`RecordedAccessibleId`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/gfx/2d/RecordedEventImpl.h#1880) event into the recording stream .
When the recording is replayed in the parent process on a `DrawTargetSkia`, `RecordedAccessibleId::PlayEvent` calls `DrawTargetSkia::AccessibleId` and the same SkPDF tagging occurs as described above.

## Stripped-Down Accessibility Engine (`ePdfOutput` Mode)
Without a dedicated PDF output mode, tagged PDF generation would require an AT client to already be running (or the engine to be force enabled), because normal accessibility engine startup does significant work that is only needed to serve AT clients: walking all existing documents, initialising platform accessibility APIs and activating the service in every content process.
None of this work is necessary to build an accessibility tree for a single document being printed.
The [`ePdfOutput`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/base/nsAccessibilityService.h#405) consumer mode allows the engine to start in a lightweight mode when the only reason it is needed is to generate a tagged PDF.

### `ePdfOutput` Consumer Flag
`nsAccessibilityService` has a bitmask of active consumers.
If only the `ePdfOutput` bit is set, this indicates that the only reason the service is running is to support PDF generation.
[`nsAccessibilityService::IsOnlyForPdfOutput()`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/base/nsAccessibilityService.h#413) returns true in this case.

### Skipped Initialization
When `GetOrCreateAccService(ePdfOutput)` starts the engine and no other consumer is active, [`nsAccessibilityService::Init`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/base/nsAccessibilityService.cpp#1650) **skips** three steps that are deferred into [`FullInit`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/base/nsAccessibilityService.cpp#1724):

1. [`ApplicationAccessible::CreateInitialDocs`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/generic/ApplicationAccessible.cpp#113): forces creation of `DocAccessible`s for all already-open windows.
2. [`PlatformInit`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/base/Platform.h#73): initializes platform accessibility APIs (IAccessible2/UIA on Windows, ATK on Linux, etc.).
3. Activating the accessibility service in every content process.

The `a11y-init-or-shutdown` notification is fired with the value `"pdf"` instead of `"1"` to let observers distinguish this limited startup from a full one.

### Suppressing Unrelated `DocAccessible` Creation
While `IsOnlyForPdfOutput()`, [creation of `DocAccessible`s is suppressed](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/base/DocManager.cpp#519) for any document that was not explicitly passed to `NotifyOfPrintDocument`.
This prevents ordinary browsing documents from consuming resources they do not need.

### Promotion to Full Service
If a real AT consumer (e.g. a screen reader) causes `GetOrCreateAccService` to be called while the service is already running in `ePdfOutput`-only mode, [`PromoteFromPdfOutput`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/base/nsAccessibilityService.cpp#1745) is called to perform the deferred `FullInit` work: creating initial document accessibles, running `PlatformInit` and notifying content processes.

### Cache Domains
Print documents use a specific set of cache domains (requested per-document via [`DocAccessible`](https://searchfox.org/firefox-main/rev/f3695d1fd8d9f7419576d8e0366069bf2cc576ac/accessible/generic/DocAccessible.cpp#396)/[`DocAccessibleParent`](https://searchfox.org/firefox-main/rev/f3695d1fd8d9f7419576d8e0366069bf2cc576ac/accessible/ipc/DocAccessibleParent.cpp#78)) rather than the global `gCacheDomains`.
This is done so that PDF output does not inadvertently widen the cache domains in use by any other running clients.
This also avoids pushing unnecessary domains for PDF when another client requires a wider set of domains.
Note that a print document is a static clone of the original DOM document, so this doesn't impact the original document being printed.

### Lifecycle
When the last print document is removed, [the `ePdfOutput` consumer bit is cleared](https://searchfox.org/firefox-main/rev/f3695d1fd8d9f7419576d8e0366069bf2cc576ac/accessible/base/DocManager.cpp#137).
If no other consumers remain, the accessibility service shuts down normally.
[`PdfStructTreeBuilder::Done`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/accessible/pdf/PdfStructTreeBuilder.cpp#75) is called from [`nsDeviceContext::EndDocument`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/gfx/src/nsDeviceContext.cpp#269)/[`AbortDocument`](https://searchfox.org/firefox-main/rev/2e7b2a02b5198ae72c06debc5cc1c2ac527fd742/gfx/src/nsDeviceContext.cpp#306) to clean up the builder instance after printing completes or is aborted.

## Data Flow Summary
```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Accessible Docs Index (`accessible/docs/index.rst`)

Accessibility
=============

These pages contain design documents for the accessibility implementation in Gecko.
They live in the mozilla-central repository under the accessible/docs directory.

The `Accessibility page on the Mozilla Wiki <https://wiki.mozilla.org/Accessibility>`__ contains general information about accessibility and the accessibility team at Mozilla.

The `Mochitest FAQ docs <../testing/mochitest-plain/faq.html#how-can-i-run-accessibility-tests-a11y-checks>`__ contain guidance on debugging a11y-checks failures and working with AccessibilityUtils when writing frontend test cases.

.. toctree::
   :maxdepth: 1

   GuidelinesForNewContributors
   Architecture
   DocumentAccessibilityLifecycle
   GeckoViewThreadTopography
   ColorsAndHighContrastMode
   HCMSettings
   HCMMediaQueries
   HCMCSSChecklist
   TaggedPdfOutput

---

### Browser Docs BrowserStartup (`browser/docs/BrowserStartup.md`)

# Browser Startup

## Invoking your code on browser startup

The first rule of running code during startup is: don't.

We take performance very seriously and ideally your component/feature should
initialize only when needed.

If you have established that you really must run code during startup, register
a category manager entry in `browser/components/BrowserComponents.manifest`.
See [the category manager indirection docs](./CategoryManagerIndirection.md) for
more details on the mechanism.

### Available category manager entries (in order)

Categories come in two types: per-application (fired once at startup) and
per-window (fired for each browser window). The following categories
are listed in the order they fire.

#### Per-application categories (invoked once, not per-window)

| Category | Notes |
|---|---|
| `browser-before-ui-startup` | Please don't do it unless absolutely necessary. This will run code before the first browser window appears on the screen and make Firefox seem slow. |
| `browser-first-window-ready` | After the first browser window's `browser-window-delayed-startup` call. |
| `browser-idle-startup` | Preferred entrypoint for most startup code. Runs during a user-idle period after startup. |
| `browser-best-effort-idle-startup` | Like `browser-idle-startup`, but your code **may not run at all** if the browser is shut down quickly. |

#### Per-window categories (invoked for each browser window)

| Category | Notes |
|---|---|
| `browser-window-before-initial-xul-layout-document-preparation` | Before XUL layout; before the tab bar visibility update. |
| `browser-window-before-initial-xul-layout` | Before XUL layout; after the tab bar visibility update and document icon are set. |
| `browser-window-domcontentloaded-before-tabbrowser` | During `DOMContentLoaded`, before the `Tabbrowser` is created. |
| `browser-window-domcontentloaded-tabbrowser` | During `DOMContentLoaded`, creates the `Tabbrowser`. **Internal category - do not add consumers here.** |
| `browser-window-domcontentloaded` | During `DOMContentLoaded`, after the `Tabbrowser` is created. Preferred entry point for `DOMContentLoaded` initialization. |
| `browser-window-load-before-sessionstore-init` | During the window `load` event, before SessionStore initializes the window. For components that must be ready before session restore runs. |
| `browser-window-load` | During the window `load` event, after SessionStore has initialized the window. |
| `browser-window-delayed-startup` | After the window's first paint, for code that can run after the window is visible. |
| `browser-window-location-change` | Fires on every `XULBrowserWindow.onLocationChange` for the window. |
| `browser-window-unload-begin` | At the very start of window unload, before checking whether the window finished loading. Runs even if the window never fully loaded. |
| `browser-window-unload` | During window unload, before `Tabbrowser` is destroyed. Preferred entry point for window unload cleanup. |
| `browser-window-unload-tabbrowser` | During window unload, destroys the `Tabbrowser`. **Internal category - do not add consumers here.** |
| `browser-window-final-unload` | During window unload, after `Tabbrowser` is destroyed. |

Other useful points in startup are:

- `BrowserGlue`'s `_onWindowsRestored`, and/or the observer service's
  `sessionstore-windows-restored` topic, and/or a category manager call that
  should replace the `BrowserGlue` list of direct calls. This fires after
  session restore has completed restoring all windows (but before all pages
  that may have been restored have necessarily loaded). Note that this is
  guaranteed to fire even if automatic session restore is not enabled.

## How do first run/first startup experiments work?

Why does synchronously reading Nimbus feature values work for
customizing display features like `about:welcome` onboarding and the
default browser prompt? The key invariant is that the display
decisions wait for `sessionstore-windows-restored` to show
customizable UI, and therefore we just need Nimbus available to read
at that point. This is arranged either via the `--first-startup`
flag; or, for subsequent startups, the relevant Nimbus features being
marked `isEarlyStartup: true`. When `isEarlyStartup: true`, Nimbus
caches all its feature variables as Gecko preferences, ready to be
read during early startup. (See [the early startup
docs](https://experimenter.info/faq/early-startup/what-do-it-do).)

Customizable display features like `about:welcome` or the default
browser prompt are used in
[`_maybeShowDefaultBrowserPrompt()`](https://searchfox.org/mozilla-central/rev/a965e3c683ecc035dee1de72bd33a8d91b1203ed/browser/components/BrowserGlue.sys.mjs#4685),
which is invoked as part of a startup idle task. Startup idle tasks
are [scheduled in response to
`sessionstore-windows-restored`](https://searchfox.org/mozilla-central/rev/a965e3c683ecc035dee1de72bd33a8d91b1203ed/browser/components/BrowserGlue.sys.mjs#2423).

Now, why is `sessionstore-windows-restored` late enough for a
first startup experiment? The answer is subtle.

During Firefox launch, [`final-ui-startup` is
notified](https://searchfox.org/mozilla-central/rev/a965e3c683ecc035dee1de72bd33a8d91b1203ed/toolkit/xre/nsAppRunner.cpp#5764-5765),
and in response `SessionStore` is initialized. Additionally,
Nimbus/Normandy initialization is [started but not
awaited](https://searchfox.org/mozilla-central/rev/a965e3c683ecc035dee1de72bd33a8d91b1203ed/browser/components/BrowserGlue.sys.mjs#1487).

Then the [command line is
handled](https://searchfox.org/mozilla-central/rev/a965e3c683ecc035dee1de72bd33a8d91b1203ed/toolkit/xre/nsAppRunner.cpp#5775-5778).
When `--first-startup` is passed, we [spin the event loop to allow
Nimbus/Normandy time to complete its initialization and first
fetch](https://searchfox.org/mozilla-central/rev/a965e3c683ecc035dee1de72bd33a8d91b1203ed/browser/components/BrowserContentHandler.sys.mjs#677)
before continuing to process the command line. See [the
`FirstStartup`
module](https://firefox-source-docs.mozilla.org/toolkit/modules/toolkit_modules/FirstStartup.html).
(Important caveat: `--first-startup` is only used on Windows; see [Bug
1872934](https://bugzilla.mozilla.org/show_bug.cgi?id=1872934), for
example.)

This races with `SessionStore`, which itself waits for the first
browser window to be shown -- in particular, the
`sessionstore-windows-restored` notification waits for the [first
browser window's `browser-delayed-startup-finished`
notification](https://searchfox.org/mozilla-central/rev/a965e3c683ecc035dee1de72bd33a8d91b1203ed/browser/components/sessionstore/SessionStore.sys.mjs#2147-2159).

This first `browser-delayed-startup-finished` notification **is not
guaranteed** to be after `--first-startup` has spun the event loop!
But, when launched with only `--first-startup` and flags considered
very early in `nsAppRunner.cpp` -- as [the stub installer
does](https://searchfox.org/mozilla-central/rev/a965e3c683ecc035dee1de72bd33a8d91b1203ed/browser/installer/windows/nsis/stub.nsi#1424-1456)
-- then the first window **is guaranteed** to be after the event loop
has been spun, and therefore `sessionstore-windows-restored` is after
as well. (As a counter-example: try `firefox.exe --browser
--first-startup` and witness the [`--browser`
flag](https://searchfox.org/mozilla-central/rev/a965e3c683ecc035dee1de72bd33a8d91b1203ed/browser/components/BrowserContentHandler.sys.mjs#505-508)
creating a window before spinning the event loop, inadvertently racing
against `sessionstore-windows-restored`.) Making this deterministic
is tracked by [Bug
1944431](https://bugzilla.mozilla.org/show_bug.cgi?id=1944431).

Together, this means that first-startup experiments will be loaded in
time to impact display features such as `about:welcome` and the
default browser prompt, and we should not have a "split brain"
scenario in which the Nimbus feature is intermittently unavailable to
the relevant display features.

---

### Browser Docs BrowserUsageTelemetry (`browser/docs/BrowserUsageTelemetry.rst`)

.. _browserusagetelemetry:

=======================
Browser Usage Telemetry
=======================

The :searchfox:`BrowserUsageTelemetry.sys.mjs <browser/modules/BrowserUsageTelemetry.sys.mjs>` module is the main module for measurements regarding the browser usage (e.g. tab and window counts, search counts, ...).

The measurements recording begins right after the ``SessionStore`` has finished restoring the session (i.e. restoring tabs/windows after Firefox starts).

Tab and window interactions
===========================
The usage telemetry module currently measures these interactions with the browser's tabs and windows:

- *tab and window engagement*: counts the number of non-private tabs and windows opened in a subsession, after the session is restored (see e.g. ``browser.engagement.max_concurrent_tab_count``);
- *URI loads*: counts the number of page loads (doesn't track and send the addresses, just the counts) directly triggered by the users (see ``browser.engagement.total_uri_count``);
- *navigation events*: at this time, this only counts the number of time a page load is triggered by a particular UI interaction (e.g. by searching through the URL bar, see ``browser.engagement.navigation.urlbar``).


Please see :searchfox:`Scalars.yaml <toolkit/components/telemetry/Scalars.yaml>` for the full list of tracked interactions.

Customizable UI
===============

This telemetry records information about the positions of toolbar items and when
the user interacts with them. It is submitted as scalar values along with the
normal telemetry ping. There are a number of different parts to this telemetry:

UI Areas
--------

For the purposes of this telemetry a set of areas are defined:

* In the main browser UI:

  * ``menu-bar`` - The main menu.
  * ``menu-toolbar`` - The normally hidden toolbar that holds the main menu.
  * ``titlebar`` - The optional title bar.
  * ``tabs-bar`` - The area where tabs are displayed.
  * ``vertical-tabs-container`` - The area where vertical tabs are displayed.
  * ``bookmarks-bar`` - The bookmarks toolbar.
  * ``app-menu`` - The main application (hamburger) menu.
  * ``tabs-context`` - The context menu shown from right-clicking a tab.
  * ``content-context`` - The context menu shown from right-clicking the web page.
  * ``widget-overflow-list`` - Items that have overflowed the available space.
  * ``pinned-overflow-menu`` - Items that the user has pinned to the toolbar overflow menu.
  * ``pageaction-urlbar`` - Page actions buttons in the address bar.
  * ``pageaction-panel`` - The page action (meatball) menu.
  * ``nav-bar-start`` - The area of the navigation toolbar before the address bar.
  * ``nav-bar-end`` - The area of the navigation toolbar after the address bar.
  * ``unified-extensions-area`` - The unified extensions panel.

* In ``about:preferences`` the different categories are used:

  * ``preferences-paneDownloads``
  * ``preferences-paneGeneral``
  * ``preferences-paneHome``
  * ``preferences-panePrivacy``
  * ``preferences-paneSearch``
  * ``preferences-paneSearchResults``
  * ``preferences-paneSync``
  * ``preferences-paneContainers``
  * ``preferences-paneAccessibility``
  * ``preferences-paneAppearance``
  * ``preferences-paneLanguages``
  * ``preferences-paneAbout``
  * ``preferences-panePermissionsData``
  * ``preferences-paneTabsBrowsing``

Widget Identifiers
------------------

In order to uniquely identify a visual element a set of heuristics are used:

#. If the element is one of the customizable toolbar items then that item's ID
   is used.
#. If the DOM element has an ID set then that is used.
#. If the DOM element's class contains one of ``bookmark-item``,
   ``tab-icon-sound`` or ``tab-close-button`` then that is used.
#. If the DOM element has a ``preference`` ``key``, ``command``, ``observes`` or
   ``data-l10n-id`` attribute then that is used.
#. If there is still no identifier then this is repeated for the DOM element's
   parent element.

Widget Locations
----------------

The keyed scalar ``browser.ui.toolbar_widgets`` records the position of widgets in
the UI. At startup the positions of widgets are collected and recorded by
setting the scalar key ``<widget id>_pinned_<area>`` to true. The widget ID are
the IDs of the elements in the DOM. The area is one of the areas listed above
from the browser UI that can be customised.

For the areas that can be controlled the scalar keys ``<area>_<off/on/newtab>`` are set.
``newtab`` is special to the Bookmarks Toolbar and is used when the toolbar will only
be shown on the New Tab page.

Widget Customization
--------------------

The scalar ``browser.ui.customized_widgets`` records whenever the user moves a
widget around the toolbars or shows or hides some of the areas. When a change
occurs the scalar with the key ``<widget id>_<action>_<old area>_<new area>_<reason>``
is incremented. The action can be one of ``move``, ``add`` or ``remove``. Old
area and new area are the previous and now locations of the widget. In the case
of ``add`` or ``remove`` actions one of the areas will be ``na``. For areas that
can be shown or hidden the areas will be ``off`` or ``on``. The reason is a simple
string that indicates what caused the move to happen (drag, context menu, etc.).

UI Interactions
---------------

The scalars ``browser.ui.interaction.<area>`` record how often the use
interacts with the browser. The area is one of those above with the addition of
``keyboard`` for keyboard shortcuts.

When an interaction occurs the widget's identifier is used as the key and the
scalar is incremented. If the widget is provided by an add-on then the add-on
identifier is dropped and an identifier of the form ``addonX`` is used where X
is a number. The number used is stable for a single session. Every time the user
moves or interacts with an add-on the same number is used but then the numbers
for each add-on may change after Firefox has been restarted.

Profile Count
=============

The scalar ``browser.engagement.profile_count`` records how many profiles have
been used by the current Firefox installation. It reports a bucketed result,
which will be 0 if there is an error. The raw value will be reported for 1-10,
but above that, it will report 10 for 10-99, 100 for 100-999, 1000 for
1000-9999, and 10000 for any values greater than that.

The profile count data for an installation is stored in the root of the
update directory in a file called ``profile_count_<install hash>.json``. The
full path to the file will typically look something like
``C:\ProgramData\Mozilla\profile_count_5A9E6E2F272F7AA0.json``.

This value is meant to be resilient to re-installation, so that file will not
be removed when Firefox is uninstalled.

Context menu entrypoints
========================

Some context menus are re-used in multiple places. By default, we simply count
the number of interactions per item within a context menu, and do not record
the entrypoint that caused the context menu to open.

It is possible to opt-in to recording the entrypoint that caused the context
menu to open. This is done by adding an entry to
``ENTRYPOINT_TRACKED_CONTEXT_MENU_IDS``, mapping the ID of the context menu
to a keyed Scalar under ``browser.ui.interaction.``. This scalar is recorded
only if an interaction is recorded within the context menu itself.

When the keyed scalar is recorded, the key will be a unique ID for the
trigger node that caused the context menu to open. The value is the count
of openings from that trigger node.

---

### Browser Docs CategoryManagerIndirection (`browser/docs/CategoryManagerIndirection.md`)

# Category manager indirection (callModulesFromCategory)

Firefox front-end code uses the category manager as a publish/subscribe
mechanism for dependency injection, so consumers can be notified of interesting
things happening without having to directly talk to the publisher/actor who
decides the interesting thing is happening.

There are 2 parts to this:

1. Consumers registering with the category manager
2. Publishers/actors invoking consumers via the category manager.

## Consumer registration with the category manager

The category manager is used for various purposes within Firefox; it is more or
less an arbitrary double string-keyed data store.

For this particular usecase, the publisher/consumer have to use the same
primary key (i.e. category name), such as `browser-idle-startup`.

The secondary key is a full URL to a `sys.mjs` module. Note that because this
is a key, **only one consumer per module & category combination is possible**.

The "value" part is an `Object.method` notation, where the expectation is that
`Object` is an exported symbol from the module identified as the secondary key,
and `method` is some method on that object.

At compile-time, registration can happen with an entry in a `.manifest` file
like [BrowserComponents.manifest](https://searchfox.org/firefox-main/source/browser/components/BrowserComponents.manifest).
Note that any manifest successfully processed by the build system would do,
we don't need to use `BrowserComponents.manifest` specifically. In fact, it
would be preferable if components used their own manifest files.

An example registration looks like:

```
category browser-idle-startup moz-src:///browser/components/tabbrowser/TabUnloader.sys.mjs TabUnloader.init
```

This will ensure that when the `browser-idle-startup` publisher is invoked,
the `TabUnloader.sys.mjs` module is loaded and the `init` method on the exported
`TabUnloader` object is invoked.

### Runtime registration

Runtime registration is less-often used, but can be done using the category
manager's XPCOM API:

```js
Services.catMan.addCategoryEntry(
    "browser-idle-startup",
    "moz-src:///browser/components/tabbrowser/TabUnloader.sys.mjs",
    "TabUnloader.init"
)
```

## Publishers/actors invoking consumers

Publishers call `BrowserUtils.callModulesFromCategory` with a dictionary of
options as the first argument. If provided, any other arguments are passed
straight through to any consumers.

```{js:autofunction} BrowserUtils.callModulesFromCategory
```

Example:

```js
BrowserUtils.callModulesFromCategory({
    categoryName: "my-fancy-category-name",
    profilerMarker: "markMyCategories",
    idleDispatch: true,
    someArgument
});
```

This will pass `someArgument` to each consumer registered for
`my-fancy-category-name`. Each consumer will be invoked via an idle task, and
each task will get a profiler marker (labelled `"markMyCategories"`) in the
[Firefox Profiler](https://profiler.firefox.com/) so it's easy to find in
performance profiles.

You should consider using `idleDispatch: true` if invocation of the consumers
does not need to happen synchronously.

If you need to care about errors produced by consumers, you can specify
a function for `failureHandler` and handle any exceptions/errors using your own
logic. Note that it may be invoked asynchronously if the consumers are async.

## Caveats

Any errors thrown by consumers are automatically caught and reported via the
[Browser Console](/devtools-user/browser_console/index.rst).

Async functions are not awaited before invoking other consumers. Note that
rejections (exceptions from async code) are still caught and reported to the
console, and that the async duration of a given consumer will be what
determines the length of the profiler marker, if the publisher asks for profiler
markers.

## Why not just call consumers directly?

There are a number of benefits over direct method calls and module imports.

### Reducing direct dependencies between different parts of the code-base

Code that looks like this:

```
Foo.thingHappened(arg);
Bar.thingHappened(arg);
Baz.thingHappened(arg);
```

is not only repetitive, it also means that the code in question has to directly
import all the modules that provide `Foo`, `Bar` and `Baz`. It means that if
those modules change or move or are refactored, the "publisher" code has to
be updated, with all the added burdens that comes with (potential for merge
conflicts, more automatically added reviewer groups for trivial changes, easy
to miss if dependencies are widespread).

### Avoiding a bootstrap problem in favour of a "just in time" approach

To make sure code is invoked later, when using the observer service, DOM event
listeners, or other mechanisms, it usually needs to add a listener
before the event of interest happens. If not managed carefully, this often leads
to component initialization being front-loaded to make sure not to "miss" it
later. This in turn makes browser startup more heavyweight rather than it needs
to be, because we set up listeners for _everything_, potentially loading entire
JS modules just to do that.

### Unified error-handling, performance inspection, and scheduling

Using the `BrowserUtils.callModulesFromCategory` API allows specifying error
handling, performance profiler markers, and scheduling (use of idle tasks) in
one place. This abstracts away the fact that we never want observers, event
listeners or other mechanisms like this to break and stop notifying (or worse,
propagate an exception themselves) when one of the consumers breaks.

---

### Browser Docs CommandLineParameters (`browser/docs/CommandLineParameters.rst`)

=======================
Command Line Parameters
=======================

Firefox recognizes many (many!) command line parameters.  Overview
documentation of these parameters lives here.

Known parameters
----------------

.. list-table::
   :widths: 20 80
   :header-rows: 1

   * - Parameter
     - Description
   * - ``-osint``
     - On Windows, ``-osint`` serves two purposes.  Most importantly, it signals
       that the command line is untrusted and must be sanitized.  Command lines
       with ``-osint`` are rejected unless they have a very specific structure,
       usually ``firefox.exe -osint -url URL`` or ``firefox.exe -osint
       -private-window URL``: refer to :searchfox:`the EnsureCommandLineSafe function <mozilla-central/rev/ead7da2d9c5400bc7034ff3f06a030531bd7e5b9:toolkit/xre/CmdLineAndEnvUtils.h#196>`.
       These command lines are produced by apps delegating to Firefox, and the
       resulting URL may not be correctly quoted.  The sanitization process
       ensures that maliciously chosen URLs do not add additional parameters to
       Firefox.  Secondarily, the ``-osint`` parameter signals that Firefox is
       being invoked by Windows to handle a URL: generally a registered file
       type, e.g., ``.html``, or protocol, e.g., ``https``.

---

### Browser Docs FrontendCodeReviewBestPractices (`browser/docs/FrontendCodeReviewBestPractices.md`)

# Frontend Code Review Best Practices

## Introduction

Code reviews help ensure that the code solves a specific problem, doesn’t have bugs or regress other functionality, and has adequate test coverage. It also provides an opportunity to ensure correct documentation is added, whether through code comments or documentation of changes. The process of reviewing code also helps spread knowledge about how the code works amongst developers, both as a patch author and as a reviewer.

A review is required before code or tests are added to Mozilla’s repository. Once approved, code is merged to autoland and once tests pass, sheriffs will merge it with other commits to mozilla-central. This guide outlines a set of standards for both patch author and reviewer.

## Intended audience and outcomes

This document is primarily intended for engineers on the Firefox Desktop Front end team. The aim of this guide is to align the team around an agreed set of expectations for patch reviews that will reduce confusion, prevent misunderstandings, help land patches more efficiently and to help onboard new team members.

As an engineer, you’ll be in the position of being both a patch author and a reviewer, so having a good understanding of the expectations of both roles is recommended.

## What is expected from a frontend code review?

The sections below outline some of the high level expectations when reviewing code. See also the [Technologies and Specifics sections for more details on what to look for that are specific to Frontend code](#technologies-and-specifics).

### The basics

A code review and automation will check if this patch:

* applies cleanly to mozilla-central and can be built.
* has a [good commit message](/contributing/contribution_quickref.rst#commit-message) that describes the changes as well as the reason for them where that is not obvious.
  * Adding a longer description in a commit message will be used as the summary in Phabricator.
* fixes the issue at hand.
* has automated test coverage where appropriate. [Exceptions to this are covered by using the test-exception-\* tags in Phabricator](https://firefox-source-docs.mozilla.org/testing/testing-policy/index.html#exceptions). Here are some common exceptions in frontend where \[new\] test coverage isn’t needed:
  * style/image/l10n-only changes
  * Code that interacts directly with the OS in ways we can’t mock in automated tests.
  * Code that requires very specific external circumstances (OS settings, wall clock time, actions by other programs, etc.) we can’t mock reliably.
  * Refactorings of existing code (where existing test coverage exists)
  * Removing code
* passes linting and/or automated tests.

**If any of these is missing/broken, a reviewer is likely to stop then and there.** Before submitting patches, code authors should ensure they have these covered.

### Is this necessary and sufficient?

Two useful ways of looking at patches are “is this necessary?” and “is this sufficient?”:

* **Necessary**: are all the changes in the patch required? It’s common to find other issues when fixing a bug, but code not necessary to fix this specific bug should be moved to a separate bug. Reviewers will usually flag up:
  * Unrelated code changes
  * Changing unrelated whitespace etc. (mind your editor’s autoformat)
  * Unnecessarily complex or hacky fixes
* **Sufficient**: does this fix the issue completely? That is, have we looked at edge cases and is the patch/patchset definitely fixing all of the issue, not just parts of it or a symptom of it?
  * This also means **considering what is not in the patch**. So e.g. when renaming a method, patch authors and reviewers should not just check if all the replacements in the patch are correct, but also if all occurrences were actually touched in the patch (searchfox should make this relatively straightforward, or you can apply the patch locally and use `grep`/`ack`/`ag` etc).

## Expectations for the Reviewer

### Progress > Perfection

As noted above, the context for the patch should be provided by the author, however it’s important to try to strike a balance between ensuring we maintain high standards and being able to make progress. If you identify issues that are routinely cropping up that could be covered by automated linting, please file issues for new rules to be added. This helps us to ensure that the time engineers dedicate to review is primarily spent on efficiently ensuring a change addresses what it sets out to and is both a maintainable and safe addition to Firefox.

### Language and tone in review comments

* Take the time to thank and point out good code changes.
* Focus on the code, not the patch author (avoid wording that sounds like it’s criticizing the author, for example “this doesn’t make sense, why did you do it this way?” versus “I’m curious why you took this approach. Could you please provide some context?”).
* Framing comments as questions rather than statements can help create an environment conducive to collaboration. Rather than “This doesn’t work when `bar` is `undefined`”, “Could you please check if this code is properly handling the case of `bar` being `undefined`?” .
* Using “please” and “what do you think?” goes a long way in making others feel like colleagues, and not subordinates. As a reviewer, double-check your comments. Assume the code author has spent more time thinking about this part of the code than you have and might actually be right, even if you originally thought something was wrong.
* Be clear about what changes are required to be changed in order to land the patch versus those that are optional.
* For things that aren’t [nits](#what-is-a-nit) or trivially understood to be improvements, explain *why* you are requesting a change. Understanding the reasoning behind requested changes helps make sure that you and the patch author share an understanding of what the patch is doing, and helps the patch author learn.
* Minimize the number of passes required for review and addressing review comments. Where possible provide your review comments in a single pass rather than multiple iterations. This helps to reduce the number of cycles needed to get something through review and any associated context switching for both the reviewer and the patch author. In a case where you don't have time for a full review, mention that your review is currently incomplete and set expectations for when it will be so the author can plan accordingly.
* When reviewing code on behalf of additional review groups added to a patch, your review should primarily focus on the areas that the review-group is responsible for or interfaces that your group is using. However, if you do spot a non-trivial issue that falls outside this during review, then it would be reasonable to flag it. .

### Turnaround time for reviews

* Aim for a response within 1 business day. This need not be a full review, but could be a comment setting expectations about when you’ll be able to review the patch, pointing to other folks who might be able to review it sooner or would be more appropriate to review the patch.
* If you’re explicitly asked for review and can’t get to it due to time constraints, it’s always helpful to set expectations for the patch author.

## Expectations for the patch author

### Communication

There is often more than one way to address an issue, and reviewers and patch authors may disagree about the “right” approach to a bug. What is “complex” or “hacky” to one person may be “correctly architectured” or “efficient” to another. If when working on a bug, you’re unsure about what the “right” approach is (e.g. “just add a nullcheck here and move on” vs. “refactor the calling code so we don’t ever pass null”), talk to your prospective reviewer or other people familiar with the code before deciding, to avoid repeated work when your reviewer suggests an alternative, perhaps because they have other context you weren’t aware of, or to fit the general architecture of the component you’re changing.

When you haven’t talked to your reviewer because you think the approach you chose is obviously correct, it is usually still helpful to outline your reasoning/choices in the extended commit message, a phabricator comment, and/or bugzilla. It doesn’t need to be an essay, but ideally the reviewer should be able to understand the patch and its reasoning from reading the patch and commit message.

Make use of the commit message to offer both a brief, and where necessary a longer explanation of what the change is doing. Reviewers often review dozens of patches each week. Ensuring that the patch contains all the information they need to review the change helps speed up reviews and avoids confusion about what a patch is trying to achieve.

If the patch needs a shorter turnaround time of the review cycle due to a release or uplift deadline (which should also be reflected in the bug priority and severity that’s been set), you should ping blocking reviewers on slack or matrix to raise awareness of this deadline and to confirm they can review your patch as soon as possible. If they are unable to do so, you’ll need to find another reviewer who can. Where possible ask the existing reviewer for a suggestion, or ask someone else in the same review group. If that’s not possible, ask for input from your team/project lead or manager.

When making changes to revisions, using the ‘plan-changes’ action in Phabricator [“removes revisions from reviewers’ queues, meaning that they will no longer be visible under “Ready to Review” on their “Active Revisions” dashboards, until a new diff is uploaded”](https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html#other-revision-actions)

When making non-trivial changes to patches which are already on Phabricator, use `--message` (or `-m`) with your `moz-phab` submission to explain what you’re changing.

Leave questions or comments in Phabricator about things you were not sure about. Your reviewer might be able to offer answers, or you might have stumbled on deeper underlying problems that need addressing elsewhere. Either way, everyone learns.

### Addressing review comments

Except for very small patches it is extremely common for a reviewer to request changes to a patch after their first review. Reviewers are expected to be courteous and clear about what they’re asking you to change and why. While reviewers *do* have the final sign-off, code review should be considered to be a conversation. Reviewers are not expected to be perfect. If you don’t understand what a reviewer has asked or disagree with their suggestions then respond with your reasoning or ask for clarification. Usually this happens in the code review itself but it is not uncommon to talk with the reviewer directly where that is faster. In this case it is helpful to add a summary of your discussion to the review comment in Phabricator for future code historians.

If you have requested reviews from multiple reviewers and one of them requests changes, the patch is removed from all reviewers' queues until you re-submit the patch with the requested changes, questions for clarification or comments.

Once you’ve addressed everything the reviewer requested, push your patch up for review again and expect that the reviewer will be verifying that you changed everything requested. To help save unnecessary review iterations, where possible avoid putting the patch back into review until you've made all the necessary changes.

Occasionally the reviewer may ask for a small number of changes but still approve the patch. You are expected to make those changes before the patch can land, the reviewer is just indicating that they trust you to make those changes and don’t need to re-review the patch. If those changes turn out to be larger than the reviewer would have reasonably expected then you should re-request review.

You’re within your rights to suggest that some review feedback can be fixed in follow-up bugs and patches, so long as you ensure to get those follow-ups filed in Bugzilla and that they’re addressed in a timely manner. This is particularly true for in-progress features that are being held to Nightly. Features still being developed and held to Nightly should not be expected to land in a perfect state all in one patch.

### Code quality

Make sure before submitting a patch that it compiles cleanly and that the tests included all pass.

Consider re-reading the patch you’ve just submitted to Phabricator once you submit it the first time. Often Phabricator’s clear diff view will highlight things to you that you might have missed, especially if you’ve worked on the patch a long time. It can also help highlight changes that aren’t immediately obvious to someone reading the patch for the first time, and might need an explanation.

Avoid whitespace or other trivial changes to code that you don’t need to change to accomplish your goal. Making other, unrelated changes makes the patch harder to review, and makes it difficult to later to find the origin of a change.

Several small patches are easier to review than one monolith that changes lots of files.

Talk to your peers and prospective reviewer(s) before starting big refactors. Firefox’s code base is huge and refactors carry risk, so reviewers are wary of big changes like that and they are usually difficult to review.

## Technologies and Specifics

This section covers some frontend-specific aspects of patches that reviewers are likely to look at.

### JS/DOM

* Use existing components to implement feature designs. Do not reimplement custom button/card/toggle/… styling based on the design and vanilla HTML, as it doesn’t scale, is hard to maintain, and will likely miss edge-cases for accessibility, RTL, etc.
  * The inverse is also true: not every new bit of code you work on has to be factored out as a generic, reusable component immediately. When you are the first/only consumer of a bit of code, it is usually not possible to predict what aspects of your code will need to be “generic”, where API boundaries should be, and so on. Trying to do it immediately is doomed to failure, so don’t spend time on it - save it for when the second potential consumer comes along.
* Lines of code is a flawed metric, and we’re not code golfing - but don’t write several 10-line functions when 2 lines of inline code will do. Balance brevity and readability appropriately.
* Use DOM properties over attributes where possible.
  * Where it isn’t, `toggleAttribute` and `classList.toggle` are often helpful to avoid repetitive if/else blocks.

### Styling and CSS, and SVGs

* Use existing components/classes to implement feature designs (see JS/DOM section).
* Keep in mind all CSS needs to work in RTL languages. Use logical properties (`margin-inline-start` and friends) rather than physical ones (`margin-left`).
  * See [Firefox RTL (right-to-left) guidelines](/code-quality/coding-style/rtl_guidelines.rst) for more detailed information.
* See the [Accessibility](#accessibility) section on use of colours, HCM, etc.
* See detailed [CSS authoring guidelines](/code-quality/coding-style/css_guidelines.rst).
* See the [Firefox SVG Guidelines](/code-quality/coding-style/svg_guidelines.rst).

### Localization

* For anything user-facing, use localised strings. **Do NOT** hardcode English strings in markup.
* For new code, use fluent. For modifying older code, use what the old code uses (but consider switching to fluent if it’s straightforward, as it provides better translation primitives in other languages).
* When writing experimental features that need strings for en-US only that are not final yet, use fluent and put the ftl file in a `content` rather than `locale` directory and package it accordingly. When strings are final, move them to a regular `locale` directory and include them as normal but make sure to do so outside string freeze and while allowing reasonable time for our (largely volunteer) localisers to submit translations - don’t just dump dozens of strings into `locale` a day before string freeze.
* If the meaning of a string changes, or \[in fluent\] you add/remove attributes, **you must update the message identifier**.
* More detailed [fluent review guidelines](/l10n/fluent/review.rst#guidelines-for-fluent-reviewers) are available separately.

### Accessibility {#accessibility}

* Write semantic HTML.
* Anything mouse-accessible should be keyboard-accessible or have a keyboard-accessible equivalent.
* Ensure things work in high contrast mode and that there is sufficient colour contrast between foreground and background items in non-high-contrast mode and with different themes.
* Any images that **aren’t purely decorative** (e.g. toolbar button icons where there is no visible text label) need an `alt` attribute or `aria-label` or similar to give it an accessible name, as well as a tooltip for sighted users who might not understand icons.
* Any images that **are** purely **decorative** (e.g. illustrations next to text) should be implemented using one of these options:
  * CSS background images, which have no representation in the accessibility tree
  * HTML `img` elements that use `role=presentation` to remove them from the accessibility tree, and do not have an alt attribute.
* If implementing animations or transitions, do so behind a `prefers-reduced-motion` media query to ensure people who have epilepsy or other motion-triggered sensitivities are not hurt by our attempts to make things beautiful.
* The first rule of ARIA is “don’t use ARIA” (see also “Write semantic HTML”) - but it can be a tool where semantic markup is insufficient (e.g. live regions, complex labeling structures).

### Performance

* Avoid [style](https://firefox-source-docs.mozilla.org/performance/bestpractices.html#detecting-and-avoiding-synchronous-style-flushes) and [layout](https://firefox-source-docs.mozilla.org/performance/bestpractices.html#detecting-and-avoiding-synchronous-reflow) flushes.
* Use `requestIdleCallback` and/or workers for anything on the startup path and/or CPU or disk-intensive work that doesn’t actually need to happen immediately.
* Use `IOUtils` to do async File IO, rather than nsIFile for synchronous access.
* Keep complexity in mind and use reasonable data structures
  * e.g. use a Set rather than arrays if they’re big, unordered, and you need to look items up in the collection
  * Bear in mind that some collections/loops may be reasonably sized in the common case, but have pathological edge cases (that person with 3652 tabs is looking at you. You know who I mean\!). You shouldn’t need to jump through too many hoops, but use memoization or association (which are O(1) or O(log n)) rather than “just” looping through the list (which is O(n)).
* Other than that, don’t over-optimize things unless the code is known to be hot/performance-sensitive.
  * As an example, we don’t, as a rule, use `for (var i; i < ary.length; i++)` style “raw” array loops, instead preferring the more readable `for (let item of ary)`, even though that is slightly less performant.

### Security

* When in doubt, ask the security team, and/or `#security` on slack.
* Take care when communicating between processes or with web content. Specifically:
  * We can’t trust web content.
  * We can’t trust web content processes (!). Any information you get via IPC (JSActor messages or similar) could be completely bogus. Use information from the parent process (the CanonicalBrowsingContext and so on) to make security decisions wherever possible.
  * As a corollary, if you have code that wants to navigate or interact with web content, do it entirely within the content process, rather than passing e.g. URIs or similar information to the parent and expecting it to navigate for you. This avoids exposing APIs to (potentially compromised) content processes that let them navigate arbitrarily - the “basic” APIs for that (`document.location` and so on) will be secured by Gecko itself, and we want to reuse that infrastructure as much as possible.
  * Do not load untrusted content (ie content from the web) in the parent process.
* XSS and markup related advice:
  * Avoid inline event handlers wherever possible.
  * All `about:` pages must have a Content Security Policy (CSP). Use one that prevents inline styles and inline script.
  * Do not use `innerHTML`.
  * Gecko has built in sanitizer APIs - if you have to deal with untrusted HTML, see [nsIParserUtils](https://searchfox.org/firefox-main/source/parser/html/nsIParserUtils.idl). Do NOT hand-roll sanitizing inputs.
* Other vectors to take into account:
  * URLs are malleable and not a good way of identifying an origin. Use nsIPrincipal objects. You’ll need this to deal correctly with `blob` URIs, `about:blank`, and data URIs.
  * We can’t assume that for `something.foo.sometld`, `something` is a subdomain of `foo`, or that `foo.sometld` is the “top” domain. Some TLDs (`.co.uk` and `.org.uk` and so on are an obvious example, but `github.io` and `s3.dualstack.ap-northeast-1.amazonaws.com`, too\!) have individually controlled subdomains. Use [nsIEffectiveTLDService](https://searchfox.org/firefox-main/source/netwerk/dns/nsIEffectiveTLDService.idl) to work out what the “top” domain is. Do not use manual string manipulation.
  * Spoofing: where an attacker tries to pretend to the user they’re on a different website, usually by overlaying content or markup over the address bar or other trusted UI, or using full screen or similar tricks.
  * Clickjacking/keyjacking: where an attacker encourages users to click or hit keys repeatedly (“win $50 if you [hook a duck](https://en.wikipedia.org/wiki/Hook-a-duck) by clicking this button really fast”), and uses that to bypass security warnings. Typical defence: delay enabling buttons on security-critical dialogs - there’s even a [helper](https://searchfox.org/mozilla-central/rev/d00845a44a8d1bf3f472ff36fd3f22a03af30a76/toolkit/components/prompts/src/PromptUtils.sys.mjs#49-61) for this.
  * Crypto: do not make up your own cryptography, random number generator, password/key management or similar. Talk to experts (some of them work at Mozilla)\!

### Testing

* All patches must have automated tests where possible and practical.
  * When writing tests, be sure to see that you’ve seen your test fail. This helps to avoid scenarios where a test always passes even when it shouldn’t.
  * There are some patches where it may be appropriate not to have tests, particularly ones that only touch documentation, styling (CSS/images), or test-only changes.
  * For situations where you can’t write tests, such as with features that interact with the operating system in ways we can’t verify automatically, leave a comment explaining why to the reviewer. It is likely going to be the first question they ask and they should know when one of these situations applies or may know alternate ways to write the test.
* If you’ve pushed to try, leaving a link to the try push on Phabricator can help avoid duplicating effort (Note: reviewers are not expected to create try pushes by default). If there are unclear test failures that may or may not be intermittent, your reviewer can help work out what is happening.

### Documentation

* Ideally, code should be readable without explanation. Where documentation is required, use code comments for individual pieces of code, and the extended commit message (i.e. the second/third/nth lines of the commit message) to describe the high-level goal of your change.
* A guideline for code comments is to add them in cases where they provide additional context for *why* a change is being made, but to avoid adding them if the comment only restates *what* the code is doing.
* If the reviewer asks for explanations, this is often a sign that the code should be simplified, it needs more code comments, or the approach in the patch is not right. Prefer code and/or comment changes over communicating only in Phabricator - so that future readers of the code have the same context.
* Ensure that any existing Firefox Source Docs material is also updated to reflect the change.

## Commandeering patches

Patches should only be commandeered by agreement with the original patch author or if the author cannot be expected to respond in a timely fashion (on vacation or sick leave or no longer active in the project).

If you do need to commandeer a patch you can preserve the original author with `git commit --amend --author="Other Person <person@mozilla.com>"` when amending the original commit.

## Community Participation Guidelines

Please remember to always abide by [the Community Participation Guidelines](https://www.mozilla.org/en-US/about/governance/policies/participation/).

Be generous and inclusive. Always assume good intentions, even where there is a disagreement during the course of the review.

## FAQ

### What is a Nit?

A nit is a minor defect. This could be a typo or a small issue. These are usually the kind of things that would *not result in a “request for changes”*, but they should be called out and it’s expected that they would be addressed by the patch author before the patch lands.

### How do I file a bug for new lint rules?

[If you have an idea for an eslint (JS) or stylelint (CSS) rule you can file a bug here](https://bugzilla.mozilla.org/enter_bug.cgi?product=Developer%20Infrastructure&component=Lint%20and%20Formatting) if a more specific component isn’t a better fit.

## Further Reading

* [Code review antipatterns](https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/code-review-antipatterns/) an article by Simon Tatham outlining common anti-patterns in code review.

---

### Browser Docs Index (`browser/docs/index.rst`)

=================
Firefox Front-end
=================

This is the documentation for the code powering the Firefox Desktop front-end.

.. toctree::
   :maxdepth: 2

   how_to/index
   urlbar/index
   BrowserUsageTelemetry
   FrontendCodeReviewBestPractices
   CommandLineParameters
   BrowserStartup
   CategoryManagerIndirection
   components/customizableui/docs/index
   components/enterprisepolicies/docs/index
   components/taskbartabs/docs/index
   extensions/formautofill/docs/index
   extensions/newtab/docs/index
   components/aboutwelcome/docs/index
   installer/windows/installer/index
   components/attribution/docs/index
   /toolkit/mozapps/defaultagent/default-browser-agent/index
   components/migration/docs/index
   components/pagedata/docs/index
   places/index
   components/asrouter/docs/index
   search/index
   base/tabbrowser/index
   touchbar/index
   components/uitour/docs/index
   branding/docs/index
   components/storybook/docs/README.storybook.stories
   components/storybook/docs/README.reusable-widgets.stories
   components/storybook/docs/README.other-widgets.stories
   components/storybook/docs/README.lit-guide.stories
   components/storybook/docs/README.xul-and-html.stories
   components/storybook/docs/README.figma-code-connect.stories
   /toolkit/themes/shared/design-system/docs/README.design-tokens.stories
   components/backup/docs/index
   components/sidebar/docs/index
   components/mozcachedohttp/docs/index

---

### Browser Docs Overview (`browser/docs/overview.rst`)

Firefox for Desktop
===================

Desktop architecture
--------------------

One of the keys to understanding how Firefox is architected is to know that Gecko is used to render
both web content as well as the UI of the browser. This means that, to a large extent, the UI of
Firefox is made using web technologies like HTML, CSS, and JavaScript. For example, the document
``chrome://browser/content/browser.xhtml`` is the markup for a single Firefox browser window. You
can think of it almost like index.html for a webpage.

The decision to use Gecko for rendering the UI was made during an era when HTML was not yet
expressive enough or sufficient to build desktop UIs. A different markup language,
`XUL <https://en.wikipedia.org/wiki/XUL>`_, was developed for that purpose instead, which Gecko also
knows how to interpret. Since that time, HTML and CSS has evolved to the point where XUL is not
strictly necessary for most use-cases. Where possible, we have been gradually migrating our UI to
use less XUL and more standard HTML and CSS.

Reusable UI Widgets
-------------------

Many of the UI widgets in use in the user interface are built as web components that can be reused.

:ref:`Read more <Reusable UI widgets>`

Tabbrowser
----------

The tabbrowser component manages the tabs in a browser window.

:ref:`Read more <tabbrowser>`

Address Bar
-----------

The address bar (varyingly also referred to as the Awesome Bar, or Quantum Bar) handles users
entering web addresses including a popup with suggestions from various sources including history,
bookmarks and search engines.

:ref:`Read more <Address Bar>`

Search
------

The search service manages the list of search engines available in the address bar.

:ref:`Read more <Search>`

Places
------

The places component includes the database that stores history and bookmarks as well as a set of UI
components that present those to the user.

:ref:`Read more <Places>`

Firefox Sync and Application Services
-------------------------------------

Application services includes the sync engines and Firefox Accounts integration.

:ref:`Read more <Services>`

Developer Tools
---------------

The developer tools support web developers when building webpages but as the Firefox UI is itself
built using web technologies it is also possible to use the developer tools to debug the Firefox UI.

:ref:`Read more <Firefox DevTools Contributor Docs>`

Browser Toolbox
###############

The Browser Toolbox is a way to launch the developer tools in a separate process so that they can be
used to debug the main browser UI.

:ref:`Read more <Browser Toolbox>`

Profiler
########

The Firefox Profiler is the way to measure the performance of your code. Go to
`profiler.firefox.com <https://profiler.firefox.com>`__ to enable the button in Firefox and record a
performance profile. These profiles can be uploaded and shared. It can identify slow parts of the
code, and reveal the underlying behavior of how code runs.

Installer
---------

The Windows installer for Firefox is built with NSIS. There are currently no installers for other
operating systems.

:ref:`Read more <Installer>`

Application Update
------------------

Application Update is responsible for requesting available updates from the update servers,
downloading them, verifying their integrity and then ultimately installing them. A binary patch tool
(bsdiff) is used to reduce the size of update files and update files are delivered in the
bespoke mar (Mozilla ARchive) format.

:ref:`Read more <Application Update>`

---

### Build Docs Build Overview (`build/docs/build-overview.rst`)

.. _build_overview:

=====================
Build System Overview
=====================

This document provides an overview on how the build system works. It is
targeted at people wanting to learn about internals of the build system.
It is not meant for persons who casually interact with the build system.
That being said, knowledge empowers, so consider reading on.

The build system is composed of many different components working in
harmony to build the source tree. We begin with a graphic overview.

.. graphviz::

   digraph build_components {
      rankdir="LR";
      "configure" -> "config.status" -> "build backend" -> "build output"
   }

Phase 1: Configuration
======================

Phase 1 centers around the ``configure`` script, which is a bash shell script.
The file is generated from a file called ``configure.in`` which is written in M4
and processed using Autoconf 2.13 to create the final configure script.
You don't have to worry about how you obtain a ``configure`` file: the build
system does this for you.

The primary job of ``configure`` is to determine characteristics of the system
and compiler, apply options passed into it, and validate everything looks OK to
build. The primary output of the ``configure`` script is an executable file
in the object directory called ``config.status``. ``configure`` also produces
some additional files (like ``autoconf.mk``). However, the most important file
in terms of architecture is ``config.status``.

The existence of a ``config.status`` file may be familiar to those who have worked
with Autoconf before. However, Mozilla's ``config.status`` is different from almost
any other ``config.status`` you've ever seen: it's written in Python! Instead of
having our ``configure`` script produce a shell script, we have it generating
Python.

Now is as good a time as any to mention that Python is prevalent in our build
system. If we need to write code for the build system, we do it in Python.
That's just how we roll. For more, see :ref:`python`.

``config.status`` contains 2 parts: data structures representing the output of
``configure`` and a command-line interface for preparing/configuring/generating
an appropriate build backend. (A build backend is merely a tool used to build
the tree - like GNU Make or Tup). These data structures essentially describe
the current state of the system and what the existing build configuration looks
like. For example, it defines which compiler to use, how to invoke it, which
application features are enabled, etc. You are encouraged to open up
``config.status`` to have a look for yourself!

Once we have emitted a ``config.status`` file, we pass into the realm of
phase 2.

Phase 2: Build Backend Preparation and the Build Definition
===========================================================

Once ``configure`` has determined what the current build configuration is,
we need to apply this to the source tree so we can actually build.

What essentially happens is the automatically-produced ``config.status`` Python
script is executed as soon as ``configure`` has generated it. ``config.status``
is charged with the task of tell a tool how to build the tree. To do this,
``config.status`` must first scan the build system definition.

The build system definition consists of various ``moz.build`` files in the tree.
There is roughly one ``moz.build`` file per directory or per set of related directories.
Each ``moz.build`` files defines how its part of the build config works. For
example it says *I want these C++ files compiled* or *look for additional
information in these directories.* config.status starts with the ``moz.build``
file from the root directory and then descends into referenced ``moz.build``
files by following ``DIRS`` variables or similar.

As the ``moz.build`` files are read, data structures describing the overall
build system definition are emitted. These data structures are then fed into a
build backend, which then performs actions, such as writing out files to
be read by a build tool. e.g. a ``make`` backend will write a
``Makefile``.

When ``config.status`` runs, you'll see the following output::

   Reticulating splines...
   Finished reading 1096 moz.build files into 1276 descriptors in 2.40s
   Backend executed in 2.39s
   2188 total backend files. 0 created; 1 updated; 2187 unchanged
   Total wall time: 5.03s; CPU time: 3.79s; Efficiency: 75%

What this is saying is that a total of *1096* ``moz.build`` files were read.
Altogether, *1276* data structures describing the build configuration were
derived from them.  It took *2.40s* wall time to just read these files and
produce the data structures.  The *1276* data structures were fed into the
build backend which then determined it had to manage *2188* files derived
from those data structures. Most of them already existed and didn't need
changed. However, *1* was updated as a result of the new configuration.
The whole process took *5.03s*. Although, only *3.79s* was in
CPU time. That likely means we spent roughly *25%* of the time waiting on
I/O.

For more on how ``moz.build`` files work, see :ref:`mozbuild-files`.

Phase 3: Invocation of the Build Backend
========================================

When most people think of the build system, they think of phase 3. This is
where we take all the code in the tree and produce Firefox or whatever
application you are creating. Phase 3 effectively takes whatever was
generated by phase 2 and runs it. Since the dawn of Mozilla, this has been
make consuming Makefiles. However, with the transition to moz.build files,
you may soon see non-Make build backends, such as Tup or Visual Studio.

When building the tree, most of the time is spent in phase 3. This is when
header files are installed, C++ files are compiled, files are preprocessed, etc.

---

### Build Docs Build Targets (`build/docs/build-targets.rst`)

.. _build_targets:

=============
Build Targets
=============

When you build with ``mach build``, there are some special targets that can be
built. This page attempts to document them.

Partial Tree Targets
====================

The targets in this section only build part of the tree. Please note that
partial tree builds can be unreliable. Use at your own risk.

export
   Build the *export* tier. The *export* tier builds everything that is
   required for C/C++ compilation. It stages all header files, processes
   IDLs, etc.

compile
   Build the *compile* tier. The *compile* tier compiles all C/C++ files.

libs
   Build the *libs* tier. The *libs* tier performs linking and performs
   most build steps which aren't related to compilation.

tools
   Build the *tools* tier. The *tools* tier mostly deals with supplementary
   tools and compiled tests. It will link tools against libXUL, including
   compiled test binaries.

binaries:
   Recompiles and relinks C/C++ files. Only works after a complete normal
   build, but allows for much faster rebuilds of C/C++ code. For performance
   reasons, however, it skips nss, nspr, icu and ffi. This is targeted to
   improve local developer workflow when touching C/C++ code.

install-manifests
   Process install manifests. Install manifests handle the installation of
   files into the object directory.

   Unless ``NO_REMOVE=1`` is defined in the environment, files not accounted
   in the install manifests will be deleted from the object directory.

install-tests
   Processes the tests install manifest.

Common Actions
==============

The targets in this section correspond to common build-related actions. Many
of the actions in this section are effectively frontends to shell scripts.
These actions will likely all be replaced by mach commands someday.

buildsymbols
   Create a symbols archive for the current build.

   This must be performed after a successful build.

check
   Run build system tests.

---

### Build Docs Chrome Registration (`build/docs/chrome-registration.rst`)

Chrome Registration
-------------------

What is chrome?
---------------

`Chrome` is the set of user interface elements of the
application window that are outside the window's content area. Toolbars,
menu bars, progress bars, and window title bars are all examples of
elements that are typically part of the chrome.

``chrome.manifest`` files are used to register XPCOM components and sources for the chrome protocol.
Every application supplies a root ``chrome.manifest`` file that Mozilla reads on startup.

Chrome providers
----------------

A supplier of chrome for a given window type (e.g., for the browser
window) is called a chrome provider. The providers work together to
supply a complete set of chrome for a particular window, from the images
on the toolbar buttons to the files that describe the text, content, and
appearance of the window itself.

There are three basic types of chrome providers:

Content
   The main source file for a window description comes from the content
   provider, and it can be any file type viewable from within Mozilla.
   It will typically be a XUL file, since XUL is designed for describing
   the contents of windows and dialogs. The JavaScript files that define
   the user interface are also contained within the content packages.

Locale
   Localizable applications keep all their localized information in
   locale providers and Fluent FTL files, which are handled separately.
   This allows translators to plug in a different
   chrome package to translate an application without altering the rest
   of the source code. In a chrome provider, localizable files are mostly
   Java-style properties files.
Skin
   A skin provider is responsible for providing a complete set of files
   that describe the visual appearance of the chrome. Typically a skin
   provider will provide CSS files and
   images.

The chrome registry
-------------------

The Gecko runtime maintains a service known as the chrome registry that
provides mappings from chrome package names to the physical location of
chrome packages on disk.

This chrome registry is configurable and persistent, and thus a user can
install different chrome providers, and select a preferred skin and
locale. This is accomplished through xpinstall and the extension
manager.

In order to inform the chrome registry of the available chrome, a text
manifest is used: this manifest is "chrome.manifest" in the root of an
extension, or theme, or XULRunner application.

The plaintext chrome manifests are in a simple line-based format. Each
line is parsed individually; if the line is parsable the chrome registry
takes the action identified by that line, otherwise the chrome registry
ignores that line (and prints a warning message in the runtime error
console).

.. code:: text

   locale packagename localename path/to/files
   skin packagename skinname path/to/files

.. note::

   The characters @ # ; : ? / are not allowed in the
   packagename.

Manifest instructions
---------------------

comments
~~~~~~~~

.. code:: text

   # this line is a comment - you can put here whatever you want

A line is a comment if it begins with the character '#'. Any following
character in the same line is ignored.

manifest
~~~~~~~~

::

   manifest subdirectory/foo.manifest [flags]

This will load a secondary manifest file. This can be useful for
separating component and chrome registration instructions, or separate
platform-specific registration data.

component
~~~~~~~~~

::

   component {00000000-0000-0000-0000-000000000000} components/mycomponent.js [flags]

Informs Mozilla about a component CID implemented by an XPCOM component
implemented in JavaScript (or another scripting language, if
applicable). The ClassID {0000...} must match the ClassID implemented by
the component. To generate a unique ClassID, use a UUID generator
program or site.

contract
~~~~~~~~

::

   contract @foobar/mycontract;1 {00000000-0000-0000-0000-000000000000} [flags]

Maps a contract ID (a readable string) to the ClassID for a specific
implementation. Typically a contract ID will be paired with a component
entry immediately preceding.

category
~~~~~~~~

::

   category category entry-name value [flags]

Registers an entry in the `category manager`. The
specific format and meaning of category entries depend on the category.

content
~~~~~~~

A content package is registered with the line:

::

   content packagename uri/to/files/ [flags]

This will register a location to use when resolving the URI
``chrome://packagename/content/...``. The URI may be absolute or
relative to the location of the manifest file. Note: it must end with a
'/'.

locale
~~~~~~

A locale package is registered with the line:

.. code:: text

   locale packagename localename uri/to/files/ [flags]

This will register a locale package when resolving the URI
chrome://*packagename*/locale/... . The *localename* is usually a plain
language identifier "en" or a language-country identifier "en-US". If
more than one locale is registered for a package, the chrome registry
will select the best-fit locale using the user's preferences.

skin
~~~~

A skin package is registered with the line:

.. code:: text

   skin packagename skinname uri/to/files/ [flags]

This will register a skin package when resolving the URI
chrome://packagename/skin/... . The *skinname* is an opaque string
identifying an installed skin. If more than one skin is registered for a
package, the chrome registry will select the best-fit skin using the
user's preferences.

style
~~~~~

Style overlays (custom CSS which will be applied to a chrome page) are
registered with the following syntax:

.. code:: text

   style chrome://URI-to-style chrome://stylesheet-URI [flags]

override
~~~~~~~~

In some cases an extension or embedder may wish to override a chrome
file provided by the application or XULRunner. In order to allow for
this, the chrome registration manifest allows for "override"
instructions:

.. code:: text

   override chrome://package/type/original-uri.whatever new-resolved-URI [flags]

Note: overrides are not recursive (so overriding
chrome://foo/content/bar/ with file:///home/john/blah/ will not usually
do what you want or expect it to do). Also, the path inside overridden
files is relative to the overridden path, not the original one (this can
be annoying and/or useful in CSS files, for example).

.. _chrome_manifest_resource:

resource
~~~~~~~~

Aliases can be created using the ``resource`` instruction:

.. code:: text

   resource aliasname uri/to/files/ [flags]

This will create a mapping for ``resource://<aliasname>/`` URIs to the
path given.

.. note::

   **Note:** There are no security restrictions preventing web content
   from including content at resource: URIs, so take care what you make
   visible there.

Manifest flags
--------------

Manifest lines can have multiple, space-delimited flags added at the end
of the registration line. These flags mark special attributes of chrome
in that package, or limit the conditions under which the line is used.

application
~~~~~~~~~~~

Extensions may install into multiple applications. There may be chrome
registration lines which only apply to one particular application. The
flag

.. code:: text

   application=app-ID

indicates that the instruction should only be applied if the extension
is installed into the application identified by *app-ID*. Multiple
application flags may be included on a single line, in which case the
line is applied if any of the flags match.

This example shows how a different overlay can be used for different
applications:

::

   overlay chrome://browser/content/browser.xul chrome://myaddon/content/ffOverlay.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
   overlay chrome://messenger/content/mailWindowOverlay.xul chrome://myaddon/content/tbOverlay.xul application={3550f703-e582-4d05-9a08-453d09bdfdc6}
   overlay chrome://songbird/content/xul/layoutBaseOverlay.xul chrome://myaddon/content/sbOverlay.xul application=songbird@songbirdnest.com

appversion
~~~~~~~~~~

Extensions may install into multiple versions of an application. There
may be chrome registration lines which only apply to a particular
application version. The flag

.. code:: text

   appversion=version
   appversion<version
   appversion<=version
   appversion>version
   appversion>=version

indicates that the instruction should only be applied if the extension
is installed into the application version identified. Multiple
``appversion`` flags may be included on a single line, in which case the
line is applied if any of the flags match. The version string must
conform to the `Toolkit version format`.

platformversion
~~~~~~~~~~~~~~~

When supporting more then one application, it is often more convenient
for an extension to specify which Gecko version it is compatible with.
This is particularly true for binary components. If there are chrome
registration lines which only apply to a particular Gecko version, the
flag

.. code:: text

   platformversion=version
   platformversion<version
   platformversion<=version
   platformversion>version
   platformversion>=version

indicates that the instruction should only be applied if the extension
is installed into an application using the Gecko version identified.
Multiple ``platformversion`` flags may be included on a single line, in
which case the line is applied if any of the flags match.

contentaccessible
~~~~~~~~~~~~~~~~~

Chrome resources can no longer be referenced from within <img>,
<script>, or other elements contained in, or added to, content that was
loaded from an untrusted source. This restriction applies to both
elements defined by the untrusted source and to elements added by
trusted extensions. If such references need to be explicitly allowed,
set the ``contentaccessible`` flag to ``yes`` to obtain the behavior
found in older versions of Firefox. See
`bug 436989 <https://bugzilla.mozilla.org/show_bug.cgi?id=436989>`__.

The ``contentaccessible`` flag applies only to content packages: it is
not recognized for locale or skin registration. However, the matching
locale and skin packages will also be exposed to content.

**n.b.:** Because older versions of Firefox do not understand the
``contentaccessible`` flag, any extension designed to work with both
Firefox 3 and older versions of Firefox will need to provide a fallback.
For example:

::

   content packagename chrome/path/
   content packagename chrome/path/ contentaccessible=yes

os
~~

Extensions (or themes) may offer different features depending on the
operating system on which Firefox is running. The value is compared to
the value of `OS_TARGET` for the platform.

.. code:: text

   os=WINNT
   os=Darwin

osversion
~~~~~~~~~

An extension or theme may need to operate differently depending on which
version of an operating system is running. For example, a theme may wish
to adopt a different look on Mac OS X 10.5 than 10.4:

.. code:: text

   osversion>=10.5

abi
~~~

If a component is only compatible with a particular ABI, it can specify
which ABI/OS by using this directive. The value is taken from the
`nsIXULRuntime` OS and
XPCOMABI values (concatenated with an underscore). For example:

::

   binary-component component/myLib.dll abi=WINNT_x86-MSVC
   binary-component component/myLib.so abi=Linux_x86-gcc3

platform (Platform-specific packages)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Some packages are marked with a special flag indicating that they are
platform specific. Some parts of content, skin, and locales may be
different based on the platform being run. These packages contain three
different sets of files, for Windows and OS/2, Macintosh, and Unix-like
platforms. For example, the order of the "OK" and "Cancel" buttons in a
dialog is different, as well as the names of some items.

The "platform" modifier is only parsed for content registration; it is
not recognized for locale or skin registration. However, it applies to
content, locale, and skin parts of the package, when specified.

process
~~~~~~~

In electrolysis registrations can be set to only apply in either the
main process or any content processes. The "process" flag selects
between these two. This can allow you to register different components
for the same contract ID or ensure a component can only be loaded in the
main process.

::

   component {09543782-22b1-4a0b-ba07-9134365776ee} maincomponent.js process=main
   component {98309951-ac89-4642-afea-7b2b6216bcef} contentcomponent.js process=content

Example chrome manifest
-----------------------

.. list-table::
   :widths: 20 20 20 20


   *  - type
      - engine
      - language
      - url
   *  - content
      - branding
      - browser/content/branding/
      - contentaccessible=yes
   *  - content
      - browser
      - browser/content/browser/
      - contentaccessible=yes
   *  - override
      -
      - chrome://global/content/license.html
      - chrome://browser/content/license.html
   *  - resource
      - payments
      - browser/res/payments/
      -
   *  - skin
      - browser
      - classic/1.0 browser/skin/classic/browser/
      -
   *  - locale
      - branding
      - en-US
      - en-US/locale/branding/
   *  - locale
      - browser
      - en-US
      - en-US/locale/browser/
   *  - locale
      - browser-region
      - en-US
      - en-US/locale/browser-region/

---

### Build Docs Cppeclipse (`build/docs/cppeclipse.rst`)

.. _build_cppeclipse:

=====================
Cpp Eclipse Projects
=====================

For additional information on using Eclipse CDT see
`the MDN page
<https://developer.mozilla.org/en-US/docs/Eclipse_CDT>`_.

The build system contains alpha support for generating C++ Eclipse
project files to aid with development.

Please report bugs to bugzilla and make them depend on bug 973770.

To generate a C++ Eclipse project files, you'll need to have a fully
built tree::

   mach build

Then, simply generate the C++ Eclipse build backend::

   mach build-backend -b CppEclipse

If all goes well, the path to the generated workspace should be
printed.

To use the generated C++ Eclipse project files, you'll need to
have a Eclipse CDT 8.3 (We plan to follow the latest Eclipse release)
`Eclipse CDT plugin
<https://www.eclipse.org/cdt/>`_
installed. You can then import all the projects into Eclipse using
*File > Import ... > General > Existing Projects into Workspace*
-only- if you have not ran the background indexer.

Updating Project Files
======================

As you pull and update the source tree, your C++ Eclipse files may
fall out of sync with the build configuration. The tree should still
build fine from within Eclipse, but source files may be missing and in
rare circumstances Eclipse's index may not have the proper build
configuration.

To account for this, you'll want to periodically regenerate the
C++ Eclipse project files. You can do this by running ``mach build
&& mach build-backend -b CppEclipse`` from the
command line.

Currently, regeneration rewrites the original project files. **If
you've made any customizations to the projects, they will likely get
overwritten.** We would like to improve this user experience in the
future.

---

### Build Docs Cross Compile (`build/docs/cross-compile.rst`)

=================
Cross-compilation
=================

If you are planning to perform cross-compilation e.g. for Linux/Aarch64, you
will probably want to use experimental feature ``--enable-bootstrap`` in your
``.mozconfig``. Then, you just have to specify the the target arch, after which
the build system will automatically set up the sysroot.

For example, cross-compiling for Linux/Aarch64:

.. code-block:: text

    ac_add_options --target=aarch64-linux-gnu
    ac_add_options --enable-bootstrap

---

### Build Docs Defining Binaries (`build/docs/defining-binaries.rst`)

.. _defining_binaries:

======================================
Defining Binaries for the Build System
======================================

One part of what the build system does is compile C/C++ and link the resulting
objects to produce executables and/or libraries. This document describes the
basics of defining what is going to be built and how. All the following
describes constructs to use in moz.build files.


Source files
============

Source files to be used in a given directory are registered in the ``SOURCES``
and ``UNIFIED_SOURCES`` variables. ``UNIFIED_SOURCES`` have a special behavior
in that they are aggregated by batches of 16, requiring, for example, that there
are no conflicting variables in those source files.

``SOURCES`` and ``UNIFIED_SOURCES`` are lists which must be appended to, and
each append requires the given list to be alphanumerically ordered.

.. code-block:: python

   UNIFIED_SOURCES += [
       'FirstSource.cpp',
       'SecondSource.cpp',
       'ThirdSource.cpp',
   ]

   SOURCES += [
       'OtherSource.cpp',
   ]

``SOURCES`` and ``UNIFIED_SOURCES`` can contain a mix of different file types,
for C, C++, and Objective C.


Static Libraries
================

To build a static library, other than defining the source files (see above), one
just needs to define a library name with the ``Library`` template.

.. code-block:: python

   Library('foo')

The library file name will be ``libfoo.a`` on UNIX systems and ``foo.lib`` on
Windows.

If the static library needs to aggregate other static libraries, a list of
``Library`` names can be added to the ``USE_LIBS`` variable. Like ``SOURCES``, it
requires the appended list to be alphanumerically ordered.

.. code-block:: python

   USE_LIBS += ['bar', 'baz']

If there are multiple directories containing the same ``Library`` name, it is
possible to disambiguate by prefixing with the path to the wanted one (relative
or absolute):

.. code-block:: python

   USE_LIBS += [
       '/path/from/topsrcdir/to/bar',
       '../relative/baz',
   ]

Note that the leaf name in those paths is the ``Library`` name, not an actual
file name.

Note that currently, the build system may not create an actual library for
static libraries. It is an implementation detail that shouldn't need to be
worried about.

As a special rule, ``USE_LIBS`` is allowed to contain references to shared
libraries. In such cases, programs and shared libraries linking this static
library will inherit those shared library dependencies.


Intermediate (Static) Libraries
===============================

In many cases in the tree, static libraries are built with the only purpose
of being linked into another, bigger one (like libxul). Instead of adding all
required libraries to ``USE_LIBS`` for the bigger one, it is possible to tell
the build system that the library built in the current directory is meant to
be linked to that bigger library, with the ``FINAL_LIBRARY`` variable.

.. code-block:: python

   FINAL_LIBRARY = 'xul'

The ``FINAL_LIBRARY`` value must match a unique ``Library`` name somewhere
in the tree.

As a special rule, those intermediate libraries don't need a ``Library`` name
for themselves.


Shared Libraries
================

Sometimes, we want shared libraries, a.k.a. dynamic libraries. Such libraries
are defined similarly to static libraries, using the ``SharedLibrary`` template
instead of ``Library``.

.. code-block:: python

   SharedLibrary('foo')

When this template is used, no static library is built. See further below to
build both types of libraries.

With a ``SharedLibrary`` name of ``foo``, the library file name will be
``libfoo.dylib`` on OSX, ``libfoo.so`` on ELF systems (Linux, etc.), and
``foo.dll`` on Windows. On Windows, there is also an import library named
``foo.lib``, used on the linker command line. ``libfoo.dylib`` and
``libfoo.so`` are considered the import library name for, resp. OSX and ELF
systems.

On OSX, one may want to create a special kind of dynamic library: frameworks.
This is done with the ``Framework`` template.

.. code-block:: python

   Framework('foo')

With a ``Framework`` name of ``foo``, the framework file name will be ``foo``.
This template however affects the behavior on all platforms, so it needs to
be set only on OSX.


Executables
===========

Executables, a.k.a. programs, are, in the simplest form, defined with the
``Program`` template.

.. code-block:: python

   Program('foobar')

On UNIX systems, the executable file name will be ``foobar``, while on Windows,
it will be ``foobar.exe``.

Like static and shared libraries, the build system can be instructed to link
libraries to the executable with ``USE_LIBS``, listing various ``Library``
names.

In some cases, we want to create an executable per source file in the current
directory, in which case we can use the ``SimplePrograms`` template

.. code-block:: python

   SimplePrograms([
       'FirstProgram',
       'SecondProgram',
   ])

Contrary to ``Program``, which requires corresponding ``SOURCES``, when using
``SimplePrograms``, the corresponding ``SOURCES`` are implied. If the
corresponding ``sources`` have an extension different from ``.cpp``, it is
possible to specify the proper extension:

.. code-block:: python

   SimplePrograms([
       'ThirdProgram',
       'FourthProgram',
   ], ext='.c')

Please note this construct was added for compatibility with what already lives
in the mozilla tree ; it is recommended not to add new simple programs with
sources with a different extension than ``.cpp``.

Similar to ``SimplePrograms``, is the ``CppUnitTests`` template, which defines,
with the same rules, C++ unit tests programs. Like ``SimplePrograms``, it takes
an ``ext`` argument to specify the extension for the corresponding ``SOURCES``,
if it's different from ``.cpp``.


Linking with system libraries
=============================

Programs and libraries usually need to link with system libraries, such as a
widget toolkit, etc. Those required dependencies can be given with the
``OS_LIBS`` variable.

.. code-block:: python

   OS_LIBS += [
       'foo',
       'bar',
   ]

This expands to ``foo.lib bar.lib`` when building with MSVC, and
``-lfoo -lbar`` otherwise.

For convenience with ``pkg-config``, ``OS_LIBS`` can also take linker flags
such as ``-L/some/path`` and ``-llib``, such that it is possible to directly
assign ``LIBS`` variables from ``CONFIG``, such as:

.. code-block:: python

   OS_LIBS += CONFIG['MOZ_PANGO_LIBS']

(assuming ``CONFIG['MOZ_PANGO_LIBS']`` is a list, not a string)

Like ``USE_LIBS``, this variable applies to static and shared libraries, as
well as programs.


Libraries from third party build system
=======================================

Some libraries in the tree are not built by the moz.build-governed build
system, and there is no ``Library`` corresponding to them.

However, ``USE_LIBS`` allows to reference such libraries by giving a full
path (like when disambiguating identical ``Library`` names). The same naming
rules apply as other uses of ``USE_LIBS``, so only the library name without
prefix and suffix shall be given.

.. code-block:: python

   USE_LIBS += [
       '/path/from/topsrcdir/to/third-party/bar',
       '../relative/third-party/baz',
   ]

Note that ``/path/from/topsrcdir/to/third-party`` and
``../relative/third-party/baz`` must lead under a subconfigured directory (a
directory with an AC_OUTPUT_SUBDIRS in configure.in), or ``security/nss``.


Building both static and shared libraries
=========================================

When both types of libraries are required, one needs to set both
``FORCE_SHARED_LIB`` and ``FORCE_STATIC_LIB`` boolean variables.

.. code-block:: python

   FORCE_SHARED_LIB = True
   FORCE_STATIC_LIB = True

But because static libraries and Windows import libraries have the same file
names, either the static or the shared library name needs to be different
than the name given to the ``Library`` template.

The ``STATIC_LIBRARY_NAME`` and ``SHARED_LIBRARY_NAME`` variables can be used
to change either the static or the shared library name.

.. code-block:: python

  Library('foo')
  STATIC_LIBRARY_NAME = 'foo_s'

With the above, on Windows, ``foo_s.lib`` will be the static library,
``foo.dll`` the shared library, and ``foo.lib`` the import library.

In some cases, for convenience, it is possible to set both
``STATIC_LIBRARY_NAME`` and ``SHARED_LIBRARY_NAME``. For example:

.. code-block:: python

  Library('mylib')
  STATIC_LIBRARY_NAME = 'mylib_s'
  SHARED_LIBRARY_NAME = CONFIG['SHARED_NAME']

This allows to use ``mylib`` in the ``USE_LIBS`` of another library or
executable.

When referring to a ``Library`` name building both types of libraries in
``USE_LIBS``, the shared library is chosen to be linked. But sometimes,
it is wanted to link the static version, in which case the ``Library`` name
needs to be prefixed with ``static:`` in ``USE_LIBS``

::

   a/moz.build:
      Library('mylib')
      FORCE_SHARED_LIB = True
      FORCE_STATIC_LIB = True
      STATIC_LIBRARY_NAME = 'mylib_s'
   b/moz.build:
      Program('myprog')
      USE_LIBS += [
          'static:mylib',
      ]


Miscellaneous
=============

The ``SONAME`` variable declares a "shared object name" for the library. It
defaults to the ``Library`` name or the ``SHARED_LIBRARY_NAME`` if set. When
linking to a library with a ``SONAME``, the resulting library or program will
have a dependency on the library with the name corresponding to the ``SONAME``
instead of the ``Library`` name. This only impacts ELF systems.

::

   a/moz.build:
      Library('mylib')
   b/moz.build:
      Library('otherlib')
      SONAME = 'foo'
   c/moz.build:
      Program('myprog')
      USE_LIBS += [
          'mylib',
          'otherlib',
      ]

On e.g. Linux, the above ``myprog`` will have DT_NEEDED markers for
``libmylib.so`` and ``libfoo.so`` instead of ``libmylib.so`` and
``libotherlib.so`` if there weren't a ``SONAME``. This means the runtime
requirement for ``myprog`` is ``libfoo.so`` instead of ``libotherlib.so``.


Gecko-related binaries
======================

Some programs or libraries are totally independent of Gecko, and can use the
above mentioned templates. Others are Gecko-related in some way, and may
need XPCOM linkage, mozglue. These things are tedious. A set of additional
templates exists to ease defining such programs and libraries. They are
essentially the same as the above mentioned templates, prefixed with "Gecko":

  - ``GeckoProgram``
  - ``GeckoSimplePrograms``
  - ``GeckoCppUnitTests``
  - ``GeckoSharedLibrary``
  - ``GeckoFramework``

All the Gecko-prefixed templates take the same arguments as their
non-Gecko-prefixed counterparts, and can take a few more arguments
for non-standard cases. See the definition of ``GeckoBinary`` in
build/gecko_templates.mozbuild for more details, but most usecases
should not require these additional arguments.

---

### Build Docs Defining Xpcom Components (`build/docs/defining-xpcom-components.rst`)

.. _defining_xpcom_components:

=========================
Defining XPCOM Components
=========================

This document explains how to write a :code:`components.conf` file. For
documentation on the idl format see :ref:`XPIDL`. For a tutorial on writing
a new XPCOM interface, see
:ref:`writing_xpcom_interface`.

Native XPCOM components are registered at build time, and compiled into static
data structures which allow them to be accessed with little runtime overhead.
Each module which wishes to register components must provide a manifest
describing each component it implements, its type, and how it should be
constructed.

Manifest files are Python data files registered in ``moz.build`` files in a
``XPCOM_MANIFESTS`` file list:

.. code-block:: python

    XPCOM_MANIFESTS += [
      'components.conf',
    ]

The files may define any of the following special variables:

.. code-block:: python

    # Optional: A function to be called once, the first time any component
    # listed in this manifest is instantiated.
    InitFunc = 'nsInitFooModule'
    # Optional: A function to be called at shutdown if any component listed in
    # this manifest has been instantiated.
    UnloadFunc = 'nsUnloadFooModule'

    # Optional: A processing priority, to determine how early or late the
    # manifest is processed. Defaults to 50. In practice, this mainly affects
    # the order in which unload functions are called at shutdown, with higher
    # priority numbers being called later.
    Priority = 10

    # Optional: A list of header files to include before calling init or
    # unload functions, or any legacy constructor functions.
    #
    # Any header path beginning with a `/` is loaded relative to the root of
    # the source tree, and must not rely on any local includes.
    #
    # Any relative header path must be exported.
    Headers = [
        '/foo/nsFooModule.h',
        'nsFoo.h',
    ]

    # A list of component classes provided by this module.
    Classes = [
        {
            # ...
        },
        # ...
    ]

    # A list of category registrations
    Categories = {
        'category': {
            'name': 'value',
            'other-name': ('value', ProcessSelector.MAIN_PROCESS_ONLY),
            # ...
        },
        # ...
    }

Class definitions may have the following properties:

``name`` (optional)
  If present, this component will generate an entry with the given name in the
  ``mozilla::components`` namespace in ``mozilla/Components.h``, which gives
  easy access to its CID, service, and instance constructors as (e.g.,)
  ``components::Foo::CID()``, ``components::Foo::Service()``, and
  ``components::Foo::Create()``, respectively.

``cid``
  A UUID string containing this component's CID, in the form
  ``'{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}'``.

``contract_ids`` (optional)
  A list of contract IDs to register for this class.

``categories`` (optional)
  A dict of category entries to register for this component's contract ID.
  Each key in the dict is the name of the category. Each value is either a
  string containing a single entry, or a list of entries.  Each entry is either
  a string name, or a dictionary of the form ``{'name': 'value', 'backgroundtasks':
  BackgroundTasksSelector.ALL_TASKS}``.  By default, category entries are registered
  for **no background tasks**: they have
  ``'backgroundtasks': BackgroundTasksSelector.NO_TASKS``.

``type`` (optional, default=``nsISupports``)
  The fully-qualified type of the class implementing this component. Defaults
  to ``nsISupports``, but **must** be provided if the ``init_method`` property
  is specified, or if neither the ``constructor`` nor ``legacy_constructor``
  properties are provided.

``headers`` (optional)
  A list of headers to include in order to call this component's constructor,
  in the same format as the global ``Headers`` property.

``init_method`` (optional)
  The name of a method to call on newly-created instances of this class before
  returning them. The method must take no arguments, and must return a
  ``nsresult``. If it returns failure, that failure is propagated to the
  ``getService`` or ``createInstance`` caller.

``constructor`` (optional)
  The fully-qualified name of a constructor function to call in order to
  create instances of this class. This function must be declared in one of the
  headers listed in the ``headers`` property, must take no arguments, and must
  return ``already_AddRefed<iface>`` where ``iface`` is the interface provided
  in the ``type`` property.

  This property is incompatible with ``legacy_constructor``.

``esModule`` (optional)
  If provided, must be the URL of a
  `JavaScript module <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules>`_
  which contains a JavaScript implementation of the component.
  The ``constructor`` property must contain the name of an exported
  function which can be constructed to create a new instance of the component.


``jsm`` (deprecated, optional)
  Do not use. Use ``esModule`` instead.

``legacy_constructor`` (optional)
  This property is deprecated, and should not be used in new code.

  The fully-qualified name of a constructor function to call in order to
  create instances of this class. This function must be declared in one of the
  headers listed in the ``headers`` property, and must have the signature
  ``nsresult(const nsID& aIID, void** aResult)``, and behave equivalently to
  ``nsIFactory::CreateInstance``.

  This property is incompatible with ``constructor``.

``singleton`` (optional, default=``False``)
  If true, this component's constructor is expected to return the same
  singleton for every call, and no ``mozilla::components::<name>::Create()``
  method will be generated for it.

``overridable`` (optional, default=``False``)
  If true, this component's contract ID is expected to be overridden by some
  tests, and its ``mozilla::components::<name>::Service()`` getter will
  therefore look it up by contract ID for every call. This component must,
  therefore, provide at least one contract ID in its ``contract_ids`` array.

  If false, the ``Service()`` getter will always retrieve the service based on
  its static data, and it cannot be overridden.

  Note: Enabling this option is expensive, and should not be done when it can
  be avoided, or when the getter is used by any hot code.

``external`` (optional, default=``False`` if any ``headers`` are provided, ``True`` otherwise)
  If true, a constructor for this component's ``type`` must be defined in
  another translation unit, using ``NS_IMPL_COMPONENT_FACTORY(type)``. The
  constructor must return an ``already_AddRefed<nsISupports>``, and will be
  used to construct instances of this type.

  This option should only be used in cases where the headers which define the
  component's concrete type cannot be easily included without local includes.

  Note: External constructors may not specify an ``init_method``, since the
  generated code will not have the necessary type information required to call
  it. This option is also incompatible with ``constructor`` and
  ``legacy_constructor``.

``processes`` (optional, default=``ProcessSelector.ANY_PROCESS``)
  An optional specifier restricting which types of process this component may
  be loaded in. This must be a property of ``ProcessSelector`` with the same
  name as one of the values in the ``Module::ProcessSelector`` enum.


Conditional Compilation
=======================

This manifest may run any appropriate Python code to customize the values of
the ``Classes`` array based on build configuration. To simplify this process,
the following globals are available:

``defined``
  A function which returns true if the given build config setting is defined
  and true.

``buildconfig``
  The ``buildconfig`` python module, with a ``substs`` property containing a
  dict of all available build substitutions.


Component Constructors
======================

There are several ways to define component constructors, which vary mostly
depending on how old the code that uses them is:

Class Constructors
------------------

This simplest way to define a component is to include a header defining a
concrete type, and let the component manager call that class's constructor:

.. rstcheck: ignore-languages=python
.. code-block:: python

  'type': 'mozilla::foo::Foo',
  'headers': ['mozilla/Foo.h'],

This is generally the preferred method of defining non-singleton constructors,
but may not be practicable for classes which rely on local includes for their
definitions.

Singleton Constructors
----------------------

Singleton classes are generally expected to provide their own constructor
function which caches a singleton instance the first time it is called, and
returns the same instance on subsequent calls. This requires declaring the
constructor in an included header, and implementing it in a separate source
file:

.. rstcheck: ignore-languages=python
.. code-block:: python

  'type': 'mozilla::foo::Foo',
  'headers': ['mozilla/Foo.h'],
  'constructor': 'mozilla::Foo::GetSingleton',

``Foo.h``

.. code-block:: cpp

    class Foo final : public nsISupports {
     public:
      static already_AddRefed<Foo> GetSingleton();
    };

``Foo.cpp``

.. code-block:: cpp

    already_AddRefed<Foo> Foo::GetSingleton() {
      // ...
    }

External Constructors
---------------------

For types whose headers can't easily be included, constructors can be defined
using a template specialization on an incomplete type:

.. rstcheck: ignore-languages=python
.. code-block:: python

  'type': 'mozilla::foo::Foo',
  'external: True,'

``Foo.cpp``

.. code-block:: cpp

    NS_IMPL_COMPONENT_FACTORY(Foo) {
      return do_AddRef(new Foo()).downcast<nsISupports>();
    }

Legacy Constructors
-------------------

These should not be used in new code, and are left as an exercise for the
reader.


Registering Categories
======================

Classes which need define category entries with the same value as their
contract ID may do so using the following:

.. rstcheck: ignore-languages=python
.. code-block:: python

    'contract_ids': ['@mozilla.org/foo;1'],
    'categories': {
        'content-policy': 'm-foo',
        'Gecko-Content-Viewers': ['image/jpeg', 'image/png'],
    },

This will define each of the following category entries:

* ``"content-policy"`` ``"m-foo",`` ``"@mozilla.org/foo;1"``
* ``"Gecko-Content-Viewers"`` ``"image/jpeg"`` ``"@mozilla.org/foo;1"``
* ``"Gecko-Content-Viewers"`` ``"image/png"`` ``"@mozilla.org/foo;1"``

Some category entries do not have a contract ID as a value. These entries can
be specified by adding to a global ``Categories`` dictionary:

.. code-block:: python

    Categories = {
        'update-timer': {
            'nsUpdateService': '@mozilla.org/updates/update-service;1,getService,background-update-timer,app.update.interval,43200,86400',
        }
    }

It is possible to limit these on a per-process basis by using a tuple as the
value:

.. code-block:: python

    Categories = {
        '@mozilla.org/streamconv;1': {
            '?from=gzip&to=uncompressed': ('', ProcessSelector.ALLOW_IN_SOCKET_PROCESS),
        }
    }

---

### Build Docs Environment Variables (`build/docs/environment-variables.rst`)

.. _environment_variables:

================================================
Environment Variables Impacting the Build System
================================================

Various environment variables have an impact on the behavior of the
build system. This document attempts to document them.

AUTOCLOBBER
   If defines, the build system will automatically clobber as needed.
   The default behavior is to print a message and error out when a
   clobber is needed.

   This variable is typically defined in a :ref:`mozconfig <mozconfig>`
   file via ``mk_add_options``.

REBUILD_CHECK
   If defined, the build system will print information about why
   certain files were rebuilt.

   This feature is disabled by default because it makes the build slower.

MACH_NO_TERMINAL_FOOTER
   If defined, the terminal footer displayed when building with mach in
   a TTY is disabled.

MACH_NO_FUNC_CACHE
   If defined, disables mach's persistent function result cache. This
   cache speeds up operations like configure by avoiding redundant
   expensive computations when input files haven't changed.

MACH_NO_WRITE_TIMES
   If defined, mach commands will not prefix output lines with the
   elapsed time since program start. This option is equivalent to
   passing ``--log-no-times`` to mach.

---

### Build Docs Files Metadata (`build/docs/files-metadata.rst`)

.. _mozbuild_files_metadata:

==============
Files Metadata
==============

:ref:`mozbuild-files` provide a mechanism for attaching metadata to
files. Essentially, you define some flags to set on a file or file
pattern. Later, some tool or process queries for metadata attached to a
file of interest and it does something intelligent with that data.

Defining Metadata
=================

Files metadata is defined by using the
:ref:`Files Sub-Context <mozbuild_subcontext_Files>` in ``moz.build``
files. e.g.::

    with Files('**/Makefile.in'):
        BUG_COMPONENT = ('Firefox Build System', 'General')

This working example says, *for all Makefile.in files in every directory
underneath this one - including this directory - set the Bugzilla
component to Firefox Build System :: General*.

For more info, read the
:ref:`docs on Files <mozbuild_subcontext_Files>`.

How Metadata is Read
====================

``Files`` metadata is extracted in :ref:`mozbuild_fs_reading_mode`.

Reading starts by specifying a set of files whose metadata you are
interested in. For each file, the filesystem is walked to the root
of the source directory. Any ``moz.build`` encountered during this
walking are marked as relevant to the file.

Let's say you have the following filesystem content::

   /moz.build
   /root_file
   /dir1/moz.build
   /dir1/foo
   /dir1/subdir1/foo
   /dir2/foo

For ``/root_file``, the relevant ``moz.build`` files are just
``/moz.build``.

For ``/dir1/foo`` and ``/dir1/subdir1/foo``, the relevant files are
``/moz.build`` and ``/dir1/moz.build``.

For ``/dir2``, the relevant file is just ``/moz.build``.

Once the list of relevant ``moz.build`` files is obtained, each
``moz.build`` file is evaluated. Root ``moz.build`` file first,
leaf-most files last. This follows the rules of
:ref:`mozbuild_fs_reading_mode`, with the set of evaluated ``moz.build``
files being controlled by filesystem content, not ``DIRS`` variables.

The file whose metadata is being resolved maps to a set of ``moz.build``
files which in turn evaluates to a list of contexts. For file metadata,
we only care about one of these contexts:
:ref:`Files <mozbuild_subcontext_Files>`.

We start with an empty ``Files`` instance to represent the file. As
we encounter a *files sub-context*, we see if it is appropriate to
this file. If it is, we apply its values. This process is repeated
until all *files sub-contexts* have been applied or skipped. The final
state of the ``Files`` instance is used to represent the metadata for
this particular file.

It may help to visualize this. Say we have 2 ``moz.build`` files::

    # /moz.build
    with Files('*.cpp'):
        BUG_COMPONENT = ('Core', 'XPCOM')

    with Files('**/*.js'):
        BUG_COMPONENT = ('Firefox', 'General')

    # /foo/moz.build
    with Files('*.js'):
        BUG_COMPONENT = ('Another', 'Component')

Querying for metadata for the file ``/foo/test.js`` will reveal 3
relevant ``Files`` sub-contexts. They are evaluated as follows:

1. ``/moz.build - Files('*.cpp')``. Does ``/*.cpp`` match
   ``/foo/test.js``? **No**. Ignore this context.
2. ``/moz.build - Files('**/*.js')``. Does ``/**/*.js`` match
   ``/foo/test.js``? **Yes**. Apply ``BUG_COMPONENT = ('Firefox', 'General')``
   to us.
3. ``/foo/moz.build - Files('*.js')``. Does ``/foo/*.js`` match
   ``/foo/test.js``? **Yes**. Apply
   ``BUG_COMPONENT = ('Another', 'Component')``.

At the end of execution, we have
``BUG_COMPONENT = ('Another', 'Component')`` as the metadata for
``/foo/test.js``.

One way to look at file metadata is as a stack of data structures.
Each ``Files`` sub-context relevant to a given file is applied on top
of the previous state, starting from an empty state. The final state
wins.

.. _mozbuild_files_metadata_finalizing:

Finalizing Values
=================

The default behavior of ``Files`` sub-context evaluation is to apply new
values on top of old. In most circumstances, this results in desired
behavior. However, there are circumstances where this may not be
desired. There is thus a mechanism to *finalize* or *freeze* values.

Finalizing values is useful for scenarios where you want to prevent
wildcard matches from overwriting previously-set values. This is useful
for one-off files.

Let's take ``Makefile.in`` files as an example. The build system module
policy dictates that ``Makefile.in`` files are part of the ``Build
Config`` module and should be reviewed by peers of that module. However,
there exist ``Makefile.in`` files in many directories in the source
tree. Without finalization, a ``*`` or ``**`` wildcard matching rule
would match ``Makefile.in`` files and overwrite their metadata.

Finalizing of values is performed by setting the ``FINAL`` variable
on ``Files`` sub-contexts. See the
:ref:`Files documentation <mozbuild_subcontext_Files>` for more.

Here is an example with ``Makefile.in`` files, showing how it is
possible to finalize the ``BUG_COMPONENT`` value.::

    # /moz.build
    with Files('**/Makefile.in'):
        BUG_COMPONENT = ('Firefox Build System', 'General')
        FINAL = True

    # /foo/moz.build
    with Files('**'):
        BUG_COMPONENT = ('Another', 'Component')

If we query for metadata of ``/foo/Makefile.in``, both ``Files``
sub-contexts match the file pattern. However, since ``BUG_COMPONENT`` is
marked as finalized by ``/moz.build``, the assignment from
``/foo/moz.build`` is ignored. The final value for ``BUG_COMPONENT``
is ``('Firefox Build System', 'General')``.

Here is another example::

    with Files('*.cpp'):
        BUG_COMPONENT = ('One-Off', 'For C++')
        FINAL = True

    with Files('**'):
        BUG_COMPONENT = ('Regular', 'Component')

For every files except ``foo.cpp``, the bug component will be resolved
as ``Regular :: Component``. However, ``foo.cpp`` has its value of
``One-Off :: For C++`` preserved because it is finalized.

.. important::

   ``FINAL`` only applied to variables defined in a context.

   If you want to mark one variable as finalized but want to leave
   another mutable, you'll need to use 2 ``Files`` contexts.

Guidelines for Defining Metadata
================================

In general, values defined towards the root of the source tree are
generic and become more specific towards the leaves. For example,
the ``BUG_COMPONENT`` for ``/browser`` might be ``Firefox :: General``
whereas ``/browser/components/preferences`` would list
``Firefox :: Preferences``.

---

### Build Docs Flatpak (`build/docs/flatpak.rst`)

.. _flatpak:

=========================
Firefox Flatpak Packaging
=========================

This page explains interactions between Firefox and Flatpak packaging format.

Where is the upstream
=====================

The code reference itself is mozilla-central and the repackaging is under :searchfox:`the mach repackage flatpak command <python/mozbuild/mozbuild/repackaging/flatpak.py>`.

Where to report bugs
====================

All bugs should be reported to Bugzilla in the appropriate component depending on the bug and marked as blocking the ``flatpak`` meta-bug.

Build process
=============

Perform a build and then run ``mach repackage flatpak``, e.g.:

.. code-block:: shell

   $ mach repackage flatpak \
                    --input target.tar.xz \
                    --name org.mozilla.firefox \
                    --arch aarch64 \
                    --version 137.0a1 \
                    --product firefox \
                    --release-type nightly \
                    --flatpak-branch nightly \
                    --template-dir browser/installer/linux/app/flatpak \
                    --langpack-pattern $PWD/langpacks/*.xpi \
                    --output test.flatpak.tar.xz,

Where ``target.tar.xz`` can be a downloaded artifact from try build or built from a local build. You will also want to download `some langpack <https://ftp.mozilla.org/pub/firefox/nightly/latest-mozilla-central-l10n/linux-x86_64/xpi/>`_.

How to hack on try
==================

Pushing to try is basically just:

.. code-block:: shell

    $ mach try fuzzy --full -q "'repackage 'flatpak !shippable"`

This will produce a repackage flatpak task at the end that generates a ``target.flatpak.tar.xz``.

Installing the try build
========================

Download and extract the previously generated ``target.flatpak.tar.xz`` and it will produce a ``./repo`` directory that you can directly use with flatpak:

.. code-block:: shell

    $ flatpak --user --no-gpg-verify remote-add firefox-try ./repo/

This should add you a user-level firefox-try flatpak remote, you can verify with (``flathub`` remote may be a user or a system level remote):

 .. code-block:: shell

    $ flatpak remotes
    Name        Options
    firefox-try user
    flathub     user

Then you can install your local build:

 .. code-block:: shell

    $ flatpak install firefox-try firefox
    Looking for matches…
    Found ref ‘app/org.mozilla.firefox/x86_64/nightly’ in remote ‘firefox-try’ (user).
    Use this ref? [Y/n]: y

    org.mozilla.firefox permissions:
        ipc          network                cups                  fallback-x11            pcsc                         pulseaudio       wayland       x11       devices
        devel        file access [1]        dbus access [2]       bus ownership [3]       system dbus access [4]

        [1] /run/.heim_org.h5l.kcm-socket, xdg-download, xdg-run/speech-dispatcher:ro
        [2] org.a11y.Bus, org.freedesktop.FileManager1, org.gtk.vfs.*
        [3] org.mozilla.firefox.*, org.mozilla.firefox_beta.*, org.mpris.MediaPlayer2.firefox.*
        [4] org.freedesktop.NetworkManager


            ID                                              Branch                 Op            Remote                 Download
     1. [✓] org.freedesktop.Platform.GL.default             24.08                  u             flathub                 67,3 Mo / 156,6 Mo
     2. [✓] org.freedesktop.Platform.GL.default             24.08extra             u             flathub                  3,9 Mo / 156,6 Mo
     3. [✓] org.freedesktop.Platform.Locale                 24.08                  u             flathub                282,1 Ko / 380,3 Mo
     4. [✓] org.freedesktop.Platform                        24.08                  u             flathub                 25,4 Mo / 264,4 Mo
     5. [✓] org.mozilla.firefox.Locale                      nightly                i             firefox-try              1,0 Ko / 1,6 Mo
     6. [✓] org.mozilla.firefox                             nightly                i             firefox-try              1,0 Ko / 111,5 Mo

    Changes complete.

And after that you can just run ``flatpak run org.mozilla.firefox//nightly``.

---

### Build Docs Glossary (`build/docs/glossary.rst`)

Build Glossary
==============

.. glossary::
   :sorted:

   object directory
       A directory holding the output of the build system. The build
       system attempts to isolate all file modifications to this
       directory. By convention, object directories are commonly
       directories under the source directory prefixed with **obj-**.
       e.g. **obj-firefox**.

   mozconfig
       A shell script used to configure the build system.

   configure
       A generated shell script which detects the current system
       environment, applies a requested set of build configuration
       options, and writes out metadata to be consumed by the build
       system.

   config.status
       An executable file produced by **configure** that takes the
       generated build config and writes out files used to build the
       tree. Traditionally, config.status writes out a bunch of
       Makefiles.

   install manifest
       A file containing metadata describing file installation rules.
       A large part of the build system consists of copying files
       around to appropriate places. We write out special files
       describing the set of required operations so we can process the
       actions efficiently. These files are install manifests.

   clobber build
      A build performed with an initially empty object directory. All
      build actions must be performed.

   incremental build
      A build performed with the result of a previous build in an
      object directory. The build should not have to work as hard because
      it will be able to reuse the work from previous builds.

   mozinfo
      An API for accessing a common and limited subset of the build and
      run-time configuration. See :ref:`mozinfo`.

---

### Build Docs Gn (`build/docs/gn.rst`)

.. _gn:

==============================
GN support in the build system
==============================

:abbr:`GN (Generated Ninja)` is a third-party build tool used by chromium and
some related projects that are vendored in mozilla-central. Rather than
requiring ``GN`` to build or writing our own build definitions for these projects,
we have support in the build system for translating GN configuration
files into moz.build files. In most cases these moz.build files will be like any
others in the tree (except that they shouldn't be modified by hand), however
those updating vendored code or building on platforms not supported by
Mozilla automation may need to re-generate these files. This is a per-project
process, described in dom/media/webrtc/third_party_build/gn-configs/README.md for
webrtc. As of writing, it is very specific to webrtc, and likely doesn't work as-is
for other projects.

---

### Build Docs Index (`build/docs/index.rst`)

============
Build System
============

Important Concepts
==================
.. toctree::
   :maxdepth: 1

   glossary
   build-overview
   supported-configurations
   Mozconfig Files <mozconfigs>
   mozbuild-files
   mozbuild-symbols
   files-metadata
   Profile Guided Optimization <pgo>
   slow
   environment-variables
   build-targets
   python
   test_manifests
   mozinfo
   preprocessor
   jar-manifests
   defining-binaries
   defining-xpcom-components
   toolchains
   toolchains-update-policy
   locales
   unified-builds
   cross-compile
   rust
   sparse
   Support for projects building with GN <gn>
   telemetry
   sccache-dist
   test_certificates

integrated development environment (IDE)
========================================
.. toctree::
   :maxdepth: 1

   cppeclipse
   visualstudio

mozbuild
========

mozbuild is a Python package containing a lot of the code for the
Mozilla build system.

.. toctree::
   :maxdepth: 1

   mozbuild/index

Snap Package
============

`Snap <https://snapcraft.io/docs>`_ is a packaging format

.. toctree::
   :maxdepth: 1

   snap

Flatpak Package
===============

`Flatpak <https://docs.flatpak.org/en/latest/>`_ is a packaging format

.. toctree::
   :maxdepth: 1

   flatpak

---

### Build Docs Jar Manifests (`build/docs/jar-manifests.rst`)

.. _jar_manifests:

=============
JAR Manifests
=============

JAR Manifests are plaintext files in the tree that are used to package chrome
files into ``.jar`` files and create :ref:`Chrome Registration <Chrome Registration>`
manifests. JAR Manifests are commonly named ``jar.mn``. They are declared in ``moz.build`` files using the ``JAR_MANIFESTS`` variable, which makes up a collection of ``jar.mn`` files.
All files declared in JAR Manifests are processed and installed into ``omni.ja`` files in ``browser/`` and ``toolkit/`` when building Firefox.

``jar.mn`` files are automatically processed by the build system when building a
source directory that contains one. The ``jar.mn`` is run through the
:ref:`preprocessor` before being passed to the manifest processor. In order to
have ``@variables@`` expanded (such as ``@AB_CD@``) throughout the file, add
the line ``#filter substitution`` at the top of your ``jar.mn`` file.

The format of a jar.mn is fairly simple; it consists of a heading specifying
which JAR file is being packaged, followed by indented lines listing files and
chrome registration instructions.

For a simple ``jar.mn`` file, see :searchfox:`toolkit/profile/jar.mn <mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0:toolkit/profile/jar.mn>`. For a much
more complex ``jar.mn`` file, see :searchfox:`toolkit/locales/jar.mn <mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0:toolkit/locales/jar.mn>`. More examples with specific formats and uses are available below.

Shipping Chrome Files
======================
General Format
^^^^^^^^^^^^^^
To ship chrome files in a JAR, an indented line indicates a file to be packaged::

   <jarfile>.jar:
     path/in/jar/file_name.xul     (source/tree/location/file_name.xul)

Note that file path mappings are listed by destination (left) followed by source (right).

Same Directory Omission
^^^^^^^^^^^^^^^^^^^^^^^
If the JAR manifest and packaged files live in the same directory, the source path and parentheses can be omitted.
A sample of a ``jar.mn`` file with omitted source paths and parentheses is :searchfox:`this revision of browser/components/colorways/jar.mn <mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0:browser/components/colorways/jar.mn>`::

   browser.jar:
     content/browser/colorwaycloset.html
     content/browser/colorwaycloset.css
     content/browser/colorwaycloset.js

Writing the following is equivalent, given that the aforementioned files exist in the same directory as the ``jar.mn``. Notice the ``.jar`` file is named ``browser.jar``::

   browser.jar:
     content/browser/colorwaycloset.html (colorwaycloset.html)
     content/browser/colorwaycloset.css  (colorwaycloset.css)
     content/browser/colorwaycloset.js   (colorwaycloset.js)

This manifest is responsible for packaging files needed by Colorway Closet, including
JS scripts, localization files, images (ex. PNGs, AVIFs), and CSS styling. Look at :searchfox:`browser/components/colorways/colorwaycloset.html <mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0:browser/components/colorways/colorwaycloset.html#18>`
to see how a file may be referenced using its chrome URL.

Absolute Paths
^^^^^^^^^^^^^^
The source tree location may also be an absolute path (taken from the top of the source tree).
One such example can be found in :searchfox:`toolkit/components/pictureinpicture/jar.mn <mozilla-central/rev/2005e8d87ee045f19dac58e5bff32eff7d01bc9b:toolkit/components/pictureinpicture/jar.mn>`::

   toolkit.jar:
     * content/global/pictureinpicture/player.xhtml   (content/player.xhtml)
     content/global/pictureinpicture/player.js      (content/player.js)

Asterisk Marker (Preprocessing)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
An asterisk marker (``*``) at the beginning of the line indicates that the file should be processed by the :ref:`preprocessor` before being packaged.
The file :searchfox:`toolkit/profile/jar.mn <mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0:toolkit/profile/jar.mn>` indicates that the file :searchfox:`toolkit/profile/content/profileDowngrade.xhtml <mozilla-central/rev/2005e8d87ee045f19dac58e5bff32eff7d01bc9b:toolkit/profile/content/profileDowngrade.xhtml#34,36>` should be
run through the preprocessor, since it contains ``#ifdef`` and ``#endif`` statements that need to be interpreted::

   * content/mozapps/profile/profileDowngrade.xhtml  (content/profileDowngrade.xhtml)

Base Path, Variables, Wildcards and Localized Files
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``.jar`` file location may be preceded with a base path between square brackets.
The file :searchfox:`toolkit/locales/jar.mn <mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0:toolkit/locales/jar.mn>` uses a base path so that the ``.jar`` file is under a ``localization`` directory,
which is a :searchfox:`special directory parsed by mozbuild <mozilla-central/rev/2005e8d87ee045f19dac58e5bff32eff7d01bc9b:python/mozbuild/mozpack/packager/l10n.py#260-265>`.

It is also named according to the value passed by the variable ``@AB_CD@``, normally a locale. Note the use of the preprocessor directive ``#filter substitution`` at the top of the file for replacing the variable with the value::

   #filter substitution

   ...

   [localization] @AB_CD@.jar:
     crashreporter                                    (%crashreporter/**/*.ftl)
     toolkit                                          (%toolkit/**/*.ftl)

The percentage sign in front of the source paths designates the locale to target as a source. By default, this is ``en-US``. With this specific example, :searchfox:`/toolkit/locales/en-US <toolkit/locales/en-US>` would be targeted.
Otherwise, the file from an alternate localization source tree ``/l10n/<locale>/toolkit/`` is read if building a localized version.
The wildcards in ``**/*.ftl`` tell the processor to install all Fluent files within the ``crashreporter`` and ``toolkit`` directories, as well as their subdirectories.

Registering Chrome
==================

:ref:`Chrome Registration <Chrome Registration>` instructions are marked with a percent sign (``%``) at the beginning of the
line, and must be part of the definition of a JAR file. Any additional percents
signs are replaced with an appropriate relative URL of the JAR file being
packaged.

There are two possible locations for a manifest file. If the chrome is being
built into a standalone application, the ``jar.mn`` processor creates a
``<jarfilename>.manifest`` next to the JAR file itself. This is the default
behavior.

If the ``moz.build`` specifies ``USE_EXTENSION_MANIFEST = 1``, the ``jar.mn`` processor
creates a single ``chrome.manifest`` file suitable for registering chrome as
an extension.

Example
^^^^^^^

The file :searchfox:`browser/themes/addons/jar.mn <mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0:browser/themes/addons/jar.mn>` registers a ``resource`` chrome package under the name ``builtin-themes``. Its source files are in ``%content/builtin-themes/``::

   browser.jar:
     %  resource builtin-themes %content/builtin-themes/

     content/builtin-themes/alpenglow                 (alpenglow/*.svg)
     content/builtin-themes/alpenglow/manifest.json   (alpenglow/manifest.json)

Notice how other files declare an installation destination using the ``builtin-themes`` resource that is defined. As such, a SVG file ``preview.svg`` for a theme ``Alpenglow`` may be loaded using the resource URL ``resource://builtin-themes/alpenglow/preview.svg``
so that a preview of the theme is available on ``about:addons``. See :ref:`Chrome Registration <Chrome Registration>` for more details on ``resource`` and other manifest instructions.

---

### Build Docs Locales (`build/docs/locales.rst`)

.. _localized-builds:

================
Localized Builds
================

Localization repacks
====================

To save on build time, the build system and automation collaborate to allow
downloading a packaged en-US Firefox, performing some locale-specific
post-processing, and re-packaging a locale-specific Firefox. Such artifacts
are termed "single-locale language repacks". There is another concept of a
"multi-locale language build", which is more like a regular build and less
like a re-packaging post-processing step.

.. note::

  These builds rely on make targets that don't work for
  `artifact builds <https://bugzilla.mozilla.org/show_bug.cgi?id=1387485>`_.

Instructions for single-locale repacks for developers
-----------------------------------------------------

This assumes that ``$AB_CD`` is the locale you want to repack with; you
find the available localizations from `firefox-l10n <https://github.com/mozilla-l10n/firefox-l10n>`_.

#. You must have a built and packaged object directory, or a pre-built
   ``en-US`` package.

   .. code-block:: shell

      ./mach build
      ./mach package

#. Repackage using the locale-specific changes.

   .. code-block:: shell

      ./mach build installers-$AB_CD

You should find a re-packaged build at ``OBJDIR/dist/``, and a runnable binary
in ``OBJDIR/dist/l10n-stage/``. The ``installers`` target runs quite a few
things for you, including getting the localizations from
https://github.com/mozilla-l10n/firefox-l10n (or updating it if already
present). It will clone them into ``~/.mozbuild/l10n-central``. If you prefer to
have the l10n repositories at a different location on your disk, you can point
to the directory via

   .. code-block:: shell

      ac_add_options --with-l10n-base=/make/this/a/absolute/path

This build also packages a language pack.

Instructions for language packs
-------------------------------

Language packs are extensions that contain just the localized resources. Building
them doesn't require an actual build, but they're only compatible with the
``mozilla-central`` source they're built with.


.. code-block:: shell

  ./mach build langpack-$AB_CD

This target shares much of the logic of the ``installers-$AB_CD`` target above,
and does the check-out of the localization repository etc. It doesn't require
a package or a build, though. The generated language pack is in
``OBJDIR/dist/$(MOZ_PKG_PLATFORM)/xpi/``.

.. note::

  Despite the platform-dependent location in the build directory, language packs
  are platform independent, and the content that goes into them needs to be
  built in a platform-independent way.

Instructions for multi-locale builds
------------------------------------

If you want to create a single build with multiple locales, you will do

#. Create a build and package

   .. code-block:: shell

      ./mach build
      ./mach package

#. Create the multi-locale package:

   .. code-block:: shell

      ./mach package-multi-locale --locales de it zh-TW

On Android, this produces a multi-locale GeckoView AAR and multi-locale APKs,
including GeckoViewExample.  You can test different locales by changing your
Android OS locale and restarting GeckoViewExample.  You'll need to install with
the ``MOZ_CHROME_MULTILOCALE`` variable set, like:

   .. code-block:: shell

       env MOZ_CHROME_MULTILOCALE=en-US,de,it,zh-TW ./mach android install-geckoview_example

Multi-locale builds without compiling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For deep technical reasons, artifact builds do not support multi-locale builds.
However, with a little work, we can achieve the same effect:

#. Arrange a ``mozconfig`` without a compilation environment but with support
   for the ``RecursiveMake`` build backend, like:

   .. code-block:: shell

      ac_add_options --disable-compile-environment
      export BUILD_BACKENDS=FasterMake,RecursiveMake
      ... other options ...

#. Configure.

   .. code-block:: shell

      ./mach configure

#. Manually provide compiled artifacts.

   .. code-block:: shell

      ./mach artifact install [-v]

#. Build.

   .. code-block:: shell

      ./mach build

#. Produce a multi-locale package.

   .. code-block:: shell

      ./mach package-multi-locale --locales de it zh-TW

This build configuration is fragile and not generally useful for active
development (for that, use a full/compiled build), but it certainly speeds
testing multi-locale packaging.

General flow of repacks
-----------------------

The general flow of the locale repacks is controlled by
``$MOZ_BUILD_APP/locales/Makefile.in`` and ``toolkit/locales/l10n.mk``, plus
the packaging build system. The three main entry points above all trigger
related build flows:

#. Get the localization repository, if needed
#. Run l10n-merge with a prior clobber of the merge dir
#. Copy l10n files to ``dist``, with minor differences here between ``l10n-%`` and ``chrome-%``
#. Repackage and package

Details on l10n-merge are described in its own section below.
The copying of files is mainly controlled by ``jar.mn``, in the few source
directories that include localizable files. ``l10n-%`` is used for repacks,
``chrome-%`` for multi-locale packages. The repackaging is dedicated
Python code in ``toolkit/mozapps/installer/l10n-repack.py``, using an existing
package. It strips existing ``chrome`` l10n resources, and adds localizations
and metadata.

Language packs don't require repackaging. The windows installers are generated
by merely packaging an existing repackaged zip into to an installer.

Exposing strings
================

The localization flow handles a few file formats in well-known locations in the
source tree.

Alongside being built by including the directory in ``$MOZ_BUILD_APP/locales/Makefile.in``
and respective entries in a ``jar.mn``, we also have configuration files tailored
to localization tools and infrastructure. They're also controlling which
files l10n-merge handles, and how.

These configurations are TOML files. They're part of the bigger
localization ecosystem at Mozilla, and `the documentation about the
file format <http://moz-l10n-config.readthedocs.io/en/latest/fileformat.html>`_
explains how to set them up, and what the entries mean. In short, you find

.. code-block:: text

   [paths]
   reference = browser/locales/en-US/**
   l10n = {l}browser/**

to add a directory for all localizations. Changes to these files are best
submitted for review by :Pike or :flod.

These configuration files are the future, and right now, we still have
support for the previous way to configuring l10n, which is described below.

The locations are commonly in directories like

    :file:`browser/`\ ``locales/en-US/``\ :file:`subdir/file.ext`

The first thing to note is that only files beneath :file:`locales/en-US` are
exposed to localizers. The second thing to note is that only a few directories
are exposed. Which directories are exposed is defined in files called
``l10n.ini``, which are at a
`few places <https://searchfox.org/mozilla-central/search?q=path%3Al10n.ini&redirect=true>`_
in the source code.

An example looks like this

.. code-block:: ini

    [general]
    depth = ../..

    [compare]
    dirs = browser
        browser/branding/official

    [includes]
    toolkit = toolkit/locales/l10n.ini

This tells the l10n infrastructure three things:

* resolve the paths against the directory two levels up
* include files in :file:`browser/locales/en-US` and
  :file:`browser/branding/official/locales/en-US`
* load more data from :file:`toolkit/locales/l10n.ini`

For projects like Thunderbird and SeaMonkey in ``comm-central``, additional
data needs to be provided when including an ``l10n.ini`` from a different
repository:

.. code-block:: ini

    [include_toolkit]
    type = hg
    mozilla = mozilla-central
    repo = https://hg.mozilla.org/
    l10n.ini = toolkit/locales/l10n.ini

This tells the l10n infrastructure where to find the repository, and where inside
that repository the ``l10n.ini`` file is. This is needed because for local
builds, :file:`mail/locales/l10n.ini` references
:file:`mozilla/toolkit/locales/l10n.ini`, which is where the comm-central
build setup expects toolkit to be.

Now that the directories exposed to l10n are known, we can talk about the
supported file formats.

File formats
------------

The following file formats are known to the l10n tool chains:

Fluent
    Used in Firefox UI, both declarative and programmatically.
Properties
    Used from JavaScript and C++. When used from js, also comes with
    plural support (avoid if possible).
ini
    Used by the crashreporter and updater, avoid if possible.

Adding new formats involves changing various different tools, and is strongly
discouraged.

Exceptions
----------
Generally, anything that exists in ``en-US`` needs a one-to-one mapping in
all localizations. There are a few cases where that's not wanted, notably
around locale configuration and locale-dependent metadata.

For optional strings and files, l10n-merge won't add ``en-US`` content if
the localization doesn't have that content.

For the TOML files, the
`[[filters]] documentation <https://moz-l10n-config.readthedocs.io/en/latest/fileformat.html#filters>`_
is a good reference. In short, filters match the localized source code, optionally
a ``key``, and an action. An example like

.. code-block:: toml

  [filters]
  path = "{l}calendar/chrome/calendar/calendar-event-dialog.properties"
  key = "re:.*Nounclass[1-9].*"
  action = "ignore"

indicates that the matching messages in ``calendar-event-dialog.properties`` are optional.

For the legacy ini configuration files, there's a Python module
``filter.py`` next to the main ``l10n.ini``, implementing :py:func:`test`, with the following
signature

.. code-block:: python

    def test(mod, path, entity = None):
        if does_not_matter:
            return "ignore"
        if show_but_do_not_merge:
            return "report"
        # default behavior, localizer or build need to do something
        return "error"

For any missing file, this function is called with ``mod`` being
the *module*, and ``path`` being the relative path inside
:file:`locales/en-US`. The module is the top-level dir as referenced in
:file:`l10n.ini`.

For missing strings, the :py:data:`entity` parameter is the key of the string
in the en-US file.

l10n-merge
==========

The chrome registry in Gecko doesn't support fallback from a localization to ``en-US`` at runtime.
Thus, the build needs to ensure that the localization as it's built into
the package has all required strings, and that the strings don't contain
errors. To ensure that, we're *merging* the localization and ``en-US``
at build time, nick-named l10n-merge.

For Fluent, we're also removing erroneous messages. For many errors in Fluent,
that's cosmetic, but when a localization has different values or attributes
on a message, that's actually important so that the DOM bindings of Fluent
can apply the translation without having to load the ``en-US`` source to
compare against.

The process can be manually triggered via

.. code-block:: bash

    $> ./mach build merge-$AB_CD

It creates another directory in the object dir, :file:`browser/locales/merge-dir/$AB_CD`, in
which the sanitized files are stored. The actual repackaging process only looks
in the merged directory, so the preparation steps of l10n-merge need to ensure
that all files are generated or copied.

l10n-merge modifies a file if it supports the particular file type, and there
are missing strings which are not filtered out, or if an existing string
shows an error. See the Checks section below for details. If the files are
not modified, l10n-merge copies them over to the respective location in the
merge dir.

Checks
------

As part of the build and other localization tool chains, we run a variety
of source-based checks. Think of them as linters.

The suite of checks is usually determined by file type, i.e., there's a
suite of checks for Fluent files and one for properties files, etc.

Localizations
-------------

Now that we talked in-depth about how to expose content to localizers,
where are the localizations?

We host all locales in a git monorepo. All of our
localizations can be found on https://github.com/mozilla-l10n/firefox-l10n.

You can search inside our localized files on
`Transvision <https://transvision.mozfr.org/>`_.

---

### Build Docs Mozbuild Files (`build/docs/mozbuild-files.rst`)

.. _mozbuild-files:

===============
moz.build Files
===============

``moz.build`` files are the mechanism by which tree metadata (notably
the build configuration) is defined.

Directories in the tree contain ``moz.build`` files which declare
functionality for their respective part of the tree. This includes
things such as the list of C++ files to compile, where to find tests,
etc.

``moz.build`` files are actually Python scripts. However, their
execution is governed by special rules. This is explained below.

moz.build Python Sandbox
========================

As mentioned above, ``moz.build`` files are Python scripts. However,
they are executed in a special Python *sandbox* that significantly
changes and limits the execution environment. The environment is so
different, it's doubtful most ``moz.build`` files would execute without
error if executed by a vanilla Python interpreter (e.g. ``python
moz.build``.

The following properties make execution of ``moz.build`` files special:

1. The execution environment exposes a limited subset of Python.
2. There is a special set of global symbols and an enforced naming
   convention of symbols.
3. Some symbols are inherited from previously-executed ``moz.build``
   files.

The limited subset of Python is actually an extremely limited subset.
Only a few symbols from ``__builtin__`` are exposed. These include
``True``, ``False``, ``None``, ``sorted``, ``int``, and ``set``. Global
functions like ``import``, ``print``, and ``open`` aren't available.
Without these, ``moz.build`` files can do very little. *This is by design*.

The execution sandbox treats all ``UPPERCASE`` variables specially. Any
``UPPERCASE`` variable must be known to the sandbox before the script
executes. Any attempt to read or write to an unknown ``UPPERCASE``
variable will result in an exception being raised. Furthermore, the
types of all ``UPPERCASE`` variables is strictly enforced. Attempts to
assign an incompatible type to an ``UPPERCASE`` variable will result in
an exception being raised.

The strictness of behavior with ``UPPERCASE`` variables is a very
intentional design decision. By ensuring strict behavior, any operation
involving an ``UPPERCASE`` variable is guaranteed to have well-defined
side-effects. Previously, when the build configuration was defined in
``Makefiles``, assignments to variables that did nothing would go
unnoticed. ``moz.build`` files fix this problem by eliminating the
potential for false promises.

After a ``moz.build`` file has completed execution, only the
``UPPERCASE`` variables are used to retrieve state.

The set of variables and functions available to the Python sandbox is
defined by the :py:mod:`mozbuild.frontend.context` module. The
data structures in this module are consumed by the
:py:class:`mozbuild.frontend.reader.MozbuildSandbox` class to construct
the sandbox. There are tests to ensure that the set of symbols exposed
to an empty sandbox are all defined in the ``context`` module.
This module also contains documentation for each symbol, so nothing can
sneak into the sandbox without being explicitly defined and documented.

Reading and Traversing moz.build Files
======================================

The process for reading ``moz.build`` files roughly consists of:

1. Start at the root ``moz.build`` (``<topsrcdir>/moz.build``).
2. Evaluate the ``moz.build`` file in a new sandbox.
3. Emit the main *context* and any *sub-contexts* from the executed
   sandbox.
4. Extract a set of ``moz.build`` files to execute next.
5. For each additional ``moz.build`` file, goto #2 and repeat until all
   referenced files have executed.

From the perspective of the consumer, the output of reading is a stream
of :py:class:`mozbuild.frontend.reader.context.Context` instances. Each
``Context`` defines a particular aspect of data. Consumers iterate over
these objects and do something with the data inside. Each object is
essentially a dictionary of all the ``UPPERCASE`` variables populated
during its execution.

.. note::

   Historically, there was only one ``context`` per ``moz.build`` file.
   As the number of things tracked by ``moz.build`` files grew and more
   and more complex processing was desired, it was necessary to split these
   contexts into multiple logical parts. It is now common to emit
   multiple contexts per ``moz.build`` file.

Build System Reading Mode
-------------------------

The traditional mode of evaluation of ``moz.build`` files is what's
called *build system traversal mode.* In this mode, the ``CONFIG``
variable in each ``moz.build`` sandbox is populated from data coming
from ``config.status``, which is produced by ``configure``.

During evaluation, ``moz.build`` files often make decisions conditional
on the state of the build configuration. e.g. *only compile foo.cpp if
feature X is enabled*.

In this mode, traversal of ``moz.build`` files is governed by variables
like ``DIRS`` and ``TEST_DIRS``. For example, to execute a child
directory, ``foo``, you would add ``DIRS += ['foo']`` to a ``moz.build``
file and ``foo/moz.build`` would be evaluated.

.. _mozbuild_fs_reading_mode:

Filesystem Reading Mode
-----------------------

There is an alternative reading mode that doesn't involve the build
system and doesn't use ``DIRS`` variables to control traversal into
child directories. This mode is called *filesystem reading mode*.

In this reading mode, the ``CONFIG`` variable is a dummy, mostly empty
object. Accessing all but a few special variables will return an empty
value. This means that nearly all ``if CONFIG['FOO']:`` branches will
not be taken.

Instead of using content from within the evaluated ``moz.build``
file to drive traversal into subsequent ``moz.build`` files, the set
of files to evaluate is controlled by the thing doing the reading.

A single ``moz.build`` file is not guaranteed to be executable in
isolation. Instead, we must evaluate all *parent* ``moz.build`` files
first. For example, in order to evaluate ``/foo/moz.build``, one must
execute ``/moz.build`` and have its state influence the execution of
``/foo/moz.build``.

Filesystem reading mode is utilized to power the
:ref:`mozbuild_files_metadata` feature.

Technical Details
-----------------

The code for reading ``moz.build`` files lives in
:py:mod:`mozbuild.frontend.reader`. The Python sandboxes evaluation results
(:py:class:`mozbuild.frontend.context.Context`) are passed into
:py:mod:`mozbuild.frontend.emitter`, which converts them to classes defined
in :py:mod:`mozbuild.frontend.data`. Each class in this module defines a
domain-specific component of tree metadata. e.g. there will be separate
classes that represent a JavaScript file vs a compiled C++ file or test
manifests. This means downstream consumers of this data can filter on class
types to only consume what they are interested in.

There is no well-defined mapping between ``moz.build`` file instances
and the number of :py:mod:`mozbuild.frontend.data` classes derived from
each. Depending on the content of the ``moz.build`` file, there may be 1
object derived or 100.

The purpose of the ``emitter`` layer between low-level sandbox execution
and metadata representation is to facilitate a unified normalization and
verification step. There are multiple downstream consumers of the
``moz.build``-derived data and many will perform the same actions. This
logic can be complicated, so we have a component dedicated to it.

:py:class:`mozbuild.frontend.reader.BuildReader`` and
:py:class:`mozbuild.frontend.reader.TreeMetadataEmitter`` have a
stream-based API courtesy of generators. When you hook them up properly,
the :py:mod:`mozbuild.frontend.data` classes are emitted before all
``moz.build`` files have been read. This means that downstream errors
are raised soon after sandbox execution.

Lots of the code for evaluating Python sandboxes is applicable to
non-Mozilla systems. In theory, it could be extracted into a standalone
and generic package. However, until there is a need, there will
likely be some tightly coupled bits.

---

### Build Docs Mozbuild Symbols (`build/docs/mozbuild-symbols.rst`)

.. _mozbuild_symbols:

========================
mozbuild Sandbox Symbols
========================

.. rstcheck: ignore-directives=mozbuildsymbols
.. mozbuildsymbols:: mozbuild.frontend.context

---

### Build Docs Mozconfigs (`build/docs/mozconfigs.rst`)

.. _mozconfig:

===============
mozconfig Files
===============

mozconfig files are used to configure how a build works.

mozconfig files are actually shell scripts. They are executed in a
special context with specific variables and functions exposed to them.

API
===

Functions
---------

The following special functions are available to a mozconfig script.

ac_add_options
^^^^^^^^^^^^^^

This function is used to declare extra options/arguments to pass into
configure.

e.g.::

    ac_add_options --disable-tests
    ac_add_options --enable-optimize

mk_add_options
^^^^^^^^^^^^^^

This function is used to inject statements into client.mk for execution.
It is typically used to define variables, notably the object directory.

e.g.::

    mk_add_options AUTOCLOBBER=1

Special mk_add_options Variables
--------------------------------

For historical reasons, the method for communicating certain
well-defined variables is via mk_add_options(). In this section, we
document what those special variables are.

MOZ_OBJDIR
^^^^^^^^^^

This variable is used to define the :term:`object directory` for the current
build.

Finding the active mozconfig
============================

Multiple mozconfig files can exist to provide different configuration
options for different tasks. The rules for finding the active mozconfig
are defined in the
:py:func:`mozboot.mozconfig.find_mozconfig` method.

.. automodule:: mozboot.mozconfig
   :members: find_mozconfig

Loading the active mozconfig
----------------------------

.. autoclass:: mozbuild.mozconfig.MozconfigLoader
   :members: read_mozconfig

---

### Build Docs Mozinfo (`build/docs/mozinfo.rst`)

.. _mozinfo:

=======
mozinfo
=======

``mozinfo`` is a solution for representing a subset of build
configuration and run-time data.

``mozinfo`` data is typically accessed through a ``mozinfo.json`` file
which is written to the :term:`object directory` during build
configuration. The code for writing this file lives in
:py:mod:`mozbuild.mozinfo`.

``mozinfo.json`` is an object/dictionary of simple string values.

The attributes in ``mozinfo.json`` are used for many purposes. One use
is to filter tests for applicability to the current build. For more on
this, see :ref:`test_manifests`.

.. _mozinfo_attributes:

mozinfo.json Attributes
=================================

``mozinfo`` currently records the following attributes.

appname
   The application being built.

   Value comes from ``MOZ_APP_NAME`` from ``config.status``.

   Optional.

asan
   Whether address sanitization is enabled.

   Values are ``true`` and ``false``.

   Always defined.

bin_suffix
   The file suffix for binaries produced with this build.

   Values may be an empty string, as not all platforms have a binary
   suffix.

   Always defined.

bits
   The number of bits in the CPU this build targets.

   Values are typically ``32`` or ``64``.

   Universal Mac builds do not have this key defined.

   Unknown processor architectures (see ``processor`` below) may not have
   this key defined.

   Optional.

buildapp
   The path to the XUL application being built.

   For desktop Firefox, this is ``browser``. For Fennec, it's
   ``mobile/android``.

crashreporter
   Whether the crash reporter is enabled for this build.

   Values are ``true`` and ``false``.

   Always defined.

datareporting
   Whether data reporting (MOZ_DATA_REPORTING) is enabled for this build.

   Values are ``true`` and ``false``.

   Always defined.

debug
   Whether this is a debug build.

   Values are ``true`` and ``false``.

   Always defined.

devedition
   Whether this is a devedition build.

   Values are ``true`` and ``false``.

   Always defined.

healthreport
   Whether the Health Report feature is enabled.

   Values are ``true`` and ``false``.

   Always defined.

mozconfig
   The path of the :ref:`mozconfig file <mozconfig>` used to produce this build.

   Optional.

nightly_build
   Whether this is a nightly build.

   Values are ``true`` and ``false``.

   Always defined.

os
   The operating system the build is produced for. Values for tier-1
   supported platforms are ``linux``, ``win``, ``mac``, and
   ``android``. For other platforms, the value is the lowercase version
   of the ``OS_TARGET`` variable from ``config.status``.

   Always defined.

processor
   Information about the processor architecture this build targets.

   Values come from ``TARGET_CPU``, however some massaging may be
   performed.

   If the build is a universal build on Mac (it targets both 32-bit and
   64-bit), the value is ``universal-x86-x86_64``.

   If the value starts with ``arm``, the value is ``arm``.

   If the value starts with a string of the form ``i[3-9]86]``, the
   value is ``x86``.

   Always defined.

release_or_beta
   Whether this is a release or beta build.

   Values are ``true`` and ``false``.

   Always defined.

stylo
   Whether the Stylo styling system is being used.

   Values are ``true`` and ``false``.

   Always defined.

tests_enabled
   Whether tests are enabled for this build.

   Values are ``true`` and ``false``.

   Always defined.

toolkit
   The widget toolkit in case. The value comes from the
   ``MOZ_WIDGET_TOOLKIT`` ``config.status`` variable.

   Always defined.

topsrcdir
   The path to the source directory the build came from.

   Always defined.

topobjdir
   The path to the obj directory the build came from.

   Always defined.

webrender
   Whether or not WebRender is enabled as the Gecko compositor.

   Values are ``true`` and ``false``.

   Always defined.

---

### Build Docs Pgo (`build/docs/pgo.rst`)

.. _pgo:

===========================
Profile Guided Optimization
===========================

:abbr:`PGO (Profile Guided Optimization)` is the process of adding
probes to a compiled binary, running said binary, then using the
run-time information to *recompile* the binary to (hopefully) make it
faster.

How PGO Builds Work
===================

The supported interface for invoking a PGO build is to add ``MOZ_PGO=1`` to
configure flags and then build. e.g. in your mozconfig::

    ac_add_options MOZ_PGO=1

Then::

    $ ./mach build

This is roughly equivalent to::

#. Perform a build with *--enable-profile-generate* in $topobjdir/instrumented
#. Perform a run of the instrumented binaries with build/pgo/profileserver.py
#. Perform a build with *--enable-profile-use* in $topobjdir

---

### Build Docs Preprocessor (`build/docs/preprocessor.rst`)

.. _preprocessor:

=================
Text Preprocessor
=================

The build system contains a text preprocessor similar to the C preprocessor,
meant for processing files which have no built-in preprocessor such as XUL
and JavaScript documents. It is implemented at ``python/mozbuild/mozbuild/preprocessor.py`` and
is typically invoked via :ref:`jar_manifests`.

While used to preprocess CSS files, the directives are changed to begin with
``%`` instead of ``#`` to avoid conflict of the id selectors.

Directives
==========

Variable Definition
-------------------

define
^^^^^^

::

   #define variable
   #define variable value

Defines a preprocessor variable.

Note that, unlike the C preprocessor, instances of this variable later in the
source are not automatically replaced (see #filter). If value is not supplied,
it defaults to ``1``.

Note that whitespace is significant, so ``"#define foo one"`` and
``"#define foo one "`` is different (in the second case, ``foo`` is defined to
be a four-character string).

undef
^^^^^

::

   #undef variable

Undefines a preprocessor variable.

Conditionals
------------

if
^^

::

   #if variable
   #if !variable
   #if variable == string
   #if variable != string

Disables output if the conditional is false. This can be nested to arbitrary
depths. Note that in the equality checks, the variable must come first.

else
^^^^

::

   #else

Reverses the state of the previous conditional block; for example, if the
last ``#if`` was true (output was enabled), an ``#else`` makes it off
(output gets disabled).

endif
^^^^^

::

   #endif

Ends the conditional block.

ifdef / ifndef
^^^^^^^^^^^^^^

::

   #ifdef variable
   #ifndef variable

An ``#if`` conditional that is true only if the preprocessor variable
variable is defined (in the case of ``ifdef``) or not defined (``ifndef``).

elif / elifdef / elifndef
^^^^^^^^^^^^^^^^^^^^^^^^^

::

   #elif variable
   #elif !variable
   #elif variable == string
   #elif variable != string
   #elifdef variable
   #elifndef variable

A shorthand to mean an ``#else`` combined with the relevant conditional.
The following two blocks are equivalent::

   #ifdef foo
     block 1
   #elifdef bar
     block 2
   #endif

::

   #ifdef foo
     block 1
   #else
   #ifdef bar
     block 2
   #endif
   #endif

File Inclusion
--------------

include
^^^^^^^

::

   #include filename

The file specified by filename is processed as if the contents was placed
at this position. This also means that preprocessor conditionals can even
be started in one file and ended in another (but is highly discouraged).
There is no limit on depth of inclusion, or repeated inclusion of the same
file, or self inclusion; thus, care should be taken to avoid infinite loops.

includesubst
^^^^^^^^^^^^

::

   #includesubst @variable@filename

Same as a ``#include`` except that all instances of variable in the included
file is also expanded as in ``#filter`` substitution

expand
^^^^^^

::

   #expand string

All variables wrapped in ``__`` are replaced with their value, for this line
only. If the variable is not defined, it expands to an empty string. For
example, if ``foo`` has the value ``bar``, and ``baz`` is not defined, then::

   #expand This <__foo__> <__baz__> gets expanded

Is expanded to::

   This <bar> <> gets expanded

filter / unfilter
^^^^^^^^^^^^^^^^^

::

   #filter filter1 filter2 ... filterN
   #unfilter filter1 filter2 ... filterN

``#filter`` turns on the given filter.

Filters are run in alphabetical order on a per-line basis.

``#unfilter`` turns off the given filter. Available filters are:

emptyLines
   strips blank lines from the output
dumbComments
    dumbComments: empties out any line that consists of optional whitespace
    followed by a ``//``. Good for getting rid of comments that are on their
    own lines, and being smarter with a simple regexp filter is impossible
substitution
   all variables wrapped in @ are replaced with their value. If the
   variable is not defined, it is a fatal error. Similar to ``#expand``
   and ``#filter``
attemptSubstitution
   all variables wrapped in ``@`` are replaced with their value, or an
   empty string if the variable is not defined. Similar to ``#expand``.

literal
^^^^^^^

::

   #literal string

Output the string (i.e. the rest of the line) literally, with no other fixups.
This is useful to output lines starting with ``#``, or to temporarily
disable filters.

Other
-----

#error
^^^^^^

::

   #error string

Cause a fatal error at this point, with the error message being the
given string.

---

### Build Docs Python (`build/docs/python.rst`)

.. _python:

===========================
Python and the Build System
===========================

The Python programming language is used significantly in the build
system. If we need to write code for the build system or for a tool
related to the build system, Python is typically the first choice.

Python Requirements
===================

The tree requires Python 3.9 or greater to build.
All Python packages not in the Python distribution are included in the
source tree. So all you should need is a vanilla Python install and you
should be good to go.

Only CPython (the Python distribution available from www.python.org) is
supported.

Compiled Python Packages
========================

There are some features of the build that rely on compiled Python packages
(packages containing C source). These features are currently all
optional because not every system contains the Python development
headers required to build these extensions.

We recommend you have the Python development headers installed (``mach
bootstrap`` should do this for you) so you can take advantage of these
features.

Issues with OS X System Python
==============================

The Python that ships with OS X has historically been littered with
subtle bugs and suboptimalities.

OS X 10.8 and below users will be required to install a new Python
distribution. This may not be necessary for OS X 10.9+. However, we
still recommend installing a separate Python because of the history with
OS X's system Python issues.

We recommend installing Python through Homebrew or MacPorts. If you run
``mach bootstrap``, this should be done for you.

Virtual Environments
====================

The build system relies heavily on
`venv <https://docs.python.org/3/library/venv.html>`_. Venv provides
standalone and isolated Python "virtual environments". The problem a venv
solves is that of dependencies across multiple Python components. If two
components on a system relied on different versions of a package, there
could be a conflict. Instead of managing multiple versions of a package
simultaneously, Python and venv take the route that it is easier
to just keep them separate so there is no potential for conflicts.

Very early in the build process, a venv is created inside the
:term:`object directory`. The venv is configured such that it can
find all the Python packages in the source tree. The code for this lives
in ``mach.site``.

Deficiencies
------------

There are numerous deficiencies with the way virtual environments are
handled in the build system.

* mach reinvents the venv.

  There is code in ``build/mach_initialize.py`` that configures ``sys.path``
  much the same way the venv does. There are various bugs tracking
  this. However, no clear solution has yet been devised. It's not a huge
  problem and thus not a huge priority.

* They aren't preserved across copies and packaging.

  If you attempt to copy an entire tree from one machine to another or
  from one directory to another, chances are the venv will fall
  apart. It would be nice if we could preserve it somehow. Instead of
  actually solving portable venv, all we really need to solve is
  encapsulating the logic for populating the venv along with all
  dependent files in the appropriate place.

* .pyc files written to source directory.

  We rely heavily on ``.pth`` files in our venv. A ``.pth`` file
  is a special file that contains a list of paths. Python will take the
  set of listed paths encountered in ``.pth`` files and add them to
  ``sys.path``.

  When Python compiles a ``.py`` file to bytecode, it writes out a
  ``.pyc`` file so it doesn't have to perform this compilation again.
  It puts these ``.pyc`` files alongside the ``.pyc`` file. Python
  provides very little control for determining where these ``.pyc`` files
  go, even in Python 3 (which offers customer importers).

  With ``.pth`` files pointing back to directories in the source tree
  and not the object directory, ``.pyc`` files are created in the source
  tree. This is bad because when Python imports a module, it first looks
  for a ``.pyc`` file before the ``.py`` file. If there is a ``.pyc``
  file but no ``.py`` file, it will happily import the module. This
  wreaks havoc during file moves, refactoring, etc.

  There are various proposals for fixing this. See bug 795995.

Installing Python Manually
==========================

We highly recommend you use your system's package manager or a
well-supported 3rd party package manager to install Python for you. If
these are not available to you, we recommend the following tools for
installing Python:

* `buildout.python <https://github.com/collective/buildout.python>`_
* `pyenv <https://github.com/yyuu/pyenv>`_
* An official installer from http://www.python.org.

If all else fails, consider compiling Python from source manually. But this
should be viewed as the least desirable option.

Common Issues with Python
=========================

Upgrading your Python distribution breaks the venv
--------------------------------------------------------

If you upgrade the Python distribution (e.g. install Python 3.6.15
from 3.6.9), chances are parts of the venv will break.
This commonly manifests as a cryptic ``Cannot import XXX`` exception.
More often than not, the module being imported contains binary/compiled
components.

If you upgrade or reinstall your Python distribution, we recommend
clobbering your build.

Packages installed at the system level conflict with build system's
-------------------------------------------------------------------

It is common for people to install Python packages using ``sudo`` (e.g.
``sudo pip install psutil``) or with the system's package manager
(e.g. ``apt-get install python-mysql``.

A problem with this is that packages installed at the system level may
conflict with the package provided by the source tree. As of bug 907902
and changeset f18eae7c3b27 (September 16, 2013), this should no longer
be an issue since the venv created as part of the build doesn't
add the system's ``site-packages`` directory to ``sys.path``. However,
poorly installed packages may still find a way to creep into the mix and
interfere with our venv.

As a general principle, we recommend against using your system's package
manager or using ``sudo`` to install Python packages. Instead, create
virtual environments and isolated Python environments for all of your
Python projects.

Python on $PATH is not appropriate
----------------------------------

Tools like ``mach`` will look for Python by performing ``/usr/bin/env
python`` or equivalent. Please be sure the appropriate Python 2.7.3+
path is on $PATH. On OS X, this likely means you'll need to modify your
shell's init script to put something ahead of ``/usr/bin``.

---

### Build Docs Rust (`build/docs/rust.rst`)

.. _rust:

==============================
Including Rust Code in Firefox
==============================

This page explains how to add, build, link, and vendor Rust crates.

The `code documentation <../../writing-rust-code>`_ explains how to write and
work with Rust code in Firefox. The
`test documentation <../../testing-rust-code>`_ explains how to test and debug
Rust code in Firefox.

Linking Rust crates into libxul
===============================

Rust crates that you want to link into libxul should be listed in the
``dependencies`` section of
:searchfox:`toolkit/library/rust/shared/Cargo.toml`.
You must also add an ``extern crate`` reference to
:searchfox:`toolkit/library/rust/shared/lib.rs`.
This ensures that the Rust code will be linked properly into libxul as well
as the copy of libxul used for gtests. (Even though Rust 2018 mostly doesn't
require ``extern crate`` declarations, these ones are necessary because the
gkrust setup is non-typical.)

After adding your crate, execute ``cargo update -p gkrust-shared`` to update
the ``Cargo.lock`` file. You will also need to do this any time you change the
dependencies in a ``Cargo.toml`` file. If you don't, you will get a build error
saying **"error: the lock file /home/njn/moz/mc3/Cargo.lock needs to be updated
but --frozen was passed to prevent this"**.

By default, all Cargo packages in the mozilla-central repository are part of
the same
:searchfox:`workspace <toolkit/library/rust/shared/lib.rs>`
and will share the ``Cargo.lock`` file and ``target`` directory in the root of
the repository.  You can change this behavior by adding a path to the
``exclude`` list in the top-level ``Cargo.toml`` file.  You may want to do
this if your package's development workflow includes dev-dependencies that
aren't needed by general Firefox developers or test infrastructure.

The actual build mechanism is as follows. The build system generates a special
'Rust unified library' crate, compiles that to a static library
(``libgkrust.a``), and links that into libxul, so all public symbols will be
available to C++ code. Building a static library that is linked into a dynamic
library is easier than building dynamic libraries directly, and it also avoids
some subtle issues around how mozalloc works that make the Rust dynamic library
path a little wonky.

Linking Rust crates into something else
=======================================

To link Rust code into libraries other than libxul, create a directory with a
``Cargo.toml`` file for your crate, and a ``moz.build`` file that contains:

.. code-block:: python

    RustLibrary('crate_name')

where ``crate_name`` matches the name from the ``[package]`` section of your
``Cargo.toml``. You can refer to :searchfox:`the moz.build file <mozilla-central/rev/603b9fded7a11ff213c0f415198cd637b7c86614:toolkit/library/rust/moz.build#9>` and :searchfox:`the Cargo.toml file <mozilla-central/rev/603b9fded7a11ff213c0f415198cd637b7c86614:toolkit/library/rust/Cargo.toml>` that are used for libxul.

You can then add ``USE_LIBS += ['crate_name']`` to the ``moz.build`` file
that defines the binary as you would with any other library in the tree.

.. important::

    You cannot link a Rust crate into an intermediate library that will be
    eventually linked into libxul. The build system enforces that only a single
    ``RustLibrary`` may be linked into a binary. If you need to do this, you
    will have to add a ``RustLibrary`` to link to any standalone binaries that
    link the intermediate library, and also add the Rust crate to the libxul
    dependencies as in `linking Rust Crates into libxul`_.

Conditional compilation
========================

Edit :searchfox:`tool/library/rust/gkrust-features.mozbuild <toolkit/library/rust/gkrust-features.mozbuild>`
to expose build flags as Cargo features.

Standalone Rust programs
========================

It is also possible to build standalone Rust programs. First, put the Rust
program (including the ``Cargo.toml`` file and the ``src`` directory) in its
own directory, and add an empty ``moz.build`` file to the same directory.

Then, if the standalone Rust program must run on the compile target (e.g.
because it's shipped with Firefox) then add this rule to the ``moz.build``
file:

.. code-block:: python

    RUST_PROGRAMS = ['prog_name']

where *prog_name* is the name of the executable as specified in the
``Cargo.toml`` (and probably also matches the name of the directory).

Otherwise, if the standalone Rust program must run on the compile host (e.g.
because it's used to build Firefox but not shipped with Firefox) then do the
same thing, but use ``HOST_RUST_PROGRAMS`` instead of ``RUST_PROGRAMS``.

Where should I put my crate?
============================

If your crate's canonical home is mozilla-central, you can put it next to the
related code in the appropriate directory.

If your crate is mirrored into mozilla-central from another repository, and
will not be actively developed in mozilla-central, you can simply list it
as a ``crates.io``-style dependency with a version number, and let it be
vendored into the ``third_party/rust`` directory.

If your crate is mirrored into mozilla-central from another repository, but
will be actively developed in both locations, you should send mail to the
dev-builds mailing list to start a discussion on how to meet your needs.

Third-party crate dependencies
==============================

Third-party dependencies for in-tree Rust crates are *vendored* into the
``third_party/rust`` directory of mozilla-central. This means that a copy of
each third-party crate's code is committed into mozilla-central. As a result,
building Firefox does not involve downloading any third-party crates.

If you add a dependency on a new crate you must run ``mach vendor rust`` to
vendor the dependencies into that directory. (Note that ``mach vendor rust``
`may not work as well on Windows <https://bugzilla.mozilla.org/show_bug.cgi?id=1938341>`_
as on other platforms.)

When it comes to checking the suitability of third-party code for inclusion
into mozilla-central, keep the following in mind.

- ``mach vendor rust`` will check that the licenses of all crates are suitable.
- ``mach vendor rust`` will run ``cargo vet`` to ensure that the crates have been audited. If not,
  you will have to audit them using ``mach cargo vet`` to check that the code looks reasonable
  (especially unsafe code) and that there are reasonable tests. All vendored crates must be audited.
- Third-party crate tests aren't run, which means that large test fixtures will
  bloat mozilla-central. Consider working with upstream to mark those test
  fixtures with ``[package] exclude = ...`` as described
  `here <https://doc.rust-lang.org/cargo/reference/manifest.html#the-exclude-and-include-fields>`_.
- If you specify a dependency on a branch, pin it to a specific revision,
  otherwise other people will get unexpected changes when they run ``./mach
  vendor rust`` any time the branch gets updated. See `bug 1612619
  <https://bugzil.la/1612619>`_ for a case where such a problem was fixed.
- Other than that, there is no formal sign-off procedure, but one may be added
  in the future.

Note that all dependencies will be vendored, even ones that aren't used due to
disabled features. It's possible that multiple versions of a crate will end up
vendored into mozilla-central.

Patching third-party crates
===========================

Sometimes you might want to temporarily patch a third-party crate, for local
builds or for a try push.

To do this, first add an entry to the ``[patch.crates-io]`` section of the
top-level ``Cargo.toml`` that points to the crate within ``third_party``. For
example

.. code-block:: toml

    bitflags = { path = "third_party/rust/bitflags" }

Next, run ``cargo update -p $CRATE_NAME --precise $VERSION``, where
``$CRATE_NAME`` is the name of the patched crate, and ``$VERSION`` is its
version number. This will update the ``Cargo.lock`` file.

Then, make the local changes to the crate.

Finally, make sure you don't accidentally land the changes to the crate or the
``Cargo.lock`` file.

For an example of a more complex workflow involving a third-party crate, see
:searchfox:`mp4parse-rust/README.md <media/mp4parse-rust/README.md>`.
It describes the workflow for a crate that is hosted on GitHub, and for which
changes are made via GitHub pull requests, but all pull requests must also be
tested within mozilla-central before being merged.

---

### Build Docs Sccache Dist (`build/docs/sccache-dist.rst`)

.. _sccache_dist:

==================================
Distributed sccache (sccache-dist)
==================================

`sccache <https://github.com/mozilla/sccache>`_ is a ccache-like tool written in
Rust by Mozilla and many contributors.

sccache-dist, its distributed variant, elevates this functionality by enabling
the distribution and caching of Rust compilations across multiple machines.
Please consider using sccache-dist when you have several machines
compiling Firefox on the same network.

The steps for setting up your machine as an sccache-dist server are detailed below.

In addition to improved security properties, distributed sccache offers
distribution and caching of rust compilation, so it should be an improvement
above and beyond what we see with icecc. Build servers run on Linux and
distributing builds is currently supported from Linux, macOS, and Windows.


Steps for distributing a build as an sccache-dist client
========================================================

Start by following the instructions at https://github.com/mozilla/sccache/blob/master/docs/DistributedQuickstart.md#configure-a-client
to configure your sccache distributed client.
*NOTE* If you're distributing from Linux a toolchain will be packaged
automatically and provided to the build server. If you're distributing from
Windows or macOS, start by using the cross-toolchains provided by
``./mach bootstrap`` rather than attempting to use ``icecc-create-env``.
sccache 0.2.12 or above is recommended, and the auth section of your config
must read::

    [dist.auth]
    type = "mozilla"

* If you're compiling from a macOS client, there are a handful of additional
  considerations outlined here:
  https://github.com/mozilla/sccache/blob/master/docs/DistributedQuickstart.md#considerations-when-distributing-from-macos.

  Run ``./mach bootstrap`` to download prebuilt toolchains to
  ``~/.mozbuild/clang-dist-toolchain.tar.xz`` and
  ``~/.mozbuild/rustc-dist-toolchain.tar.xz``. This is an example of the paths
  that should be added to your client config to specify toolchains to build on
  macOS, located at ``~/Library/Application Support/Mozilla.sccache/config``::

    [[dist.toolchains]]
    type = "path_override"
    compiler_executable = "/path/to/home/.rustup/toolchains/stable-x86_64-apple-darwin/bin/rustc"
    archive = "/path/to/home/.mozbuild/rustc-dist-toolchain.tar.xz"
    archive_compiler_executable = "/builds/worker/toolchains/rustc/bin/rustc"

    [[dist.toolchains]]
    type = "path_override"
    compiler_executable = "/path/to/home/.mozbuild/clang/bin/clang"
    archive = "/path/to/home/.mozbuild/clang-dist-toolchain.tar.xz"
    archive_compiler_executable = "/builds/worker/toolchains/clang/bin/clang"

    [[dist.toolchains]]
    type = "path_override"
    compiler_executable = "/path/to/home/.mozbuild/clang/bin/clang++"
    archive = "/path/to/home/.mozbuild/clang-dist-toolchain.tar.xz"
    archive_compiler_executable = "/builds/worker/toolchains/clang/bin/clang"

  Note that the version of ``rustc`` found in ``rustc-dist-toolchain.tar.xz``
  must match the version of ``rustc`` used locally. The distributed archive
  will contain the version of ``rustc`` used by automation builds, which may
  lag behind stable for a few days after Rust releases, which is specified by
  the task definition in
  `this file <https://hg.mozilla.org/mozilla-central/file/tip/taskcluster/kinds/toolchain/dist-toolchains.yml>`_.
  For instance, to specify 1.37.0 rather than the current stable, run
  ``rustup toolchain add 1.37.0`` and point to
  ``/path/to/home/.rustup/toolchains/1.37.0-x86_64-apple-darwin/bin/rustc`` in your
  client config.

  The build system currently requires an explicit target to be passed with
  ``HOST_CFLAGS`` and ``HOST_CXXFLAGS`` e.g.::

    export HOST_CFLAGS="--target=x86_64-apple-darwin16.0.0"
    export HOST_CXXFLAGS="--target=x86_64-apple-darwin16.0.0"

* Compiling from a Windows client is supported but hasn't seen as much testing
  as other platforms. The following example mozconfig can be used as a guide::

    ac_add_options CCACHE="C:/Users/<USER>/.mozbuild/sccache/sccache.exe"

    export CC="C:/Users/<USER>/.mozbuild/clang/bin/clang-cl.exe --driver-mode=cl"
    export CXX="C:/Users/<USER>/.mozbuild/clang/bin/clang-cl.exe --driver-mode=cl"
    export HOST_CC="C:/Users/<USER>/.mozbuild/clang/bin/clang-cl.exe --driver-mode=cl"
    export HOST_CXX="C:/Users/<USER>/.mozbuild/clang/bin/clang-cl.exe --driver-mode=cl"

  The client config should be located at
  ``~/AppData/Roaming/Mozilla/sccache/config/config``, and as on macOS custom
  toolchains should be obtained with ``./mach bootstrap`` and specified in the
  client config, for example::

    [[dist.toolchains]]
    type = "path_override"
    compiler_executable = "C:/Users/<USER>/.mozbuild/clang/bin/clang-cl.exe"
    archive = "C:/Users/<USER>/.mozbuild/clang-dist-toolchain.tar.xz"
    archive_compiler_executable = "/builds/worker/toolchains/clang/bin/clang"

    [[dist.toolchains]]
    type = "path_override"
    compiler_executable = "C:/Users/<USER>/.rustup/toolchains/stable-x86_64-pc-windows-msvc/bin/rustc.exe"
    archive = "C:/Users/<USER>/.mozbuild/rustc-dist-toolchain.tar.xz"
    archive_compiler_executable = "/builds/worker/toolchains/rustc/bin/rustc"

* Add the following to your mozconfig::

    ac_add_options CCACHE=/path/to/home/.mozbuild/sccache/sccache

  If you're compiling from a macOS client, you might need some additional configuration::

    # Set the target flag to Darwin
    export CFLAGS="--target=x86_64-apple-darwin16.0.0"
    export CXXFLAGS="--target=x86_64-apple-darwin16.0.0"
    export HOST_CFLAGS="--target=x86_64-apple-darwin16.0.0"
    export HOST_CXXFLAGS="--target=x86_64-apple-darwin16.0.0"

    # Specify the macOS SDK to use
    ac_add_options --with-macos-sdk=/path/to/MacOSX-SDKs/MacOSX13.3.sdk

  You can get the right macOS SDK by downloading an old version of XCode from
  `developer.apple.com <https://developer.apple.com>`_ and unpacking the SDK
  from it.

* When attempting to get your client running, the output of ``sccache -s`` should
  be consulted to confirm compilations are being distributed. To receive helpful
  logging from the local daemon in case they aren't, run
  ``SCCACHE_NO_DAEMON=1 SCCACHE_START_SERVER=1 SCCACHE_LOG=sccache=trace path/to/sccache``
  in a terminal window separate from your build prior to building. *NOTE* use
  ``RUST_LOG`` instead of ``SCCACHE_LOG`` if your build of ``sccache`` does not
  include `pull request 822
  <https://github.com/mozilla/sccache/pull/822>`_. (``sccache`` binaries from
  ``mach bootstrap`` do include this PR.)

* Run ``./mach build -j<value>`` with an appropriately large ``<value>``.
  ``sccache --dist-status`` should provide the number of cores available to you
  (or a message if you're not connected). In the future this will be integrated
  with the build system to automatically select an appropriate value.

This should be enough to distribute your build and replace your use of icecc.
Bear in mind there may be a few speedbumps, and please ensure your version of
sccache is current before investigating further. Please see the common questions
section below and ask for help if anything is preventing you from using it over
email (dev-builds), on slack in #sccache, or in #build on irc.

Steps for setting up a server
=============================

Build servers must run linux and use bubblewrap 0.3.0+ for sandboxing of compile
processes. This requires a kernel 4.6 or greater, so Ubuntu 18+, RHEL 8, or
similar.

* Run ``./mach bootstrap`` or
  ``./mach artifact toolchain --from-build linux64-sccache`` to acquire a recent
  version of ``sccache-dist``. Please use a ``sccache-dist`` binary acquired in
  this fashion to ensure compatibility with statically linked dependencies.

* The instructions at https://github.com/mozilla/sccache/blob/master/docs/DistributedQuickstart.md#configure-a-build-server
  should contain everything else required to configure and run the server.

  *NOTE* Port 10500 will be used by convention for builders.
  Please use port 10500 in the ``public_addr`` section of your builder config.

  Extra logging may be helpful when setting up a server. To enable logging,
  run your server with
  ``sudo env SCCACHE_LOG=sccache=trace ~/.mozbuild/sccache/sccache-dist server --config ~/.config/sccache/server.conf``
  (or similar). *NOTE* ``sudo`` *must* come before setting environment variables
  for this to work. *NOTE* use ``RUST_LOG`` instead of ``SCCACHE_LOG`` if your
  build of ``sccache`` does not include `pull request 822
  <https://github.com/mozilla/sccache/pull/822>`_. (``sccache`` binaries from
  ``mach bootstrap`` do include this PR.)


Common questions/considerations
===============================

* My build is still slow: scache-dist can only do so much with parts of the
  build that aren't able to be parallelized. To start debugging a slow build,
  ensure the "Successful distributed compilations" line in the output of
  ``sccache -s`` dominates other counts. For a full build, at least a 2-3x
  improvement should be observed.

* My build output is incomprehensible due to a flood of warnings: clang will
  treat some warnings differently when it's fed preprocessed code in a separate
  invocation (preprocessing occurs locally with sccache-dist). Adding
  ``rewrite_includes_only = true`` to the ``dist`` section of your client config
  will improve this; however, setting this will cause build failures with a
  commonly deployed version of ``glibc``. This option will default to ``true``
  once the fix is more widely available. Details of this fix can be found in
  `this patch <https://sourceware.org/ml/libc-alpha/2019-11/msg00431.html>`_.

* My build fails with a message about incompatible versions of rustc between
  dependent crates: if you're using a custom toolchain check that the version
  of rustc in your ``rustc-dist-toolchain.tar.xz`` is the same as the version
  you're running locally.

---

### Build Docs Slow (`build/docs/slow.rst`)

.. _slow:

==================================
Why the Build System might be slow
==================================

A common complaint about the build system is that it can be slow. There are
many reasons contributing to its slowness.
However, on modern hardware, Firefox can be built in less than 10 minutes.

First, it is important to distinguish between a :term:`clobber build`
and an :term:`incremental build`. The reasons for why each are slow can
be different.

The build does a lot of work
============================

It may not be obvious, but the main reason the build system is slow is
because it does a lot of work! The source tree consists of a few
thousand C++ files. On a modern machine, we spend over 120 minutes of CPU
core time compiling files! So, if you are looking for the root cause of
slow clobber builds, look at the sheer volume of C++ files in the tree.

You don't have enough CPU cores and MHz
=======================================

The build should be CPU bound. If the build system maintainers are
optimizing the build system perfectly, every CPU core in your machine
should be 100% saturated during a build. While this isn't currently the
case (keep reading below), generally speaking, the more CPU cores you
have in your machine and the more total MHz in your machine, the better.

**We highly recommend building with no fewer than 4 physical CPU
cores.** Please note the *physical* in this sentence. Hyperthreaded
cores (an Intel Core i7 will report 8 CPU cores but only 4 are physical
for example) only yield at most a 1.25x speedup per core.

This cause impacts both clobber and incremental builds.

You are building with a slow I/O layer
======================================

The build system can be I/O bound if your I/O layer is slow. Linking
libxul on some platforms and build architectures can perform gigabytes
of I/O.

To minimize the impact of slow I/O on build performance, **we highly
recommend building with an SSD.** Power users with enough memory may opt
to build from a RAM disk. Mechanical disks should be avoided if at all
possible.

Some may dispute the importance of an SSD on build times. It is true
that the beneficial impact of an SSD can be mitigated if your system has
lots of memory and the build files stay in the page cache. However,
operating system memory management is complicated. You don't really have
control over what or when something is evicted from the page cache.
Therefore, unless your machine is a dedicated build machine or you have
more memory than is needed by everything running on your machine,
chances are you'll run into page cache eviction and you I/O layer will
impact build performance. That being said, an SSD certainly doesn't
hurt build times. And, anyone who has used a machine with an SSD will
tell you how great of an investment it is for performance all around the
operating system. On top of that, some automated tests are I/O bound
(like those touching SQLite databases), so an SSD will make tests
faster.

This cause impacts both clobber and incremental builds.

You don't have enough memory
============================

The build system allocates a lot of memory, especially when building
many things in parallel. If you don't have enough free system memory,
the build will cause swap activity, slowing down your system and the
build. Even if you never get to the point of swapping, the build system
performs a lot of I/O and having all accessed files in memory and the
page cache can significantly reduce the influence of the I/O layer on
the build system.

**We recommend building with no less than 8 GB of system memory.** As
always, the more memory you have, the better. For a bare bones machine
doing nothing more than building the source tree, anything more than 16
GB is likely entering the point of diminishing returns.

This cause impacts both clobber and incremental builds.

You are building on Windows
===========================

New processes on Windows are about a magnitude slower to spawn than on
UNIX-y systems such as Linux. This is because Windows has optimized new
threads while the \*NIX platforms typically optimize new processes.
Anyway, the build system spawns thousands of new processes during a
build. Parts of the build that rely on rapid spawning of new processes
are slow on Windows as a result. This is most pronounced when running
*configure*. The configure file is a giant shell script and shell
scripts rely heavily on new processes. This is why configure
can run over a minute slower on Windows.

Another reason Windows builds are slower is because Windows lacks proper
symlink support. On systems that support symlinks, we can generate a
file into a staging area then symlink it into the final directory very
quickly. On Windows, we have to perform a full file copy. This incurs
much more I/O. And if done poorly, can muck with file modification
times, messing up build dependencies.

These issues impact both clobber and incremental builds.

make is inefficient
===================

Compared to modern build backends like Tup or Ninja, `make` is slow and
inefficient. We can only make `make` so fast. At some point, we'll hit a
performance plateau and will need to use a different tool to make builds
faster.

Please note that clobber and incremental builds are different. A clobber build
with `make` will likely be as fast as a clobber build with a modern build
system.

C++ header dependency hell
==========================

Modifying a *.h* file can have significant impact on the build system.
If you modify a *.h* that is used by 1000 C++ files, all of those 1000
C++ files will be recompiled.

Our code base has traditionally been sloppy managing the impact of
changed headers on build performance. Bug 785103 tracks improving the
situation.

This issue mostly impacts the times of an :term:`incremental build`.

A search/indexing service on your machine is running
====================================================

Many operating systems have a background service that automatically
indexes filesystem content to make searching faster. On Windows, you
have the Windows Search Service. On OS X, you have Finder.

These background services sometimes take a keen interest in the files
being produced as part of the build. Since the build system produces
hundreds of megabytes or even a few gigabytes of file data, you can
imagine how much work this is to index! If this work is being performed
while the build is running, your build will be slower.

OS X's Finder is notorious for indexing when the build is running. And,
it has a tendency to suck up a whole CPU core. This can make builds
several minutes slower. If you build with ``mach`` and have the optional
``psutil`` package built (it requires Python development headers - see
:ref:`python` for more) and Finder is running during a build, mach will
print a warning at the end of the build, complete with instructions on
how to fix it.

---

### Build Docs Snap (`build/docs/snap.rst`)

.. _snap:

======================
Firefox Snap Packaging
======================

This page explains interactions between Firefox and Snap packaging format.

Where is the upstream
=====================

The code reference itself is mozilla-central, but the packaging is being worked
within the `Canonical's firefox-snap repository <https://github.com/canonical/firefox-snap/>`_.

This packaging includes a few more bits and dependencies, including compiler.
It will also re-download the mercurial repository: this is on purpose.

Where to report bugs
====================

All bugs should be reported to Bugzilla's ``Third Party Packaging`` component,
and marked as blocking ``snap`` meta-bug.

Full build process
==================

There may be a few differences between a simple repack and a real full build of
the Snap, you can find mention of the repackage usage below.

The following steps should be enough, assuming you have properly setup:

 - ``snapcraft`` (see `quickstart doc <https://snapcraft.io/docs/snapcraft-quickstart>`_)
 - ``LXD`` (see `providers doc <https://snapcraft.io/docs/build-providers>`_)

While the documentation still refers to `Multipass`, the Firefox Snap and its
dependency had some requirements that made it better suited to use `LXD`.

When performing the checkout, please keep in mind the branch mapping:

 - `edge` is our `nightly`
 - `beta` is our `beta`
 - `stable` is our `release`
 - `esr` is our `esr`

.. code-block:: shell

    $ git clone https://github.com/canonical/firefox-snap --branch BRANCH
    $ snap run snapcraft

You should end up after some time with two files: ``firefox-XXX.snap`` and
``firefox-XXX.debug``. The first one is the package you will want to ``snap
install`` while the second one holds your debugging symbols.

You can then install the package:

.. code-block:: shell

    $ sudo snap install --name firefox --dangerous ./path/to/firefox-XXX.snap

If you want to have parallel installs, then you can change the `--name firefox`
to something else. This will be the name you use for ``snap run
installed-name``, e.g., ``--name firefox_nightly`` will require you to run
``snap run firefox_nightly``.

`Snap` has a notion of plugs and slots, and some gets automatically connected
in various ways, including depending on the ``Snap Sore`` itself, and if you
manually install as ``firefox`` it should reuse them (but you might do bad
things with your profile). If you install using another name, then the ``Snap
Store`` automatic connection will not happen and this can result in a broken
state. Inspecting ``snap connections firefox`` using a store-installed snap
should get your an accurate list that you can replicate.

Cross-compilation
=================

There is now support for cross-compilation for ``arm64``.
To produce cross-compiled version locally:

 - follow the steps above for building, except you need to pass
   ``--build-for=ARCH`` to ``snapcraft``
 - this needs ``snapcraft`` of at least v8.x
 - make sure you uncomment the ``##CROSS-COMPILATION##`` lines due to Launchpad
   limitations

Builds on Treeherder as well as Try pushes are also available using
cross-compilation. Tests on Treeherder will also be supported when ARM-based
workers will be available, confere `Bug 1855463
<https://bugzilla.mozilla.org/show_bug.cgi?id=1855463>`_.

What CI coverage
================

Currently, there are upstream-like builds on treeherder. They are scheduled as
a cron task daily and includes:

 - building opt/debug versions of the snap
 - building them on all branches
 - running a few selenium-based tests

The build definitions :searchfox:`are based on docker <mozilla-central/rev/3c72de9280ec57dc55c24886c6334d9e340500e8:taskcluster/docker/snap-coreXX-build/Dockerfile>`.

It should be noted that for the moment, all tasks needs to run under docker.
However, this setup is not working for `Snap` since it interacts with `SystemD`
which does not work under `Docker`. This is why the installation is handled by
:searchfox:`the install-snap script <mozilla-central/rev/3c72de9280ec57dc55c24886c6334d9e340500e8:taskcluster/docker/snap-coreXX-build/install-snap.sh>`
rather than plain `sudo snap install`, and also why we need to run `snap` in
`destructive mode` (which is fine since we are within a docker container). This
does not apply to the tests case which relies on newly-available wayland
virtual machines.

Outside the build oddities because of the setup, it should be noted that those
builds are as close as possible to upstream. This means:

 - the mozilla-central hash they run against is not matching the source code it
   builds from, and one should inspect the build log to see the mercurial clone
   step
 - it builds using the clang build within the snap definition

The tests are defined :searchfox:`within the docker subdirectory <mozilla-central/rev/3c72de9280ec57dc55c24886c6334d9e340500e8:taskcluster/docker/snap-coreXX-build/snap-tests/tests.sh>`.
They are using Selenium because this is what was used by pre-existing tests ran
on GitHub Actions from upstream.

Their coverage is ensuring that we get a basic working browser out of builds.
It includes some tests that previously were manually ran by QA.

How to hack on try
==================

Build and test tasks can be explored via ``mach try fuzzy --full`` by searching
for ``'snap 'upstream``. There is a bit of hacking for try to make sure we
actually don't re-download the mercurial repo and directly reuse the clone
generated by `run-task`, handled in the :searchfox:`run.sh script <mozilla-central/rev/3c72de9280ec57dc55c24886c6334d9e340500e8:taskcluster/docker/snap-coreXX-build/run.sh#61-72>`.

So pushing to try is basically just:

.. code-block:: shell

    $ mach try fuzzy --full -q "'snap 'upstream 'local"

Because of the build process, a full opt build will take around 1h45-2h while a
debug build will be around 60 minutes, the difference coming from the use of
PGO on opt builds.

If you need to reuse a package from the Snap Store or from the latest
mozilla-central or a specific successful build, you can use ``USE_SNAP_FROM_STORE_OR_MC`` en
variable ; setting it to ``store`` will download from the Snap Store (warning:
no debug builds on the Snap Store, so whatever ``debug`` variants we have will
be an ``opt`` build in fact), and setting to a TaskCluster index value will
download from the index. Set it to ``latest`` if you want latest, or explore
the TaskCluster index for others. Any ``try`` will be pulled from latest
``nightly`` while others will be fetched from their respective branches.

How to hack locally
===================

After a successful build, you can also build a Snap by performing a repackaging
using the ``mach repackage snap`` tool. This requires a ``snapcraft`` working
installation relying on ``LXD``, which installation steps are
`documented upstream <https://snapcraft.io/docs/build-providers>`_.

---

### Build Docs Sparse (`build/docs/sparse.rst`)

.. _build_sparse:

================
Sparse Checkouts
================

The Firefox repository is large: over 230,000 files. That many files
can put a lot of strain on machines, tools, and processes.

Some version control tools have the ability to only populate a
working directory / checkout with a subset of files in the repository.
This is called *sparse checkout*.

Various tools in the Firefox repository are configured to work
when a sparse checkout is being used.

Sparse Checkouts in Mercurial
=============================

Mercurial 4.3 introduced **experimental** support for sparse checkouts
in the official distribution (a Facebook-authored extension has
implemented the feature as a 3rd party extension for years).

To enable sparse checkout support in Mercurial, enable the ``sparse``
extension::

   [extensions]
   sparse =

The *sparseness* of the working directory is managed using
``hg debugsparse``. Run ``hg help debugsparse`` and ``hg help -e sparse``
for more info on the feature.

When a *sparse config* is enabled, the working directory only contains
files matching that config. You cannot ``hg add`` or ``hg remove`` files
outside the *sparse config*.

.. warning::

   Sparse support in Mercurial 4.3 does not have any backwards
   compatibility guarantees. Expect things to change. Scripting against
   commands or relying on behavior is strongly discouraged.

In-Tree Sparse Profiles
=======================

Mercurial supports defining the sparse config using files under version
control. These are called *sparse profiles*.

Essentially, the sparse profiles are managed just like any other file in
the repository. When you ``hg update``, the sparse configuration is
evaluated against the sparse profile at the revision being updated to.
From an end-user perspective, you just need to *activate* a profile once
and files will be added or removed as appropriate whenever the versioned
profile file updates.

In the Firefox repository, the ``build/sparse-profiles`` directory
contains Mercurial *sparse profiles* files.

Each *sparse profile* essentially defines a list of file patterns
(see ``hg help patterns``) to include or exclude. See
``hg help -e sparse`` for more.

Mach Support for Sparse Checkouts
=================================

``mach`` detects when a sparse checkout is being used and its
behavior may vary to accommodate this.

By default it is a fatal error if ``mach`` can't load one of the
``mach_commands.py`` files it was told to. But if a sparse checkout
is being used, ``mach`` assumes that file isn't part of the sparse
checkout and to ignore missing file errors. This means that
running ``mach`` inside a sparse checkout will only have access
to the commands defined in files in the sparse checkout.

Sparse Checkouts in Automation
==============================

``hg robustcheckout`` (the extension/command used to perform clones
and working directory operations in automation) supports sparse checkout.
However, it has a number of limitations over Mercurial's default sparse
checkout implementation:

* Only supports 1 profile at a time
* Does not support non-profile sparse configs
* Does not allow transitioning from a non-sparse to sparse checkout or
  vice-versa

These restrictions ensure that any sparse working directory populated by
``hg robustcheckout`` is as consistent and robust as possible.

``run-task`` (the low-level script for *bootstrapping* tasks in
automation) has support for sparse checkouts.

TaskGraph tasks using ``run-task`` can specify a ``sparse-profile``
attribute in YAML (or in code) to denote the sparse profile file to
use. e.g.::

   run:
       using: run-command
       command: <command>
       sparse-profile: taskgraph

This automagically results in ``run-task`` and ``hg robustcheckout``
using the sparse profile defined in ``build/sparse-profiles/<value>``.

Pros and Cons of Sparse Checkouts
=================================

The benefits of sparse checkout are that it makes the repository appear
to be smaller. This means:

* Less time performing working directory operations -> faster version
  control operations
* Fewer files to consult -> faster operations
* Working directories only contain what is needed -> easier to understand
  what everything does

Fewer files in the working directory also contributes to disadvantages:

* Searching may not yield hits because a file isn't in the sparse
  checkout. e.g. a *global* search and replace may not actually be
  *global* after all.
* Tools performing filesystem walking or path globbing (e.g.
  ``**/*.js``) may fail to find files because they don't exist.
* Various tools and processes make assumptions that all files in the
  repository are always available.

There can also be problems caused by mixing sparse and non-sparse
checkouts. For example, if a process in automation is using sparse
and a local developer is not using sparse, things may work for the
local developer but fail in automation (because a file isn't included
in the sparse configuration and not available to automation.
Furthermore, if environments aren't using exactly the same sparse
configuration, differences can contribute to varying behavior.

When Should Sparse Checkouts Be Used?
=====================================

Developers are discouraged from using sparse checkouts for local work
until tools for handling sparse checkouts have improved. In particular,
Mercurial's support for sparse is still experimental and various Firefox
tools make assumptions that all files are available. Developers should
use sparse checkout at their own risk.

The use of sparse checkouts in automation is a performance versus
robustness trade-off. Use of sparse checkouts will make automation
faster because machines will only have to manage a few thousand files
in a checkout instead of a few hundred thousand. This can potentially
translate to minutes saved per machine day. At the scale of thousands
of machines, the savings can be significant. But adopting sparse
checkouts will open up new avenues for failures. (See section above.)
If a process is isolated (in terms of file access) and well-understood,
sparse checkout can likely be leveraged with little risk. But if a
process is doing things like walking the filesystem and performing
lots of wildcard matching, the dangers are higher.

---

### Build Docs Supported Configurations (`build/docs/supported-configurations.rst`)

Supported Build Hosts and Targets
=================================

 ..  role:: strikethrough

There are three tiers of supported Firefox build hosts and targets.
These tiers represent the shared engineering priorities of the Mozilla project.

The "build host" is the machine that is performing the build of Firefox, and
the "build target" is the machine that will run the built Firefox application.
For example, if you were building Firefox for Android on your Linux computer, then the
Linux computer would be the "build host".

.. note::

   Sheriffs are in charge of monitoring the tree. Their definition for tiers
   is for automation jobs, which tells a developer what is expected of them when
   they land code. This document is about the tiers of supported build hosts and targets,
   which tells a person compiling/using Firefox what they can expect from Mozilla.
   See the `job tier definition <https://wiki.mozilla.org/Sheriffing/Job_Visibility_Policy#Overview_of_the_Job_Visibility_Tiers>`__ for more information.


.. _build_hosts:

Supported Build Hosts
---------------------

While we want to help users resolve build-related issues on their systems, we
are unable to help resolve build system issues on all possible operating
systems and versions.

.. _tier_1_hosts:

Tier-1 Hosts and Toolchains
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Support is available for the following **host operating systems** and versions
when building for a :ref:`Tier-1 Firefox build target<tier_1_targets>`, including
cross-compilation where available:

* Ubuntu Linux x86_64
    * Current stable release
    * Previous stable release
    * Current LTS release
* Debian Linux x86_64
    * Current stable release
    * Current testing release
* Fedora Linux x86_64
    * Current stable release
    * Previous stable release
* macOS Intel and M1
    * Current major macOS release
    * Previous major macOS release
* Windows x86_64
    * Windows 10 with MozillaBuild Environment
    * Windows 11 with MozillaBuild Environment

Tier-2 Hosts and Toolchains
^^^^^^^^^^^^^^^^^^^^^^^^^^^

In addition to the limitations outlined above in the Tier-1 list, our ability
to provide assistance with build issues using/targeting Tier-2
hosts/targets/compilers is not unbounded.

While we will endeavour to make a best effort to help resolve issues, you may
be referred to the relevant community maintainers for further support.

The Tier-2 hosts are:

* Other Linux x86_64 distributions and/or versions
* Older macOS versions
* Older Windows x86_64 versions

Tier-3 Hosts and Toolchains
^^^^^^^^^^^^^^^^^^^^^^^^^^^

We cannot provide any guarantees of assistance in resolving build issues using
or targeting Tier-3 platforms.


Supported Build Targets
-----------------------

.. _tier_1_targets:

Tier-1 Targets
^^^^^^^^^^^^^^

The term **"Tier-1 platform"** refers to those platforms - CPU
architectures and operating systems - that are the primary focus of
Firefox development efforts. Tier-1 platforms are fully supported by
Mozilla's `continuous integration processes <https://treeherder.mozilla.org/>`__ and the
:ref:`Pushing to Try`. Any proposed change to Firefox on these
platforms that results in build failures, test failures, performance
regressions or other major problems **will be reverted immediately**.


The **Tier-1 Firefox platforms** and their supported compilers are:

-  Android on Linux x86-64, ARMv7 and ARMv8-A (clang)
-  Linux x86-64 (gcc and clang), Linux/AArch64 (clang)
-  macOS 10.15 and later on x86-64 and AArch64 (clang)
-  Windows/x86, x86-64 and AArch64 (clang-cl)

Prior to Firefox 63, Windows/x86 and Windows/x86-64 relied on the MSVC
compiler; from **Firefox 63 onward MSVC is not supported**. Older 32-bit
x86 CPUs without SSE2 instructions such as the Pentium III and Athlon XP
are also **not considered Tier-1 platforms, and are not supported**.
Note also that while Windows/x86 and ARM/AArch64 are supported *as build
targets*, it is not possible to build Firefox *on* Windows/x86 or
Windows/AArch64 systems.

Tier-2 Targets
^^^^^^^^^^^^^^

**Tier-2 platforms** are actively maintained by the Mozilla community,
though with less rigorous requirements. Proposed changes resulting in
breakage or regressions limited to these platforms **may not immediately
result in reversion**. However, developers who break these platforms are
expected to work with platform maintainers to fix problems, and **may be
required to revert their changes** if a fix cannot be found.

The **Tier-2 Firefox platforms** and their supported compilers are:

-  Windows/x86 (mingw-clang) - maintained by Tom Ritter and Jacek Caban
   -

   -  *Note that some features of this platform are disabled, as they
      require MS COM or the w32api project doesn't expose the necessary
      Windows APIs.*

Tier-3 Targets
^^^^^^^^^^^^^^

**Tier-3 platforms** have a maintainer or community which attempt to
keep the platform working. These platforms are **not supported by our
continuous integration processes**, and **Mozilla does not routinely
test on these platforms**, nor do we block further development on the
outcomes of those tests.

At any given time a Firefox built from mozilla-central for these
platforms may or may not work correctly or build at all.

**Tier-3 Firefox platforms** include:

-  Linux on various CPU architectures including ARM variants not listed
   above, PowerPC, and x86 CPUs - maintained by various Linux distributions
-  FreeBSD/x86, x86-64, Aarch64 (clang) - `maintained by gecko@FreeBSD.org <https://www.freshports.org/www/firefox/>`__
-  OpenBSD/x86, x86-64 (clang) - maintained by Landry Breuil
-  NetBSD/x86-64 (gcc) - maintained by David Laight
-  Solaris/x86-64, sparc64 (gcc) - maintained by Petr Sumbera
-  :strikethrough:`Windows/x86-64 (mingw-gcc)` - Unsupported due to
   requirements for clang-bindgen

If you're filing a bug against Firefox on a Tier-3 platform (or any
combination of OS, CPU and compiler not listed above) please bear in
mind that Mozilla developers do not reliably have access to non-Tier-1
platforms or build environments. To be actionable bug reports against
non-Tier-1 platforms should include as much information as possible to
help the owner of the bug determine the cause of the problem and the
proper solution. If you can provide a patch, a regression range or
assist in verifying that the developer's patches work for your platform,
that would help a lot towards getting your bugs fixed and checked into
the tree.

---

### Build Docs Telemetry (`build/docs/telemetry.rst`)

.. _buildtelemetry:

===============
Build Telemetry
===============

The build system (specifically, all the build tooling hooked
up to ``./mach``) has been configured to collect metrics data
points and errors for various build system actions. This data
helps drive team planning for the build team and ensure that
resources are applied to build processes that need them most.
You can adjust your telemetry settings by editing your
``~/.mozbuild/machrc`` file.

Glean Telemetry
===============

Mozbuild reports data using `Glean <https://mozilla.github.io/glean/>`_ via
:ref:`mach_telemetry`.  The metrics collected are documented :ref:`here<metrics>`.

Error Reporting
===============

``./mach`` uses `Sentry <https://sentry.io/welcome/>`_
to automatically report errors to `our issue-tracking dashboard
<https://sentry.prod.mozaws.net/operations/mach/>`_.

Information captured
++++++++++++++++++++

Sentry automatically collects useful information surrounding
the error to help the build team discover what caused the
issue and how to reproduce it. This information includes:

* Environmental information, such as the computer name, timestamp, Python runtime and Python module versions
* Process arguments
* The stack trace of the error, including contextual information:

    * The data contained in the exception
    * Functions and their respective source file names, line numbers
    * Variables in each frame
* `Sentry "Breadcrumbs" <https://docs.sentry.io/platforms/python/default-integrations/>`_,
  which are important events that have happened which help contextualize the error, such as:

    * An HTTP request has occurred
    * A subprocess has been spawned
    * Logging has occurred

Note that file paths may be captured, which include absolute paths (potentially including usernames).

---

### Build Docs Test Certificates (`build/docs/test_certificates.rst`)

.. _test_certificates:

===============================
Adding Certificates for Testing
===============================

Sometimes we need to write tests for scenarios that require custom client, server or certificate authority (CA) certificates. For that purpose, you can generate such certificates using ``build/pgo/genpgocert.py``.

The certificate specifications (and key specifications) are located in ``build/pgo/certs/``.

To add a new **server certificate**, add a ``${cert_name}.certspec`` file to that folder.
If it needs a non-default private key, add a corresponding ``${cert_name}.server.keyspec``.

For a new **client certificate**, add a ``${cert_name}.client.keyspec`` and corresponding ``${cert_name}.certspec``.

To add a new **CA**, add a ``${cert_name}.ca.keyspec`` as well as a corresponding ``${cert_name}.certspec`` to that folder.

.. hint::

   * The full syntax for .certspec files is documented at :searchfox:`security/manager/tools/pycert.py`

   * The full syntax for .keyspec files is documented at :searchfox:`security/manager/tools/pykey.py`

Then regenerate the certificates by running:::

   ./mach python build/pgo/genpgocert.py

These commands will modify cert9.db and key4.db, and if you have added a .keyspec file will generate a ``{$cert_name}.client`` or ``{$cert_name}.ca`` file.

**These files need to be committed.**

If you've created a new server certificate, you probably want to modify ``build/pgo/server-locations.txt`` to add a location with your specified certificate:::

   https://my-test.example.com:443           cert=${cert_name}

You will need to run ``./mach build`` again afterwards.

.. important::

   Make sure to exactly follow the naming conventions and use the same ``cert_name`` in all places

---

### Build Docs Test Manifests (`build/docs/test_manifests.rst`)

.. _test_manifests:

==============
Test Manifests
==============

Many test suites have their test metadata defined in files called
**test manifests**.

Test manifests are divided into two flavors: :ref:`manifestparser_manifests`
and :ref:`reftest_manifests`.

Naming Convention
=================

The build system does not enforce file naming for test manifest files.
However, the following convention is used.

mochitest.toml
   For the *plain* flavor of mochitests.

chrome.toml
   For the *chrome* flavor of mochitests.

browser.toml
   For the *browser chrome* flavor of mochitests.

a11y.toml
   For the *a11y* flavor of mochitests.

xpcshell.toml
   For *xpcshell* tests.

.. _manifestparser_manifests:

ManifestParser Manifests
==========================

ManifestParser manifests are essentially toml files that conform to a basic
set of assumptions.

The :doc:`reference documentation </mozbase/manifestparser>`
for manifestparser manifests describes the basic format of test manifests.

In summary, manifests are toml files with section names describing test files::

    ["test_foo.js"]
    ["test_bar.js"]

Keys under sections can hold metadata about each test::

    ["test_foo.js"]
    skip-if = ["os == 'win'"]
    ["test_foo.js"]
    skip-if = ["os == 'linux' && debug"]
    ["test_baz.js"]
    fail-if = [
      "os == 'mac'",
      "os == 'android'",
    ]

There is a special **DEFAULT** section whose keys/metadata apply to all
sections/tests::

    [DEFAULT]
    property = value

    ["test_foo.js"]

In the above example, **test_foo.js** inherits the metadata **property = value**
from the **DEFAULT** section.

Recognized Metadata
-------------------

Test manifests can define some common keys/metadata to influence behavior.
Those keys are as follows:

head
   List of files that will be executed before the test file. (Used in
   xpcshell tests.)

tail
   List of files that will be executed after the test file. (Used in
   xpcshell tests.)

support-files
   List of additional files required to run tests. This is typically
   defined in the **DEFAULT** section.

   Unlike other file lists, *support-files* supports a globbing mechanism
   to facilitate pulling in many files with minimal typing. This globbing
   mechanism is activated if an entry in this value contains a ``*``
   character. A single ``*`` will wildcard match all files in a directory.
   A double ``**`` will descend into child directories. For example,
   ``data/*`` will match ``data/foo`` but not ``data/subdir/bar`` where
   ``data/**`` will match ``data/foo`` and ``data/subdir/bar``.

   Support files starting with ``/`` are placed in a root directory, rather
   than a location determined by the manifest location. For mochitests,
   this allows for the placement of files at the server root. The source
   file is selected from the base name (e.g., ``foo`` for ``/path/foo``).
   Files starting with ``/`` cannot be selected using globbing.

   Some support files are used by tests across multiple directories. In
   this case, a test depending on a support file from another directory
   must note that dependency with the path to the required support file
   in its own **support-files** entry. These use a syntax where paths
   starting with ``!/`` will indicate the beginning of the path to a
   shared support file starting from the root of the srcdir. For example,
   if a manifest at ``dom/base/test/mochitest.toml`` has a support file,
   ``dom/base/test/server-script.sjs``, and a mochitest in
   ``dom/workers/test`` depends on that support file, the test manifest
   at ``dom/workers/test/mochitest.toml`` must include
   ``!/dom/base/test/server-script.sjs`` in its **support-files** entry.

generated-files
   List of files that are generated as part of the build and don't exist in
   the source tree.

   The build system assumes that each manifest file, test file, and file
   listed in **head**, **tail**, and **support-files** is static and
   provided by the source tree (and not automatically generated as part
   of the build). This variable tells the build system not to make this
   assumption.

   This variable will likely go away sometime once all generated files are
   accounted for in the build config.

   If a generated file is not listed in this key, a clobber build will
   likely fail.

dupe-manifest
   Record that this manifest duplicates another manifest.

   The common scenario is two manifest files will include a shared
   manifest file via the ``["include:file"]`` special section. The build
   system enforces that each test file is only provided by a single
   manifest. Having this key present bypasses that check.

   The value of this key is ignored.

skip-if
   Skip this test if the specified condition is true.
   See :ref:`manifest_filter_language`.

   Conditions can be specified on multiple lines, where each line is implicitly
   joined by a logical OR (``||``). This makes it easier to add comments to
   distinct failures. For example:

   .. parsed-literal::

      ["test_foo.js"]
      skip-if = [
          "os == 'mac' && fission",  # bug 123 - fails on fission
          "os == 'windows' && debug",  # bug 456 - hits an assertion
      ]

fail-if
   Expect test failure if the specified condition is true.
   See :ref:`manifest_filter_language`.

   Conditions can be specified on multiple lines (see ``skip-if``).

run-sequentially
   Run test sequentially if the specified condition is true.
   See :ref:`manifest_filter_language`.

   To always run a test sequentially, use ``run-sequentially = ["true"]``.

scheme
   Changes the scheme and domain from which the test runs. (Only used in mochitest suites)

   There are two possible values:
      - ``http`` (default): The test will run from http://mochi.test:8888
      - ``https``: The test will run from https://example.com:443

.. _manifest_filter_language:

Manifest Filter Language
------------------------

Some manifest keys accept a special filter syntax as their values. These
values are essentially boolean expressions that are evaluated at test
execution time.

The expressions can reference a well-defined set of variables, such as
``os`` and ``debug``. These variables are populated from the
``mozinfo.json`` file. For the full list of available variables, see
the :ref:`mozinfo documentation <mozinfo_attributes>`.

See
`the source <https://hg.mozilla.org/mozilla-central/file/default/testing/mozbase/manifestparser/manifestparser/manifestparser.py>`_ for the full documentation of the
expression syntax until it is documented here.

.. rstcheck: ignore-directives=todo
.. todo::

   Document manifest filter language.

.. _manifest_file_installation:

File Installation
-----------------

Files referenced by manifests are automatically installed into the object
directory into paths defined in
:py:func:`mozbuild.frontend.emitter.TreeMetadataEmitter._process_test_manifest`.

Relative paths resolving to parent directory (e.g.
``support-files = ../foo.txt`` have special behavior.

For ``support-files``, the file will be installed to the default destination
for that manifest. Only the file's base name is used to construct the final
path: directories are irrelevant.  Files starting with ``/`` are an exception,
these are installed relative to the root of the destination; the base name is
instead used to select the file..

For all other entry types, the file installation is skipped.

.. _reftest_manifests:

Reftest Manifests
=================

See `MDN <https://developer.mozilla.org/en-US/docs/Creating_reftest-based_unit_tests>`_.

---

### Build Docs Toolchains Update Policy (`build/docs/toolchains-update-policy.rst`)

.. _build_toolchains-update-policy:

========================
Toolchains update policy
========================

We document here the decision making and planning around when we update the
various toolchains used and required to build Firefox.

Rust
====

The Rust update policy is documented in a
:ref:`separate document<Rust Update Policy>`.

Clang
=====

*We ship official stable Firefox with a released Clang.*

As a general rule, we update the Clang compiler version used to build Firefox
Nightly as soon as possible, considering the constraint that the Clang compiler
and the Rust compiler need to use the same version of LLVM.

We don't upgrade the Clang version in the beta or release branches of Firefox.

The following exception applies:

- We may skip the update (or backout the update) if major problems are
  encountered (typically, we’ve had to do so because of build problems, crash
  reporting bustage, or performance issues).

*Local developer builds use the same version as used for the official builds.*

Minimum Supported Clang Version
-------------------------------

*We will update the Minimum Supported Clang Version to match the smallest LLVM
version supported by the Minimum Supported Rust Version.*

That smallest LLVM version can be found in the `check_llvm_version` function in
the `src/bootstrap/src/core/build_steps/llvm.rs` source file in the Rust
compiler source code for the Minimum Supported Rust Version.

Rationale
^^^^^^^^^

Downstreams that need to procure a Rust compiler will also need an LLVM
toolchain, which in practice includes a Clang with the same version. Since Rust
enforces a minimum supported LLVM version, setting our Minimum Supported Clang
Version to match that same baseline makes the requirements straightforward: a
single minimum LLVM version covers both Rust and C/C++ compilation.

This approach strikes a balance between the constraints faced by downstreams in
acquiring and maintaining toolchains, and our own need to use reasonably modern
compilers for C and C++ code.

libstdc++
=========

*We build stable Firefox with a libstdc++ that allows to provide the necessary
binary compatibility*

The binary compatibility is defined by the Firefox system requirements on Linux.
Those can be adjusted but a balance must be made between the breadth of systems
supported by Firefox builds, and the desired C++ features on the development
side. As of writing there isn't a policy describing exactly how the system
requirements are updated, yet.

Tricks may be put in place to guarantee the required binary compatibility with
older versions of libstdc++ than the one used to build.
(see `build/unix/stdc++compat`)

GCC
===

*The Minimum Supported GCC Version matches the version of libstdc++ above*

GCC and libstdc++ are, generally speaking, coupled, and it can be difficult to
use a version of GCC that doesn't match the version of libstdc++. As such, we
don't support building with a version of GCC older than the version of
libstdc++ Firefox is built against by default (from the development sysroot).

---

### Build Docs Toolchains (`build/docs/toolchains.rst`)

.. _build_toolchains:

===========================
Creating Toolchain Archives
===========================

There are various scripts in the repository for producing archives
of the build tools (e.g. compilers and linkers) required to build.

Clang and Rust
==============

To modify the toolchains used for a particular task, you may need several
things:

1. A :searchfox:`build task <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:taskcluster/ci/build/linux.yml#5-45>`

2. Which uses a toolchain task

    - :searchfox:`clang toolchain <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:taskcluster/ci/toolchain/clang.yml#51-72>`
    - :searchfox:`rust toolchain <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:taskcluster/ci/toolchain/rust.yml#57-74>`

3. Which uses a git fetch

    - :searchfox:`clang fetch <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:taskcluster/ci/fetch/toolchains.yml#413-418>`
    - (from-source ``dev`` builds only) :searchfox:`rust fetch <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:taskcluster/ci/fetch/toolchains.yml#434-439>`

4. (clang only) Which uses a :searchfox:`config json <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:build/build-clang/clang-linux64.json>`

5. Which takes :searchfox:`patches <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:build/build-clang/static-llvm-symbolizer.patch>` you may want to apply.

For the most part, you should be able to accomplish what you want by
copying/editing the existing examples in those files.

Clang
-----

Building clang is handled by :searchfox:`build-clang.py <build/build-clang/build-clang.py>`, which uses several resources
in the :searchfox:`build-clang <build/build-clang/>` directory. Read the :searchfox:`build-clang README <build/build-clang/README>` for more
details.

Note for local builds: build-clang.py can be run on developer machines but its
lengthy multi-stage build process is unnecessary for most local development. The
upstream `LLVM Getting Started Guide`_ has instructions on how to build
clang more directly.

.. _LLVM Getting Started Guide: https://llvm.org/docs/GettingStarted.html

Rust
----

Rust builds are handled by :searchfox:`repack_rust.py <taskcluster/scripts/misc/repack_rust.py>`. The primary purpose of
that script is to download prebuilt tarballs from the Rust project.

It uses the same basic format as `rustup` for specifying the toolchain
(via ``--channel``):

- request a stable build with ``1.xx.y`` (e.g. ``1.47.0``)
- request a beta build with ``beta-yyyy-mm-dd`` (e.g. ``beta-2020-08-26``)
- request a nightly build with ``nightly-yyyy-mm-dd`` (e.g. ``nightly-2020-08-26``)
- request a build from `Rust's ci`_ with ``bors-$sha`` (e.g. ``bors-796a2a9bbe7614610bd67d4cd0cf0dfff0468778``)
- request a from-source build with ``dev``

Rust From Source
----------------

As of this writing, from-source builds for Rust are a new feature, and not
used anywhere by default. The feature was added so that we can test patches
to rustc against the tree. Expect things to be a bit hacky and limited.

Most importantly, building from source requires your toolchain to have a
:searchfox:`fetch of the rust tree <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:taskcluster/ci/toolchain/rust.yml#69-71>` as well as :searchfox:`clang and binutils toolchains <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:taskcluster/ci/toolchain/rust.yml#72-74>`. It is also
recommended to upgrade the worker-type to e.g. ``b-linux-large``.

Rust's build dependencies are fairly minimal, and it has a sanity check
that should catch any missing or too-old dependencies. See the `Rust README`_
for more details.

Patches are set via :searchfox:`the --patch flag <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:taskcluster/scripts/misc/repack_rust.py#667-675>` (passed via ``toolchain/rust.yml``).
Patch paths are assumed to be relative to ``/build/build-rust/``, and may be
optionally prefixed with ``module-path:`` to specify they apply to that git
submodule in the Rust source. e.g. ``--patch src/llvm-project:mypatch.diff``
patches rust's llvm with ``/build/build-rust/mypatch.diff``. There are no
currently checked in rust patches to use as an example, but they should be
the same format as :searchfox:`the clang ones <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:build/build-clang/static-llvm-symbolizer.patch>`.

Rust builds are not currently configurable, and uses a :searchfox:`hardcoded config.toml <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:taskcluster/scripts/misc/repack_rust.py#384-421>`,
which you may need to edit for your purposes. See Rust's `example config`_ for
details/defaults. Note that these options do occasionally change, so be sure
you're using options for the version you're targeting. For instance, there was
a large change around Rust ~1.48, and the currently checked in config was for
1.47, so it may not work properly when building the latest version of Rust.

Rust builds are currently limited to targeting only the host platform.
Although the machinery is in place to request additional targets, the
cross-compilation fails for some unknown reason. We have not yet investigated
what needs to be done to get this working.

While Rust generally maintains a clean tree for building ``rustc`` and
``cargo``, other tools like ``rustfmt`` or ``miri`` are allowed to be
transiently broken. This means not every commit in the Rust tree will be
able to build the :searchfox:`tools we require <mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c:taskcluster/scripts/misc/repack_rust.py#398>`.

Although ``repack_rust`` considers ``rustfmt`` an optional package, Rust builds
do not currently implement this and will fail if ``rustfmt`` is busted. Some
attempt was made to work around it, but `more work is needed`_.

.. _Rust's ci: https://github.com/rust-lang/rust/pull/77875#issuecomment-736092083
.. _Rust README: https://github.com/rust-lang/rust/#building-on-a-unix-like-system
.. _example config: https://github.com/rust-lang/rust/blob/b7ebc6b0c1ba3c27ebb17c0b496ece778ef11e18/config.toml.example
.. _more work is needed: https://github.com/rust-lang/rust/issues/79249

Python
------

Python is built from source by ``taskcluster/scripts/misc/build-cpython.sh`` on
Linux and OSX. We use the upstream installer on Windows, through
``taskcluster/scripts/misc/pack-cpython.sh``. In order to ensure consistency, we
use the same version for both approaches. Note however that the Windows installer is
not packaged for all patch versions, so there might be a slight delta there.

Windows
=======

The ``build/vs/generate_yaml.py`` and ``taskcluster/scripts/misc/get_vs.py``
scripts are used to manage and get Windows toolchains containing Visual
Studio executables, SDKs, etc.

The ``build/vs/generate_yaml.py`` script is used to generate one of the
YAML files used in the relevant toolchain task. The exact command line
used to generate the file is stored in the header of the YAML file itself.
Each YAML file records the necessary downloads from Microsoft servers to
install the required Visual Studio components given on the command line.

The ``taskcluster/scripts/misc/get_vs.py`` script takes a YAML file as
input and fills a directory with the corresponding Visual Studio components.

Both scripts should be run via ``mach python --virtualenv build``. The
latter is automatically invoked by the bootstrapping mechanism.


MacOS
=====

The ``build/macosx/catalog.py`` and ``taskcluster/scripts/misc/unpack-sdk.py``
scripts are used to manage and get macOS SDKs.

The ``build/macosx/catalog.py`` script is used to explore the Apple
software update catalog. Running the script with no argument will show
a complete list of "products". You probably don't want that, but rather
start with a filter:

.. code-block:: shell

    $ ./mach python build/macosx/catalog.py --filter MOS_SDK
    071-29699 Command Line Tools for Xcode 12.5
    001-89745 Command Line Tools for Xcode 12.4
    071-54303 Command Line Tools for Xcode 12.5
    002-41708 Command Line Tools for Xcode 13.2
    002-83793 Command Line Tools for Xcode 13.4
    012-92431 Command Line Tools for Xcode 14.2
    032-64167 Command Line Tools for Xcode 14.3

From there, pick the id of the product you're interested in, and run the
script again with that id:

.. code-block:: shell

    $ ./mach python build/macosx/catalog.py 032-64167
    com.apple.pkg.CLTools_Executables https://swcdn.apple.com/content/downloads/38/61/032-64167-A_F8LL7XSTW6/k3kg0uip4kxd3qupgy6y8fzp27mnxdpt6y/CLTools_Executables.pkg
    com.apple.pkg.CLTools_SDK_macOS13 https://swcdn.apple.com/content/downloads/38/61/032-64167-A_F8LL7XSTW6/k3kg0uip4kxd3qupgy6y8fzp27mnxdpt6y/CLTools_macOSNMOS_SDK.pkg
    com.apple.pkg.CLTools_SDK_macOS12 https://swcdn.apple.com/content/downloads/38/61/032-64167-A_F8LL7XSTW6/k3kg0uip4kxd3qupgy6y8fzp27mnxdpt6y/CLTools_macOSLMOS_SDK.pkg
    com.apple.pkg.CLTools_macOS_SDK https://swcdn.apple.com/content/downloads/38/61/032-64167-A_F8LL7XSTW6/k3kg0uip4kxd3qupgy6y8fzp27mnxdpt6y/CLTools_macOS_SDK.pkg
    com.apple.pkg.CLTools_SwiftBackDeploy https://swcdn.apple.com/content/downloads/38/61/032-64167-A_F8LL7XSTW6/k3kg0uip4kxd3qupgy6y8fzp27mnxdpt6y/CLTools_SwiftBackDeploy.pkg

From there, pick the id of the package you're interested in, and run the
script again with a combination of both product and package ids to inspect
its content and ensure that's what you're looking for.

.. code-block:: shell

    $ ./mach python build/macosx/catalog.py 032-64167/com.apple.pkg.CLTools_SDK_macOS13
    Library
    Library/Developer
    Library/Developer/CommandLineTools
    Library/Developer/CommandLineTools/SDKs
    Library/Developer/CommandLineTools/SDKs/MacOSX13.sdk
    Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk
    Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr
    (...)

Once you have found the SDK you want, you can create or update toolchain tasks
in ``taskcluster/kinds/toolchain/macosx-sdk.yml``.

The ``taskcluster/scripts/misc/unpack-sdk.py`` script takes the url of a SDK
package, the sha512 hash for its content, the path to the SDK in the package,
and an output directory, and extracts the package in that directory.

Both scripts should be run via ``mach python``. The latter is automatically
invoked by the bootstrapping mechanism.

On automation, the script will download the file from tooltool instead of the
original url, so the file should also be uploaded to tooltool with `internal`
visibility.
See https://github.com/mozilla-releng/tooltool.

Firefox for Android with Gradle
===============================

To build Firefox for Android with Gradle in automation, archives
containing both the Gradle executable and a Maven repository
comprising the exact build dependencies are produced and uploaded to
an internal Mozilla server.  The build automation will download,
verify, and extract these archive before building.  These archives
provide a self-contained Gradle and Maven repository so that machines
don't need to fetch additional Maven dependencies at build time.
(Gradle and the downloaded Maven dependencies can be both
redistributed publicly.)

Archiving the Gradle executable is straight-forward, but archiving a
local Maven repository is not.  Therefore a toolchain job exists for
producing the required archives, `android-gradle-dependencies`.  The
job runs in a container based on a custom Docker image and spawns a
Sonatype Nexus proxying Maven repository process in the background.
The job builds Firefox for Android using Gradle and the in-tree Gradle
configuration rooted at ``build.gradle``.  The spawned proxying Maven
repository downloads external dependencies and collects them.  After
the Gradle build completes, the job archives the Gradle version used
to build, and the downloaded Maven repository, and exposes them as
Task Cluster artifacts.

To update the version of Gradle in the archive produced, update
``gradle/wrapper/gradle-wrapper.properties``.  Be sure to also update
the SHA256 checksum to prevent poisoning the build machines!

To update the versions of Gradle dependencies used, update
``dependencies`` sections in the in-tree Gradle configuration rooted
at ``build.gradle``.  Once you are confident your changes build
locally, push a fresh build to try.  The `android-gradle-dependencies`
toolchain should run automatically, fetching your new dependencies and
wiring them into the appropriate try build jobs.

To update the version of Sonatype Nexus, update the `sonatype-nexus`
`fetch` task definition.

To modify the Sonatype Nexus configuration, typically to proxy a new
remote Maven repository, modify
`taskcluster/scripts/misc/android-gradle-dependencies/nexus.xml`.

There is also a toolchain job that fetches the Android SDK and related
packages.  To update the versions of packaged fetched, modify
`python/mozboot/mozboot/android-packages.txt` and update the various
in-tree versions accordingly.

---

### Build Docs Unified Builds (`build/docs/unified-builds.rst`)

.. _unified-builds:

==============
Unified Builds
==============

The Firefox build system uses the technique of "unified builds" (or elsewhere
called "`unity builds <https://en.wikipedia.org/wiki/Unity_build>`_") to
improve compilation performance. Rather than compiling source files individually,
groups of files in the same directory are concatenated together, then compiled once
in a single batch.

Unified builds can be configured using the ``UNIFIED_SOURCES`` variable in ``moz.build`` files.

.. _unified_build_compilation_failures:

Why are there unrelated compilation failures when I change files?
=================================================================

Since multiple files are concatenated together in a unified build, it's possible for a change
in one file to cause the compilation of a seemingly unrelated file to fail.
This is usually because source files become implicitly dependent on each other for:

* ``#include`` statements
* ``using namespace ...;`` statements
* Other symbol imports or definitions

One of the more common cases of unexpected failures are when source code files are added or
removed, and the "chunking" is changed. There's a limit on the number of files that are combined
together for a single compilation, so sometimes the addition of a new file will cause another one
to be bumped into a different chunk. If that other chunk doesn't meet the implicit requirements
of the bumped file, there will be a tough-to-debug compilation failure.

Building outside of the unified environment
===========================================

As described above, unified builds can cause source files to implicitly depend on each other, which
not only causes unexpected build failures but also can cause issues when using source-analysis tools.
To combat this, we'll use a "non-unified" build that attempts to perform a build with as many files compiled
individually as possible.

To build in the non unified mode, set the following flag in your ``mozconfig``:

``ac_add_options --disable-unified-build``

Other notes:
============

* Some IDEs (such as VSCode with ``clangd``) build files in standalone mode, so they may show
  more failures than a ``mach build``.
* The amount of files per chunk can be adjusted in ``moz.build`` files with the
  ``FILES_PER_UNIFIED_FILE`` variable. Note that changing the chunk size can introduce
  compilation failures as described :ref:`above<unified_build_compilation_failures>`.
* We are happy to accept patches that fix problematic unified build chunks (such as by adding
  includes or namespace annotations).

---

### Build Docs Visualstudio (`build/docs/visualstudio.rst`)

.. _build_visualstudio:

======================
Visual Studio Projects
======================

The build system automatically generates Visual Studio project files to aid
with development, as part of a normal ``mach build`` from the command line.

You can find the solution file at ``$OBJDIR/msvc/mozilla.sln``.

If you want to generate the project files before/without doing a full build,
running ``./mach configure && ./mach build-backend -b VisualStudio`` will do
so.


Structure of Solution
=====================

The Visual Studio solution consists of hundreds of projects spanning thousands
of files. To help with organization, the solution is divided into the following
trees/folders:

Build Targets
   This folder contains common build targets. The *full* project is used to
   perform a full build. The *binaries* project is used to build just binaries.
   The *visual-studio* project can be built to regenerate the Visual Studio
   project files.

   Performing the *clean* action on any of these targets will clean the
   *entire* build output.

Binaries
   This folder contains common binaries that can be executed from within
   Visual Studio. If you are building the Firefox desktop application,
   the *firefox* project will launch firefox.exe. You probably want one of
   these set to your startup project.

Libraries
   This folder contains entries for each static library that is produced as
   part of the build. These roughly correspond to each directory in the tree
   containing C/C++. e.g. code from ``dom/base`` will be contained in the
   ``dom_base`` project.

   These projects don't do anything when built. If you build a project here,
   the *binaries* build target project is built.

Updating Project Files
======================

Either re-running ``./mach build`` or ``./mach build-backend -b VisualStudio``
will update the Visual Studio files after the tree changes.

Moving Project Files Around
===========================

The produced Visual Studio solution and project files should be portable.
If you want to move them to a non-default directory, they should continue
to work from wherever they are. If they don't, please file a bug.

Invoking mach through Visual Studio
===================================

It's possible to run mach commands via Visual Studio. There is some light magic
involved here.

Alongside the Visual Studio project files is a batch script named ``mach.bat``.
This batch script sets the environment variables present in your *MozillaBuild*
development environment at the time of Visual Studio project generation
and invokes *mach* inside an msys shell with the arguments specified to the
batch script. This script essentially allows you to invoke mach commands
inside the MozillaBuild environment without having to load MozillaBuild.

Projects currently utilize the ``mach build`` and ``mach clobber`` commands
for building and cleaning the tree respectively. Note that running ``clobber``
deletes the Visual Studio project files, and running ``build`` recreates them.
This might cause issues while Visual Studio is running. Thus a full rebuild is
currently neither recommended, nor supported, but incremental builds should work.

The batch script does not limit its use: any mach command can be invoked.
Developers may use this fact to add custom projects and commands that invoke
other mach commands.

---

### Ai Agent Tools Firefox Devtools Mcp (`docs/ai-agent-tools/firefox-devtools-mcp.rst`)

=========================================
Firefox DevTools MCP for AI Agent Testing
=========================================

Overview
========

The ``firefox-devtools-mcp`` is a Model Context Protocol (MCP) server that
enables AI assistants (such as Claude Code) to automate and interact with
Firefox through WebDriver protocols (BiDi and Classic). This tool is
particularly useful for:

- Automating browser interactions for testing and debugging
- Attempting to reproduce issues on live websites
- Capturing Firefox debug logs (MOZ_LOG) while controlling the browser
- Dynamically changing Firefox configuration without restarting

The MCP server provides programmatic access to a Firefox build, including
DevTools capabilities such as page navigation, DOM inspection, network
monitoring, console logs, user input simulation, and Firefox logging. It isn't
complete yet, but can already be useful.

This documentation refers to the official Mozilla MCP for
Firefox development: https://github.com/mozilla/firefox-devtools-mcp

Key Features
------------

- **WebDriver BiDi Protocol**: Uses the modern WebDriver BiDi protocol via
  Selenium WebDriver
- **WebDriver Classic Fallback**: Uses WebDriver Classic (Marionette) for
  features not yet ported to BiDi (notably Chrome context usage)
- **Local Firefox Support**: Can connect to custom Firefox builds (e.g., local
  development builds), or typical release/beta/nightly/esr builds, present on
  the machine
- **Real-time Interaction**: Provides live access to browser state and network
  activity
- **Firefox Output Capture**: stdout/stderr capturing, including setting and
  reading MOZ_LOG

Prerequisites
=============

Required Software
-----------------

- **Node.js**: Version 20.19.0 or higher
- **Firefox**: system installation (all channels supported) or local build
- **Claude Code** (or compatible MCP client): For AI-assisted automation

Installation and Configuration
===============================

The Firefox DevTools MCP server is **automatically configured** when using
Claude Code in the Firefox repository, via the ``.mcp.json`` file at the root
of the repository.

For installation in other projects or at user scope, Claude Code can configure
the MCP server with a single command:

.. code-block:: bash

   claude mcp add firefox-devtools npx @mozilla/firefox-devtools-mcp-moz

This command registers the MCP server with your Claude Code configuration for
the current project (typically ``project/.claude/``).

If a global installation is preferred (so that it works from multiple project
directories), it can be installed at the user scope:

.. code-block:: bash

   claude mcp add firefox-devtools npx @mozilla/firefox-devtools-mcp-moz --scope user

This changes ``~/.claude.json``, either in the project section, or in the global
section (if installed at the user scope).

After installation and/or configuration restart Claude Code to load the new MCP
server:

.. code-block:: bash

   # Exit Claude Code, then restart it, continuing the last session
   claude -c

The MCP server will automatically start when Claude Code initializes.

Configuration options
---------------------

The MCP server supports several command-line options. It's preferable to start
with no options, but they exist:

.. list-table::
   :widths: 25 75
   :header-rows: 1

   * - Option
     - Description
   * - ``--firefox-path <path>``
     - Path to Firefox executable (system Firefox used if not specified)
   * - ``--headless``
     - Run Firefox without UI (useful for automated testing)
   * - ``--viewport <size>``
     - Set initial viewport size (e.g., ``1280x720``)
   * - ``--profile-path <path>``
     - Use a specific Firefox profile directory
   * - ``--start-url <url>``
     - Initial URL to load (default: ``about:home``)
   * - ``--accept-insecure-certs``
     - Ignore TLS certificate errors (use with caution)
   * - ``--firefox-arg <arg>``
     - Additional arguments to pass to Firefox
   * - ``--env <KEY=VALUE>``
     - Set environment variables for Firefox (can be used multiple times)
   * - ``--output-file <path>``
     - Path where Firefox output (stdout/stderr) will be captured (optional)

Example with multiple options:

.. code-block:: json

   {
      "type": "stdio",
      "command": "@mozilla/firefox-devtools-mcp-moz",
      "args": [
       "--firefox-path",
       "/home/developer/firefox/obj-x86_64-pc-linux-gnu/dist/bin/firefox",
       "--headless",
       "--viewport",
       "1920x1080",
       "--env",
       "MOZ_LOG=HTMLMediaElement:5"
     ]
   }

Available Capabilities
======================

The ``firefox-devtools-mcp`` provides tools through the MCP protocol. Tool names
are generally self-describing. Simply ask your AI assistant to perform tasks - it
will use the appropriate tools. This list may not be complete as the server is
under active development.

Importantly, you can instruct the agent to run a different Firefox than the one
it picked, e.g. your own build, or some specific version, by telling it the
path: it isn't necessary to configure it.

**Page Management:**
``list_pages``, ``new_page``, ``navigate_page``, ``select_page``, ``close_page``

**DOM Interaction:**
``take_snapshot``, ``resolve_uid_to_selector``, ``click_by_uid``, ``hover_by_uid``,
``fill_by_uid``, ``fill_form_by_uid``, ``drag_by_uid_to_uid``, ``upload_file_by_uid``

**Network & Console:**
``list_network_requests``, ``get_network_request``, ``list_console_messages``,
``clear_console``

**Screenshots:**
``screenshot_page``, ``screenshot_by_uid``

**Dialogs & Navigation:**
``accept_dialog``, ``dismiss_dialog``, ``navigate_history``, ``set_viewport_size``

**Firefox Management:**
``get_firefox_info``, ``get_firefox_output``, ``restart_firefox``

**Script Evaluation:**
``evaluate_script`` (content), ``evaluate_chrome_script`` (privileged)

**Chrome Context (privileged code):**
``list_chrome_contexts``, ``select_chrome_context``, ``evaluate_chrome_script``

Working with MOZ_LOG
====================

Firefox's MOZ_LOG system provides detailed debug output from various modules.
The ``firefox-devtools-mcp`` captures this output automatically when environment
variables are set.

You can enable MOZ_LOG with something like this:

.. code-block:: text

   Developer: "Enable HTMLMediaElement logging at level 5"

   AI uses: restart_firefox(env=["MOZ_LOG=HTMLMediaElement:5"])

Common MOZ_LOG Modules
-----------------------

For a useful list of available MOZ_LOG modules and their descriptions, see
``toolkit/content/aboutLogging/aboutLogging.mjs`` in the Firefox repository, or search
searchfox.org with something like this `searchfox query <https://searchfox.org/firefox-main/search?q=LazyLogModule.*%5C%28%22&path=&case=false&regexp=true>`__.

Chrome Context Access
=====================

For debugging privileged Firefox code (chrome/XUL), enable system access:

.. code-block:: text

   restart_firefox(env=["MOZ_REMOTE_ALLOW_SYSTEM_ACCESS=1"])

Then use ``list_chrome_contexts``, ``select_chrome_context``, and
``evaluate_chrome_script`` to access ``gBrowser``, ``Components``, and other
privileged APIs.

At the moment, the MCP relies on WebDriver Classic (Marionette) for Chrome
context APIs. While WebDriver BiDi and Classic are meant to work seamlessly
together, some WebDriver BiDi features might not work when getting executed for
chrome browsing contexts. Chrome support for WebDriver BiDi is tracked on the
following `meta bug <https://bugzilla.mozilla.org/show_bug.cgi?id=1722679>`__.

Troubleshooting
===============

Try to update to the latest version:

.. code-block:: bash

   ./mach npx @mozilla/firefox-devtools-mcp-moz@latest

then quit when seeing "Ready to accept tool requests".

MCP Server Not Working
-----------------------

1. Verify the ``.mcp.json`` at the root of the repository is present.
2. Verify Node.js is available via ``./mach npx --version``.
3. Ask in #ai4dev or #developers on chat.mozilla.org

---

### Ai Agent Tools Index (`docs/ai-agent-tools/index.rst`)

======================================
AI Agent Tools for Firefox Development
======================================

This section documents tools and workflows for using AI assistants to interact
with and test Firefox during development.

.. toctree::
   :maxdepth: 2

   firefox-devtools-mcp

---

### Bug Mgmt Index (`docs/bug-mgmt/index.rst`)

Bug Handling
============

Guides
------

.. toctree::
   :maxdepth: 1
   :glob:

   guides/*

Policies
--------

.. toctree::
   :maxdepth: 1
   :glob:

   policies/*

Processes
---------

.. toctree::
   :maxdepth: 1
   :glob:

   processes/*

Related documentation
---------------------

-  `bugzilla.mozilla.org documentation <https://bmo.readthedocs.org/>`__
-  `bugzilla.mozilla.org field
   definitions <https://wiki.mozilla.org/BMO/UserGuide/BugFields>`__
-  `Lando
   documentation <https://moz-conduit.readthedocs.io/en/latest/lando-user.html>`__
-  `Mozilla Phabricator (Code Review)
   documentation <https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html>`__

---

### Code Quality Index (`docs/code-quality/index.rst`)

Code quality
============

Because Firefox is a complex piece of software, a lot of tools are
executed to identify issues at development phase.
In this document, we try to list these all tools.


.. toctree::
  :maxdepth: 1
  :glob:

  static-analysis/index.rst
  lint/index.rst
  coding-style/index.rst
  typescript/index.md

.. list-table:: C/C++
   :header-rows: 1
   :widths: 20 20 20 20 20

   * - Tools
     - Has autofixes
     - Meta bug
     - More info
     - Upstream
   * - Custom clang checker
     -
     -
     - :searchfox:`Source <build/clang-plugin>`
     -
   * - Clang-Tidy
     - Yes
     - `bug 712350 <https://bugzilla.mozilla.org/show_bug.cgi?id=712350>`__
     - :ref:`Static analysis <Static Analysis>`
     - https://clang.llvm.org/extra/clang-tidy/checks/list.html
   * - Clang analyzer
     -
     - `bug 712350 <https://bugzilla.mozilla.org/show_bug.cgi?id=712350>`__
     -
     - https://clang-analyzer.llvm.org/
   * - cpp virtual final
     -
     -
     - :ref:`cpp virtual final <cpp virtual final>`
     -
   * - clang-format
     - Yes
     - `bug 1188202 <https://bugzilla.mozilla.org/show_bug.cgi?id=1188202>`__
     - :ref:`Formatting C++ Code With clang-format`
     - https://clang.llvm.org/docs/ClangFormat.html

.. list-table:: CSS
   :widths: 20 20 20 20 20
   :header-rows: 1

   * - Tools
     - Has autofixes
     - Meta bug
     - More info
     - Upstream
   * - Stylelint
     - Yes
     - `bug 1762027 <https://bugzilla.mozilla.org/show_bug.cgi?id=1762027>`__
     - :ref:`Stylelint`
     - https://stylelint.io/
   * - Mozilla Stylelint
     -
     -
     - :ref:`Mozilla Stylelint Plugin`
     -

.. list-table:: JavaScript
   :widths: 20 20 20 20 20
   :header-rows: 1

   * - Tools
     - Has autofixes
     - Meta bug
     - More info
     - Upstream
   * - Eslint
     - Yes
     - `bug 1229856 <https://bugzilla.mozilla.org/show_bug.cgi?id=1229856>`__
     - :ref:`ESLint`
     - https://eslint.org/
   * - Mozilla ESLint
     -
     - `bug 1229856 <https://bugzilla.mozilla.org/show_bug.cgi?id=1229856>`__
     - :ref:`Mozilla ESLint Plugin`
     -
   * - Prettier
     - Yes
     - `bug 1558517 <https://bugzilla.mozilla.org/show_bug.cgi?id=1558517>`__
     - :ref:`JavaScript Coding style`
     - https://prettier.io/

.. list-table:: Python
   :widths: 20 20 20 20 20
   :header-rows: 1

   * - Tools
     - Has autofixes
     - Meta bug
     - More info
     - Upstream
   * - ruff
     - Yes
     - `bug 1811850 <https://bugzilla.mozilla.org/show_bug.cgi?id=1811850>`__
     - :ref:`ruff`
     - https://github.com/charliermarsh/ruff
   * - black
     - Yes
     - `bug 1555560 <https://bugzilla.mozilla.org/show_bug.cgi?id=1555560>`__
     - :ref:`black`
     - https://black.readthedocs.io/en/stable

.. list-table:: Rust
   :widths: 20 20 20 20 20
   :header-rows: 1

   * - Tools
     - Has autofixes
     - Meta bug
     - More info
     - Upstream
   * - Rustfmt
     - Yes
     - `bug 1454764 <https://bugzilla.mozilla.org/show_bug.cgi?id=1454764>`__
     - :ref:`Rustfmt`
     - https://github.com/rust-lang/rustfmt
   * - Clippy
     - Yes
     - `bug 1361342 <https://bugzilla.mozilla.org/show_bug.cgi?id=1361342>`__
     - :ref:`clippy`
     - https://github.com/rust-lang/rust-clippy
   * - cargo-audit
     -
     - `bug 1747536 <https://bugzilla.mozilla.org/show_bug.cgi?id=1747536>`__
     - :ref:`cargo-audit`
     - https://rustsec.org/

.. list-table:: Java/Kotlin
   :widths: 20 20 20 20 20
   :header-rows: 1

   * - Tools
     - Has autofixes
     - Meta bug
     - More info
     - Upstream
   * - Spotless
     - Yes
     - `bug 1571899 <https://bugzilla.mozilla.org/show_bug.cgi?id=1571899>`__
     - :ref:`Spotless`
     - https://github.com/diffplug/spotless

.. list-table:: Others
   :widths: 20 20 20 20 20
   :header-rows: 1

   * - Tools
     - Has autofixes
     - Meta bug
     - More info
     - Upstream
   * - shellcheck
     -
     -
     -
     - https://www.shellcheck.net/
   * - rstchecker
     -
     -
     - :ref:`RST Linter`
     - https://github.com/myint/rstcheck
   * - Typo detection
     - Yes
     -
     - :ref:`Codespell`
     - https://github.com/codespell-project/codespell
   * - Fluent Lint
     - No
     -
     - :ref:`Fluent Lint`
     -
   * - YAML linter
     - No
     -
     - :ref:`yamllint`
     - https://github.com/adrienverge/yamllint

---

### Content Security Index (`docs/content-security/index.rst`)

============================
Web Security Checks in Gecko
============================

Key Concepts and Terminology
=============================

Security Principal (nsIPrincipal)
---------------------------------

A Security Principal represents the security context for a piece of code or data. Firefox uses four types of principals:

- **ContentPrincipal**: Used for typical web pages and can be serialized to an origin URL, e.g., https://example.com/.
- **NullPrincipal**: Used for pages that are never same-origin with anything else, such as iframes with the sandbox attribute or documents loaded with a data: URI. This is also known as an opaque origin.
- **SystemPrincipal**: Used for the browser's user interface, commonly referred to as "browser chrome", and various other background services (OCSP requests, fetching favicons). Pages like about:preferences use the SystemPrincipal.
- **ExpandedPrincipal**: Used by browser extensions that need to assume the security context of a website. An ExpandedPrincipal is best understood as a list of principals.

OriginAttributes
----------------------------

`OriginAttributes` help in managing and enforcing security policies by distinguishing different security contexts that might otherwise be considered the same based on their Principal. They are used to:

- Isolate data and resources in private browsing mode.
- Implement cache isolation.
- Manage user context identifiers for container tabs.
- Enforce first-party isolation.

Attributes
----------

The `OriginAttributes` class extends the functionality of `dom::OriginAttributesDictionary` and includes additional methods for setting and managing various attributes.

Key attributes include:

- **FirstPartyDomain**: Used to isolate data based on the domain.
- **UserContextId**: Identifies different user contexts, such as container tabs.
- **PrivateBrowsingId**: Indicates whether a request is made in private browsing mode.
- **PartitionKey**: Used to implement cache isolation.


Load Info Object (nsILoadInfo)
------------------------------

The `nsILoadInfo` object is crucial for security checks. It holds all security-relevant attributes, including security flags indicating what checks need to be performed and the associated Principal.

Attributes:
-----------

- `loadingPrincipal`: The principal of the document where the result of the load will be used.
- `triggeringPrincipal`: The principal that triggered the URL to load.
- `securityFlags`: Indicate the type of security checks required.
- `contentPolicyType`: Specifies the type of content being loaded, used for security checks like Content Security Policy.

Loading Lifecycle in Firefox
============================

From Request to Response
------------------------

1. **Request Initiation**: A web page initiates a request.
2. **nsIChannel Creation**: Firefox creates an `nsIChannel` object, representing the request.
3. **nsILoadInfo Attachment**: An `nsILoadInfo` object is required for the creation of an `nsIChannel` and holds security-related information.
4. **Security Checks**: Security checks are performed using the `ContentSecurityManager`.
5. **Request Execution**: If all checks pass, the request proceeds.

Role of nsIChannel and nsILoadInfo
----------------------------------

- **nsIChannel**: Manages the transport algorithm (e.g., HTTP, WebSocket).
- **nsILoadInfo**: Holds security relevant meta information of a network load and determines what security checks need to be enforced.


Security Checks During Loading
==============================

Pre-Request Checks
------------------

- **Same-Origin Policy**: Ensures resources are only accessed if they share the same origin.
- **Content Security Policy**: Enforces content restrictions based on policies defined by the site.
- **Mixed Content Blocking**: Implements the Mixed Content standard, including blocking and upgrading of insecure (HTTP) content on secure (HTTPS) pages.

ContentSecurityManager and doContentSecurityCheck()
---------------------------------------------------

- **ContentSecurityManager**: Centralized manager for performing security checks.
- **PerformSecurityCheck()**: Key function that is invoked to perform all relevant security checks before a request is executed.

Subsumes Concept
----------------

- **Definition**: A principal subsumes another if it has access to the same resources.
- **Implementation**: `aPrincipal->Subsumes(aOtherPrincipal)` is used to check access permissions.

Code example::

    bool subsumes = principal1->Subsumes(principal2);

Subsumption is asymmetrical. One principal subsuming the other does not imply the inverse. A typical example is the `SystemPrincipal`, which subsumes all other
principals.

References
----------
The interface definition in source code have a lot of detailed comments:

- The :searchfox:`nsIPrincipal <caps/nsIPrincipal.idl>` interface definition.
- The :searchfox:`nsILoadInfo <netwerk/base/nsILoadInfo.idl>` interface definition.
- The :searchfox:`nsIContentSecurityManager <dom/interfaces/security/nsIContentSecurityManager.idl>` interface definition

---

### Contributing Code Review FAQ (`docs/contributing/Code_Review_FAQ.rst`)

Code Review FAQ
===============

What is the purpose of code review?
-----------------------------------

Code review is our basic mechanism for validating the design and
implementation of patches. It also helps us maintain a level of
consistency in design and implementation practices across the many
hackers and among the various modules of Mozilla.

Of course, code review doesn't happen instantaneously, and so there is
some latency built into the system. We're always looking for ways to
reduce the wait, while simultaneously allowing reviewers to do a good
chunk of hacking themselves. We don't have a perfect system, and we
never will. It's still evolving, so let us know if you have suggestions.

Who must review my code?
------------------------

You must have an approval (example: "r=name") from
the module owner or designated "peer" of the module where the code will
be checked in. If your code affects several modules, then generally you
should have an "r=name" from the owner or
designated peer of each affected module. We try to be reasonable here,
so we don't have an absolute rule on when every module owner must
approve. For example, tree-wide changes such as a change to a string
class or a change to text that is displayed in many modules generally
doesn't get reviewed by every module owner.

You may wish to ask others as well.


What do reviewers look for?
---------------------------

A review is focused on a patch's design, implementation, usefulness in
fixing a stated problem, and fit within its module. A reviewer should be
someone with domain expertise in the problem area. A reviewer may also
utilize other areas of his or her expertise and comment on other
possible improvements. There are no inherent limitations on what
comments a reviewer might make about improving the code.

Reviewers will probably look at the following areas of the code:

-  “goal” review: is the issue being fixed actually a bug? Does the
   patch fix the fundamental problem?
-  API/design review. Because APIs define the interactions between
   modules, they need special care. Review is especially important to
   keep APIs balanced and targeted, and not too specific or
   overdesigned. There are a `WebIDL review
   checklist <https://wiki.mozilla.org/WebAPI/WebIDL_Review_Checklist>`__.
   There are also templates for emails that should be sent when APIs are
   going to be exposed to the Web and general guidance around naming on
   `this wiki
   page <https://wiki.mozilla.org/WebAPI/ExposureGuidelines>`__.
-  Maintainability review. Code which is unreadable is impossible to
   maintain. If the reviewer has to ask questions about the purpose of a
   piece of code, then it is probably not documented well enough. Does
   the code follow the :ref:`Coding style` ? Be careful when
   reviewing code using modern C++ features like auto.
-  Security review. Does the design use security concepts such as input
   sanitizers, wrappers, and other techniques? Does this code need
   additional security testing such as fuzz-testing or static analysis?
-  Integration review. Does this code work properly with other modules?
   Is it localized properly? Does it have server dependencies? Does it
   have user documentation?
-  Testing review. Are there tests for correct function? Are there tests
   for error conditions and incorrect inputs which could happen during
   operation?
-  Performance review. Has this code been profiled? Are you sure it's
   not negatively affecting performance of other code?
-  License review. Does the code follow the `code licensing
   rules <https://www.mozilla.org/hacking/committer/committers-agreement.pdf>`__?
-  AI-assisted code review. If the patch was authored with the assistance
   of AI tools, does the contributor understand and can they explain every change?
   Does the code meet the same standards as any human-written patch?
   See the :doc:`AI Coding Policy <ai-coding>` for more details.


How can I tell the status of reviews?
-------------------------------------

When a patch has passed review you'll see "Accepted" in green at the top
of a Phabricator revision, under the title. In Bugzilla (which is
deprecated in favour of Phabricator), this is indicated by "name:review+"
in the attachment table in the
bug report. If it has failed review then you'll see "Needs Revision" in
red at the top of the revision, or, in Bugzilla, "name:review-".
Most of the time that a reviewer
sets a review flag, they will also add a comment to the bug explaining
the review.

---

### Contributing Ai Coding (`docs/contributing/ai-coding.md`)

# Firefox AI Coding Policy

This policy applies to anyone contributing to the Firefox project. It defines expectations and requirements for any usage of AI or AI-adjacent tools when authoring production code for the browser. These guidelines may evolve as the Mozilla community gains experience.

## Philosophy

AI-assisted tools are evolving quickly, but it's clear that they present both opportunities and risks when used by developers to explore, understand, and create code. They can accelerate work and help catch issues earlier, but they also make it easy to generate code that looks right without being right.

For contributors who choose to use these tools, we trust them to do so with care, just as we trust them with every other part of Firefox's development. AI can assist, but responsibility always stays with the human behind the change.

## Responsibilities

AI-assisted contributions must meet the same standards of correctness, security, and maintainability as any other patch.

### When using AI tools

* **Maintain quality and scope.** You are responsible for the technical excellence of your work, regardless of the tools you used. Keep patches small and focused so they're easy to review and clearly justified.
* **Understand what you submit.** You're expected to understand and be able to explain every change you make. The role of the [reviewer](./Code_Review_FAQ.rst) is to double-check the work of a human, not the output of a tool.
* **Self-review before submitting.** To fully understand the patch you must fully review the code yourself, before requesting peer review. In addition to this, consider running an AI review locally to catch issues you may have missed.
* **Protect sensitive data.** Do not include private, security-sensitive, or otherwise confidential information in prompts to external AI tools.

At the end of the day you are accountable for all changes you submit, regardless of the tools you use.

::: {admonition} For new contributors

"Good First" and "Good Next" bugs exist to help new contributors learn the Firefox codebase. Take these only if you intend to learn and continue contributing. Fixing a large number of these with AI tools alone is counterproductive to that goal.

:::

---

### Contributing Contributing To Mozilla (`docs/contributing/contributing_to_mozilla.rst`)

Contributing to Mozilla projects
================================

This page is here to help you get from "I want to build Firefox"
to "I'm building my own Firefox" to "I can contribute to Firefox".
So if you'd like to help Mozilla build the best web browsers in the
world, you're in the right place.

.. rubric:: Need help?
   :name: Need_help

The Mozilla community prides itself on being an open, accessible, and
friendly community for new participants. If you have any difficulties
getting involved or finding answers to your questions, please `come and
ask your questions in our
chatroom <https://chat.mozilla.org/#/room/#introduction:mozilla.org>`_,
where we can help you get started.

We know even before you start contributing that getting set up to work
on Firefox and finding a bug that's a good fit for your skills can be a
challenge, and we're always looking for ways to improve this process: making
Mozilla more open, accessible, and easier to participate with. If you're
having any trouble following this documentation, or hit a barrier you
can't get around, please join us in the Introduction room on Matrix.

What skills do I need?
----------------------

Mozilla maintains small and large projects and we are thrilled to have contributors with
very diverse skills:

-  If you know **C++,** **Rust,** **JavaScript,** **HTML** or **CSS**,
   you can :ref:`contribute to the core layers <Firefox Contributors' Quick Reference>` of
   Firefox and many other Mozilla projects.
-  If you know **Rust**, you can also contribute to the `Rust programming
   language <https://github.com/rust-lang/rust>`_ itself, numerous crates like `grcov <https://github.com/mozilla/grcov/>`_
   or `Stylo </layout/StyleSystemOverview.html>`_, Firefox's parallel CSS engine, :searchfox:`WebRender <gfx/wr/>`, Firefox's GPU-based 2D rendering engine, and `Neqo <https://github.com/mozilla/neqo>`_, our QUIC/HTTP3 networking stack.
-  If you know **Kotlin**, you can contribute to :ref:`Firefox for Android <Firefox Contributors' Quick Reference>` (code name: "Fenix"). :searchfox:`Fenix's code <mobile/android/>` is integrated into the same repository as Firefox Desktop.
-  If you know **Swift**, you can contribute to `Firefox and Firefox Focus for
   iOS <https://github.com/mozilla-mobile/firefox-ios>`_.
-  If you know **C++**, you can contribute to our `VPN client <https://github.com/mozilla-mobile/mozilla-vpn-client>`_.
-  If you know **C++** and programming language implementations, you can contribute to `SpiderMonkey <https://spidermonkey.dev/>`_, our JavaScript engine.
-  If you know **JavaScript**, you can contribute to `PDF.js <https://github.com/mozilla/pdf.js>`_, the PDF viewer shipped with Firefox.
-  If you know **C++**, **JavaScript** or **machine learning**, you can contribute to `Firefox Translations <https://github.com/mozilla/translations>`_, our local, privacy-preserving translation engine.
-  If you know **Make**, **shell**, **Perl**, or **Python**, you can
   contribute to our build systems, release engineering, and automation.
   If you know **Rust**, you can also contribute to `sccache <https://github.com/mozilla/sccache/>`_,
   our compiler caching tool used to speed up Firefox builds.
-  If you know **Go** or **JavaScript**, you can contribute to `Taskcluster
   <https://github.com/taskcluster/taskcluster>`_, our CI infrastructure.
-  If you know **C**, you can contribute to `NSS </security/nss/index.html>`_, our cryptography library.
-  There are even many ways to contribute to the Mozilla mission without
   programming. If getting involved in design, support, translation,
   testing, or other types of contributions sparks your interest please
   see the `Volunteer Opportunities
   wiki <https://contribute.mozilla.org>`_ or the `Mozilla
   community <https://community.mozilla.org/>`_ site.

Perhaps you do not know programming yet, but you want to start learning?
There are `plenty of
resources <https://developer.mozilla.org/learn>`_ available on
the MDN Web Docs!

---

### Contributing Contribution Quickref (`docs/contributing/contribution_quickref.rst`)

Firefox Contributors' Quick Reference
=====================================

Some parts of this process, including cloning and compiling, can take a long time even on modern hardware.
If at any point you get stuck, please don't hesitate to ask at `https://chat.mozilla.org <https://chat.mozilla.org>`__
in the `#introduction <https://chat.mozilla.org/#/room/#introduction:mozilla.org>`__ channel.

Don’t hesitate to look at the :ref:`Getting Set Up To Work On The Firefox Codebase<Getting Set Up To Work On The Firefox Codebase>` for a more detailed tutorial.

Before you start
----------------
Please register and create your account for

`Bugzilla <https://bugzilla.mozilla.org/>`__ : web-based general-purpose bug tracking system.
To register with Phabricator, make sure you enable Two-Factor Authentication (My Profile >> Edit Profile & Preferences >> Two-Factor Authentication) in Bugzilla.

`Phabricator <https://phabricator.services.mozilla.com/>`__: web-based software development collaboration tools, mainly for code review.
Please obtain an API Token (Settings >> Conduit API Tokens)

Windows dependencies
--------------------

#. You need a :ref:`supported version of Windows<tier_1_hosts>`.
#. Download the `MozillaBuild Package. <https://ftp.mozilla.org/pub/mozilla/libraries/win32/MozillaBuildSetup-Latest.exe>`__ Installation directory should be:

    .. code-block:: shell

        $ c:\mozilla-build\

#. Before moving on to the next steps, make sure to fulfill the :ref:`Windows prerequisites <Building Firefox On Windows>`

.. note::

    All the commands of this tutorial must be run in the shell provided with the MozillaBuild Package (start-shell.bat)

:ref:`More information on building Firefox on Windows <Building Firefox On Windows>`

Bootstrap a copy of the Firefox source code
-------------------------------------------

You can download the source code and have Firefox automatically download and install the other dependencies it needs. The below command as per your Operating System, will download a lot of data (years of Firefox history!) then guide you through the interactive setup process.

Downloading can take from 40 minutes to two hours (depending on your connection) and the repository should be less than 5GB (~ 20GB after the build).

The **default options are recommended**.
If you're not planning to write C++ or Rust code, select :ref:`Artifact Mode <Understanding Artifact Builds>`
and follow the instructions at the end of the bootstrap for creating a mozconfig file.

To Setup Firefox On Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: shell

    $ cd c:/
    $ mkdir mozilla-source
    $ cd mozilla-source
    $ wget https://raw.githubusercontent.com/mozilla-firefox/firefox/refs/heads/main/python/mozboot/bin/bootstrap.py

    $ python3 bootstrap.py

More information on :ref:`building Firefox for Windows <Building Firefox On Windows>`.

To Setup Firefox On macOS and Linux
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: shell

    $ curl -L https://raw.githubusercontent.com/mozilla-firefox/firefox/refs/heads/main/python/mozboot/bin/bootstrap.py -O

    $ python3 bootstrap.py

More information on :ref:`building Firefox for Linux <Building Firefox On Linux>` and :ref:`building Firefox for MacOS <Building Firefox On MacOS>`.

To Setup Firefox for Android
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: shell

    $ curl -L https://raw.githubusercontent.com/mozilla-firefox/firefox/refs/heads/main/python/mozboot/bin/bootstrap.py -O

    $ python3 bootstrap.py

More information on :ref:`building Firefox for Android <Firefox for Android>`

To set up your editor
---------------------

.. note::

    Visual Studio Code is the recommended editor for Firefox development.
    Not because it is better than the other editors but because we decided to
    focus our energy on a single editor.

Setting up your editor is an important part of the contributing process. Having
linting and other features integrated, saves you time and will help with reducing
build and reviews cycles.

See our :ref:`editor page for more information about how to set up your favorite editor <Editor / IDE integration>`.

More advanced git configuration
-------------------------------

See the :ref:`Git tips and tricks page <Git Tricks>` to use a personal fork, and for other useful git configurations.

To build & run
--------------

Once the System is bootstrapped, run:

.. code-block:: shell

    $ cd firefox
    $ ./mach build

which will check for dependencies and start the build.
This will take a while; a few minutes to a few hours depending on your hardware.

.. note::

    If you build Firefox often, add `ac_add_options \-\-with-ccache=sccache` to .mozconfig.
    sccache will significantly speed up your builds by caching compilation results.
    The Firefox build system will download sccache automatically.

.. note::

    The default build is a compiled build with optimizations. Check out the
    :ref:`mozconfig file documentation <Configuring Build Options>`
    to see other build options. If you don't plan to change C++ or Rust code,
    an :ref:`artifact build <Understanding Artifact Builds>` will be faster.

To run it:

.. code-block:: shell

     $ ./mach run

This command will open your locally built Firefox in a new window.

:ref:`More information about building Firefox on Linux <Building Firefox On Linux>` / :ref:`More information about building Firefox on MacOS <Building Firefox On MacOS>`

If you encounter build errors, please reference the more detailed "Building Firefox" on your specific operating system document and specifically the "Troubleshooting" section.

.. _write_a_patch:

To write a patch
----------------

Make the changes you need in the codebase. You can look up UI text in `Searchfox <https://searchfox.org>`__ to find the right file.

.. note::
    If you are unsure of what changes you need to make, or need help from the mentor of the bug,
    please don't hesitate to use the needinfo feature ("Request information from") on `Bugzilla <https://bugzilla.mozilla.org/home>`__ to get the attention of your mentor.


After making your changes, visualize your changes to ensure you're including all the necessary work:

.. code-block:: shell

    # For files changed/added/removed
    $ git status

    # For detailed line changes
    $ git diff

Then commit your changes:

.. code-block:: shell

    # Git
    $ git commit

.. _Commit message:

The commit message should look like:

.. code-block:: text

    Bug xxxx - Short description of your change. r?reviewer

    Optionally, a longer description of the change.

**Make sure you include the bug number and at least one reviewer (or reviewer group) in this format.**

For example, here is an example of a good commit message:
"Bug 123456 - Null-check presentation shell so we don't crash when a button removes itself
during its own onclick handler. r=person"

To :ref:`find a reviewer or a review group <Getting reviews>`, the easiest way is to run
`git log <modified-file>`` on the relevant files, and look who usually is
reviewing the actual changes (ie not reformat, renaming of variables, etc).


To visualize your patch in the repository, run:

.. code-block:: shell

    # Git
    $ git show

:ref:`More information on how to work with stack of patches <Working with stack of patches Quick Reference>`

To make sure the change follows the coding style
------------------------------------------------

To detect coding style violations, use mach lint:

.. code-block:: shell

    $ ./mach lint path/to/the/file/or/directory/you/changed

    # To get the autofix, add --fix:
    $ ./mach lint path/to/the/file/or/directory/you/changed --fix

:ref:`More information <Code quality>`

To test a change locally
------------------------

To run the tests, use mach test with the path. However, it isn’t
always easy to parse the results.

.. code-block:: shell

    $ ./mach test dom/serviceworkers

To run tests based on :ref:`GTest` (C/C++ based unit tests), run:

.. code-block:: shell

    $ ./mach gtest 'QuotaManager.*'

To test a change remotely
-------------------------

Running all the tests for Firefox takes a very long time and requires multiple
operating systems with various configurations. To build Firefox and run its
tests on continuous integration servers (CI), multiple :ref:`options to select tasks <Selectors>`
are available.

To automatically select the tasks that are most likely to be affected by your changes, run:

.. code-block:: shell

    $ ./mach try auto

To select tasks manually using a fuzzy search interface, run:

.. code-block:: shell

    $ ./mach try fuzzy

To rerun the same tasks:

.. code-block:: shell

    $ ./mach try again

From `Treeherder <https://treeherder.mozilla.org/>`__ (our continuous integration system), it is also possible to attach new jobs. As every review has
a try CI run associated, it makes this work easier. See :ref:`attach-job-review` for
more information.

.. note::

    This requires `level 1 commit access <https://www.mozilla.org/about/governance/policies/commit/access-policy/>`__.

    You can ask your reviewer to submit the patch for you if you don't have that
    level of access.

:ref:`More information <Pushing to Try>`


If you used AI tools
--------------------

AI-assisted tools can help you write patches, but you are accountable for what you submit.
Before requesting review, make sure you understand and can explain every change in your
patch -- a reviewer's job is to double-check a human's work, not a tool's output. Taking
the time to read through and understand the patch yourself helps reviews go smoothly.

If your AI tool offers a code review feature (for example, a ``/review`` command),
running it in a fresh session before submitting can catch issues your working session and
self-review may have missed.

See the :doc:`AI Coding Policy <ai-coding>` for the full expectations.

To submit a patch
-----------------

To submit a patch for review, we use a tool called `moz-phab <https://pypi.org/project/MozPhab/>`__.
To install it, run:

.. code-block:: shell

     $ ./mach install-moz-phab

Once you want to submit your patches (make sure you :ref:`use the right commit message <Commit message>`), run:

.. code-block:: shell

     $ moz-phab

It will publish all the currently applied patches to Phabricator and inform the reviewer.

If you wrote several patches on top of each other:

.. code-block:: shell

    $ moz-phab submit <first_revision>::<last_revision>

`More
information on how to use Phabricator and MozPhab <https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html>`__

To update the working directory
-------------------------------

If you're finished with a patch and would like to return to the tip to make a new patch:

.. code-block:: shell

    $ git pull --rebase

To update a submitted patch
---------------------------

It is rare that a reviewer will accept the first version of patch. Moreover,
as the code review bot might suggest some improvements, changes to your patch
may be required.

If your patch is not loaded in your working directory, you first need to re-apply it:

.. code-block:: shell

    $ moz-phab patch D<revision_id>

    # Or you can use the URL of the revision on Phabricator
    $ moz-phab patch https://phabricator.services.mozilla.com/D<revision_id>

Make your changes in the working folder and run:

.. code-block:: shell

   # Git
   $ git commit --amend

After amending the patch, you will need to submit it using moz-phab again.

.. warning::

    Don't use ``git commit --amend -m``.

    Phabricator tracks revision by editing the commit message when a
    revision is created to add a special ``Differential Revision:
    <url>`` line.

    When ``--amend -m`` is used, that line will be lost, leading to
    the creation of a new revision when re-submitted, which isn't
    the desired outcome.

If you wrote many changes, you can squash or edit commits with the
command:

.. code-block:: shell

   # Git
   $ git rebase -i

The submission step is the same as for the initial patch.

:ref:`More information on how to work with stack of patches <Working with stack of patches Quick Reference>`

Retrieve new changes from the repository
----------------------------------------

To pull changes from the repository, run:

.. code-block:: shell

   # Git
   $ git pull --rebase

.. _push_a_change:

To push a change in the code base
---------------------------------

Once the change has been accepted and you've fixed any remaining issues
the reviewer identified, the reviewer should land the patch.

If the patch has not landed on "autoland" (the integration branch) after a few days,
feel free to contact the reviewer and/or
@Aryx or @Sylvestre on the `#introduction <https://chat.mozilla.org/#/room/#introduction:mozilla.org>`__
channel.

The landing procedure will automatically close the review and the bug.

:ref:`More information <How to submit a patch>`

Contributing to GeckoView
-------------------------

Note that the GeckoView setup and contribution processes are different from those of Firefox;
GeckoView setup and contribution docs live in `geckoview.dev <https://geckoview.dev>`__.

More documentation about contribution
-------------------------------------

:ref:`How to Contribute Code to Firefox`

:ref:`Contributing to Mozilla projects`

https://mozilla-version-control-tools.readthedocs.io/en/latest/devguide/contributing.html

https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html

---

### Contributing Data Collection (`docs/contributing/data-collection.md`)

# Data Collection

Most Firefox features operate entirely on-device. A feature involving one or
more connections to a Mozilla server qualifies as data collection. Even if the
request data is not actually retained by Mozilla, it should be reviewed as if
it might be, so that the privacy properties of Firefox can be verified without
relying on retention commitments.

As part of our overall [vision for privacy][privacy-vision], we hold Firefox to
an unusually high standard with respect to handling user data. Accordingly, any
data collection needs to be carefully vetted for consistency with this standard.
Our engineering processes are designed to ensure this vetting happens
consistently, but browsers are extremely complex and mistakes can happen. As
such, everyone who works on Firefox is responsible for understanding our rules
for data and speaking up if something doesn’t look right.

This document outlines our approach and policies on a few key topics.

## User Control

Users must be able to disable any network connection from the client to Mozilla.
Absent a good reason, this should be possible as a supported configuration in
the browser UI. In the rare situations where we do have a good reason not to
offer a control in Firefox settings (e.g., fetching the malicious add-ons
blocklist), there must still be a [documented mechanism][sumo-stop-connections]
to disable the connection in `about:config`.

## Browsing Data

A longstanding tenet of Firefox development is that _even Mozilla_ shouldn’t be
able to learn what a user does online — sites they visit, what they do on them,
etc. This is different from many other browsers and internet applications, where
the vendor routinely collects and stores sensitive user data on their servers.
Rather than asking users to trust Mozilla with this information, Firefox aims to
provide _verifiable guarantees_ of secrecy: someone should be able to inspect
the source code and verify that it is never revealed in the first place. There
are various edge-case [exceptions](#exceptions) to this posture, but that’s the
big picture.

The simplest guarantee is inspectable source code that never transmits the
data[^1]. This is how Firefox handles browsing data modulo a _very_ small number
of exceptions. Those exceptions are situations where we use some form of
encryption to create a verifiable guarantee for an important online use-case.
For example, the history and bookmark sync feature for Firefox Accounts uses
end-to-end encryption to store browsing history on Mozilla’s servers without
Mozilla learning the contents. The approved technologies for verifiable
guarantees are outlined [below](#verifiable-guarantees).

The consequence of these restrictions on sensitive data is that nearly all of
the data transmitted by Firefox to Mozilla falls into the
not-particularly-sensitive bucket. This includes the data exchanged to power
various cloud-supported features (updates, add-ons, push notifications, etc) as
well as measurement telemetry (described in the next section).

## Telemetry and Experiments

Firefox contains various [measurement probes][gleandict] to help us understand
and improve the browser, loosely known within Mozilla as “Telemetry”[^2]. This
instrumentation is enabled by default, but can be disabled during onboarding, in
settings, or through various other mechanisms (e.g., enterprise policies). Some
representative probes include [OS version][os-version-dict],
[memory usage][memory-dict], [CSS use-counters][usercounter-dict], and
[number of interactions with the bookmarks bar][bookmarks-dict]. In addition to
telemetry, other measurement probes collect data on a more de-identified basis
for measuring daily usage numbers and for some engagement and attribution
purposes.

Sitting atop this infrastructure is an optional experimentation system. This
allows us to deploy features to subsets of our user base to ensure they perform
as expected. For example, we might deploy a new network protocol backend to 1%
of our users to ensure it doesn’t increase average connection times or failure
rates.

Building a full-stack, web-compatible browser is extremely complicated, and
there is no realistic way to do it without representative telemetry and
experimentation. For example, page-load speed depends on many factors like
network conditions and hardware quirks which cannot be exhaustively tested in
automation. Telemetry allows Mozilla to determine how Firefox is performing for
users, and measure whether big changes make things faster or slower before
deploying them to everyone. The browsers that brag about not having telemetry
all use someone else’s engine (generally Chromium), and thus rely on the engine
vendor to collect telemetry and tune the stack correctly. We strive to keep
Firefox independent and competitive, so we need infrastructure to tell us what
is and is not working well.

Ordinary telemetry is associated with a pseudonymous identifier called a client
ID. Our data infrastructure endeavors to make it difficult to associate a client
ID with identifiable data, but this is not a strong guarantee. Therefore,
ordinary telemetry is generally restricted to low-sensitivity technical and
interaction data. Note that “interaction” here refers to interaction with
_Firefox UI_, not web content. The latter would inherently reveal browsing data,
and is thus off-limits.

## Verifiable Guarantees

As discussed above, sensitive information like browsing data must be protected
by a verifiable guarantee of secrecy (modulo the exceptions listed
[below](#exceptions)). This section outlines the current mechanisms Firefox uses
to provide such a guarantee in different situations:

1. **On-Device Processing:** This is the default, and should be used wherever
   possible.
2. **End-to-End Encryption:** This is used for situations where Mozilla needs to
   store user data as an opaque payload. The bookmark, history, and password
   sync feature is the canonical use-case for this feature. To be clear, the
   ‘ends’ of this type of End-to-End encryption are a users’ devices, and
   exclude Mozilla.
3. **Oblivious HTTP:** OHTTP is an [IETF standard][ietf-ohttp] for concealing
   the IP address in HTTPS transactions which can be used to create a verifiable
   guarantee that a network service cannot link a request to a client. It does
   this by routing the request through an independently-operated relay (in our
   case, [Fastly][dap-ohttp-partners]). The protocol ensures that the relay
   provider sees the source of the request but not the contents, and the
   endpoint sees the contents but not the source (see the
   [SUMO OHTTP explanation][sumo-ohttp]). For this to work, the payload must be carefully vetted
   to ensure that its contents are non-identifying. There are obvious ways to
   get this wrong (e.g., including any sort of personal identifier), but subtler
   ones as well (e.g., a set of innocuous values that could be jointly unique
   to a user). For this reason, any usage of OHTTP requires careful analysis
   from a privacy expert as part of data review.
4. **DAP/Prio:** [DAP][ietf-dap] is a standards-track Multi-Party Computation
   (MPC) aggregate measurement protocol with formally verifiable privacy
   guarantees. It allows computing aggregate statistics across a population
   (e.g., how many users visit this page with a known web-compat issue) without
   the individual data points being revealed to any party off the device. There
   are a lot of [complicated details][dap-explainer], but an important upshot is
   that the protocol incorporates differential privacy guards to make it
   virtually impossible to inadvertently leak individual information with too
   small of a sample (it does this by automatically adding noise whose magnitude
   is inversely proportional to the sample size). Firefox’s DAP node is
   [operated by ISRG][dap-ohttp-partners], who also operates Let’s Encrypt.

### Exceptions

There are a few exceptional cases where information related to a website visited
by the user is sent to Mozilla without a verifiable guarantee. These are
generally unsurprising and self-explanatory, but it’s worth writing them down.
If you discover one that isn’t listed here, please flag it to the
[Firefox Technical Leadership Committee][fx-tlc] so that it can be either
addressed or added to this list:

- **Specific opt-in consent:** For example, submitting a crash report with a
  memory dump (which, depending on the crash location and the compiler memory
  layout, could include data like URLs).
- **Explicit user action:** For example, submitting a report to us that a site
  is broken.
- **Site-specific feature integrations for widely-used sites:** For example, we
  learn users visit Google to search, and we learned users visited Facebook when
  they received the contextual prompt to install the Facebook container.
- **Visiting a Mozilla-operated website:** Mozilla, like any website operator,
  has the technical capability to observe which websites are loaded by a given
  IP address. Some sites, like [addons.mozilla.org](http://addons.mozilla.org),
  also have special hooks to deliver browser functionality.

## Data Review

Any data collection introduced to Firefox requires careful review. Our code
review system automatically detects the most common patterns (e.g., new or
modified [glean probes][gleandict]) and flags any matching changesets for
classification. However, these heuristics may not catch unusual patterns, and so
code reviewers are responsible for manually flagging anything that slips through
the cracks.

The details of the data review process for Firefox patches are documented
in the [data review process][data-review].

[^1]: To Mozilla. To state the obvious, the architecture of the web platform
means that interactions with a website are generally observable to the operator
of that website.

[^2]: This is referred to in documentation and settings as “technical and
interaction data”. People often mistakenly equate this with “data collection in
Firefox”, but the latter is a broader category. For example, Firefox also has a
separate [daily usage ping][usage-ping] to count users, and the content feed on
New Tab maintains its own separate communication channel. These are all
optional, but the features are controlled separately. Disabling Telemetry does
not disable the New Tab content, and vice-versa.

[privacy-vision]: https://www.mozilla.org/en-US/about/webvision/full/#privacy
[sumo-stop-connections]: https://support.mozilla.org/en-US/kb/how-stop-firefox-making-automatic-connections
[gleandict]: https://dictionary.telemetry.mozilla.org/
[os-version-dict]: https://dictionary.telemetry.mozilla.org/apps/firefox_desktop/metrics/os_version
[memory-dict]: https://dictionary.telemetry.mozilla.org/apps/firefox_desktop/metrics/memory_heap_allocated
[usercounter-dict]: https://dictionary.telemetry.mozilla.org/apps/firefox_desktop?page=1&search=use.counter.css
[bookmarks-dict]: https://dictionary.telemetry.mozilla.org/apps/firefox_desktop/metrics/browser_ui_interaction_bookmarks_bar
[ietf-ohttp]: https://datatracker.ietf.org/doc/rfc9458/
[dap-ohttp-partners]: https://blog.mozilla.org/en/products/firefox/partnership-ohttp-prio/
[sumo-ohttp]: https://support.mozilla.org/en-US/kb/ohttp-explained
[ietf-dap]: https://datatracker.ietf.org/doc/html/draft-ietf-ppm-dap-11
[dap-explainer]: https://educatedguesswork.org/posts/ppm-prio/
[fx-tlc]: https://wiki.mozilla.org/Modules/Firefox_Technical_Leadership
[data-review]: ./data-review
[usage-ping]: https://support.mozilla.org/en-US/kb/usage-ping-settings

---

### Contributing Data Review (`docs/contributing/data-review.rst`)

Data Review
-----------

**Everything that lands in mozilla-central that adds or expands data
collection must go through the data review process.**

The data review process is in place to ensure we follow Firefox's
:doc:`standards for data collection <data-collection>`.

This will require assessing the sensitivity of the data that is being
collected, and going through the `sensitive data collection
process <https://wiki.mozilla.org/Data_Collection#Step_3:_Sensitive_Data_Collection_Review_Process>`__
if necessary. All data collection is subject to our `overall data
collection policy <https://wiki.mozilla.org/Data_Collection>`__.

Documentation for the data collection request process and the
expectations we have for people following it `lives on the
wiki <https://wiki.mozilla.org/Data_Collection#Requesting_Data_Collection>`__.
This document describes the technical implementation in Phabricator
using tags.

1. Any change that touches metrics will be automatically flagged with a
   ``needs-data-classification`` tag by Phabricator, using `this herald
   rule <https://phabricator.services.mozilla.com/H436>`__. If a change
   adds/updates data collection in a way that doesn’t automatically
   trigger this rule, this tag should be added manually (and if
   appropriate, please file a bug to update the herald rule so it
   happens automatically next time).

2. After assessing data sensitivity, the tag can be replaced with either
   ``data-classification-low`` or ``data-classification-high`` depending
   on that sensitivity.

3. Adding ``data-classification-high`` will auto-add the ``#data-stewards``
   reviewer group as a blocking reviewer for the change and initiate the
   `sensitive data review process <https://wiki.mozilla.org/Data_Collection#Step_3:_Sensitive_Data_Collection_Review_Process>`__.

4. For patches making mechanical changes that happen to trigger the
   herald rule linked above, but that do not actually add or update any
   data collection, the ``data-classification-unnecessary`` tag can be used.

Patches with the ``needs-data-classification`` tag will not be landable in
Lando. The process linked above must be followed in order to land the
change.

---

### Contributing Directory Structure (`docs/contributing/directory_structure.rst`)

Firefox Source Code Directory Structure
=======================================

This article provides an overview of what the various directories contain.

To simply take a look at the Firefox source code, you do not need to
download it. You can look at the source directly with your web browser
using Searchfox (start at https://searchfox.org/firefox-main/source for
the complete firefox source code of branch HEAD).

In order to modify the source, you have to acquire it either by
downloading a :ref:`snapshot <Firefox Contributors' Quick Reference>` of the sources or
by checking out the current sources from
:ref:`the repository <Firefox Contributors' Quick Reference>`.

This document describes the directory structure -- i.e., directories that
are used by at least some of the
Mozilla project's client products. There are other directories in the
other Mozilla repository, such as those for Web tools and those for the
Classic codebase.

See the `more detailed overview of the pieces of Gecko <https://wiki.mozilla.org/Gecko:Overview>`__.

.cargo
------

Configuration files for the `Cargo package
manager <https://crates.io/>`__.

.vscode
-------

Configuration files used by the `Visual Studio Code
IDE <https://code.visualstudio.com/>`__ when working in the
mozilla-central tree.

accessible
----------

Files for accessibility (i.e., MSAA (Microsoft Active Accessibility),
ATK (Accessibility Toolkit, used by GTK) support files). See
`Accessibility <https://developer.mozilla.org/docs/Web/Accessibility>`__.


browser
-------

Contains the front end code (in XUL, Javascript, XBL, and C++) for the
Firefox desktop browser. Many of these files started off as a copy of files in
`xpfe <#xpfe>`__.

browser/extensions
------------------

Contains `PDF.js <https://mozilla.github.io/pdf.js/>`__ and
`WebCompat <https://github.com/mozilla/webcompat-addon>`__ built-in extensions.

browser/themes
--------------

Contains images and CSS files to skin the browser for each OS (Linux,
Mac and Windows)

build
-----

Miscellaneous files used by the build process. See also `config <#config>`__.

caps
----

Capability-based web page security management. It contains C++ interfaces
and code for determining the capabilities of content based on the
security settings or certificates (e.g., VeriSign). See `Component
Security <https://www.mozilla.org/projects/security/components/>`__ .

chrome
------

:ref:`Chrome registry <Chrome Registration>` used with `toolkit <#toolkit>`__/.
These files were originally copies of files in `rdf/chrome/`.

config
------

More files used by the build process, common includes for the makefiles,
etc.


devtools
--------

The Firefox Developer Tools server and client components. See :ref:`contributor <devtools-contributor-doc>` and :ref:`user <devtools-user-doc>` documentation.


docs
----

Contains the documentation configuration (`Sphinx <http://www.sphinx-doc.org/>`__ based), the index page
and the contribution pages.


docshell
--------

Implementation of the docshell, the main object managing things related
to a document window. Each frame has its own docshell. It contains
methods for loading URIs, managing URI content listeners, etc. It is the
outermost layer of the embedding API used to embed a Gecko browser into
an application.

dom
---

-  :ref:`IDL definitions <XPIDL>` of the interfaces defined by
   the DOM specifications and Mozilla extensions to those interfaces
   (implementations of these interfaces are primarily, but not
   completely, in `content <#content>`__).
-  The parts of the connection between JavaScript and the
   implementations of DOM objects that are specific both to JavaScript
   and to the DOM.
-  Implementations of a few of the core "DOM Level 0" objects, such as
   `window <https://developer.mozilla.org/docs/Web/API/Window>`__ , `window.navigator <https://developer.mozilla.org/docs/Web/API/Window/navigator>`__, `window.location <https://developer.mozilla.org/docs/Web/API/Window/location>`__, etc.

editor
------

The editor directory contains XUL/Javascript for the embeddable editor
component, which is used for the HTML Editor("Composer"), for plain and
HTML mail composition, and for text fields and text areas throughout the
product. The editor is designed like a
"browser window with editing features": it adds some special classes for
editing text and managing transaction undo/redo, but reuses browser code
for nearly everything else.

extensions
----------

Contains several extensions to mozilla, which can be enabled at
compile-time using the ``--enable-extensions`` configure argument.

Note that some of these are now built specially and not using the
``--enable-extensions`` option. For example, disabling xmlextras is done
using ``--disable-xmlextras``.


extensions/auth
---------------

Implementation of the negotiate auth method for HTTP and other
protocols. Has code for SSPI, GSSAPI, etc. See `Integrated
Authentication <https://www.mozilla.org/projects/netlib/integrated-auth.html>`__.


extensions/pref
---------------

Preference-related extensions.

extensions/spellcheck
---------------------

Spellchecker for mailnews and composer.

extensions/universalchardet
---------------------------

Detects the character encoding of text.

gfx
---

Contains interfaces that abstract the capabilities of platform specific
graphics toolkits, along with implementations on various platforms.
These interfaces provide methods for things like drawing images, text,
and basic shapes. It also contains basic data structures such as points
and rectangles used here and in other parts of Mozilla.

gradle
------

Containing files related to a Java build system.

hal
---

Contains platform specified functions (e.g. obtaining battery status,
sensor information, memory information, Android
alarms/vibrate/notifications/orientation, etc)

image
-----

Image rendering library. Contains decoders for the image formats Firefox
supports.

intl
----

Internationalization and localization support. See
`L10n:NewProjects <https://wiki.mozilla.org/L10n:NewProjects>`__.

intl/locale
-----------

Code related to determination of locale information from the operating
environment.

intl/lwbrk
----------

Code related to line breaking and word breaking.

intl/strres
-----------

Code related to string resources used for localization.

intl/uconv
----------

Code that converts (both ways: encoders and decoders) between UTF-16 and
many other character encodings.

intl/unicharutil
----------------

Code related to implementation of various algorithms for Unicode text,
such as case conversion.

ipc
---

Container for implementations of IPC (Inter-Process Communication).

js/src
------

The JavaScript engine, also known as
:ref:`SpiderMonkey <SpiderMonkey>`.
See also `JavaScript <https://developer.mozilla.org/docs/JavaScript>`__.

js/xpconnect
------------

Support code for calling JavaScript code from C++ code and C++ code from
JavaScript code, using XPCOM interfaces. See
`XPConnect <https://developer.mozilla.org/docs/XPConnect>`__.

layout
------

Code that implements a tree of rendering objects that describe the types
and locations of the objects that are displayed on the screen (such as
CSS boxes, tables, form controls, XUL boxes, etc.), and code that
manages operations over that rendering tree (such as creating and
destroying it, doing layout, painting, and event handling). See
`documentation <https://www.mozilla.org/newlayout/doc/>`__ and `other
information <https://www.mozilla.org/newlayout/>`__.

layout/base
-----------

Code that deals with the rendering tree.

layout/forms
------------

Rendering tree objects for HTML form controls.

layout/generic
--------------

The basic rendering object interface and the rendering tree objects for
basic CSS boxes.

layout/mathml
-------------

Rendering tree objects for `MathML <https://developer.mozilla.org/docs/Web/MathML>`__.

layout/svg
----------

Rendering tree objects for `SVG <https://developer.mozilla.org/docs/Web/SVG>`__.

layout/tables
-------------

Rendering tree objects for CSS/HTML tables.

layout/xul
----------

Additional rendering object interfaces for `XUL <https://developer.mozilla.org/docs/XUL>`__ and
the rendering tree objects for XUL boxes.

media
-----

Contains sources of used media libraries for example *libpng*.

memory
------

Cross-platform wrappers for *memallocs* functions etc.

mfbt
----

Implementations of classes like *WeakPtr*. Multi-platform *assertions*
etc.

mobile
------

mobile/android
--------------

Firefox for Android and Geckoview

modules
-------

Compression/Archiving, math library, font (and font compression),
Preferences Library

modules/libjar
--------------

Code to read zip files, used for reading the .jar files that contain the
files for the mozilla frontend.

modules/libpref
---------------

Library for reading and writing preferences.

modules/zlib
------------

Source code of zlib, used at least in the networking library for
compressed transfers.

mozglue
-------

Glue library containing various low-level functionality, including a
dynamic linker for Android, a DLL block list for Windows, etc.

netwerk
-------

:ref:`Networking library <Networking>`, also known as Necko.
Responsible for doing actual transfers from and to servers, as well as
for URI handling and related stuff.

netwerk/cookie
--------------

Permissions backend for cookies, images, etc., as well as the user
interface to these permissions and other cookie features.

nsprpub
-------

Netscape Portable Runtime. Used as an abstraction layer to things like
threads, file I/O, and socket I/O. See :ref:`NSPR`.

nsprpub/lib
-----------

Mostly unused; might be used on Mac?

other-licenses
--------------

Contains libraries that are not covered by the MPL but are used in some
Firefox code.

parser
------

Group of structures and functions needed to parse files based on
XML/HTML.

parser/expat
------------

Copy of the expat source code, which is the XML parser used by mozilla.

parser/html
-----------

The HTML parser (for everything except about:blank).

parser/htmlparser
-----------------

The legacy HTML parser that's still used for about:blank. Parts of it
are also used for managing the conversion of the network bytestream into
Unicode in the XML parsing case.

parser/xml
----------

The code for integrating expat (from parser/expat) into Gecko.

python
------

Cross module python code.

python/mach
-----------

The code for the :ref:`Mach` building tool.

security
--------

Contains NSS and PSM, to support cryptographic functions in mozilla
(like S/MIME, SSL, etc). See :ref:`Network Security Services (NSS)`
and
`Personal Security Manager
(PSM) <https://www.mozilla.org/projects/security/pki/psm/>`__.

services
--------

Firefox accounts and sync (history, preferences, tabs, bookmarks,
telemetry, startup time, which addons are installed, etc). See
`here <https://docs.services.mozilla.com/>`__.

servo
-----

`Servo <https://servo.org/>`__, the parallel browser engine project.

startupcache
------------

XXX this needs a description.

storage
-------

`Storage <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Storage>`__: XPCOM wrapper for sqlite. Wants to
unify storage of all profile-related data. Supersedes mork. See also
`Unified Storage <https://wiki.mozilla.org/Mozilla2:Unified_Storage>`__.

taskcluster
-----------

Scripts and code to automatically build and test Mozilla trees for the
continuous integration and release process.

testing
-------

Common testing tools for mozilla codebase projects, test suite
definitions for automated test runs, tests that don't fit anywhere else,
and other fun stuff.

third_party
-----------

Vendored dependencies maintained outside of Mozilla.

toolkit
-------

The "new toolkit" used by Thunderbird, Firefox, etc. This contains
numerous front-end components shared between applications as well as
most of the XBL-implemented parts of the XUL language (most of which was
originally forked from versions in `xpfe/`).

toolkit/mozapps/extensions/test/xpinstall
-----------------------------------------

The installer, which contains code for installing Mozilla and for
installing XPIs/extensions. This directory also contains code needed to
build installer packages. See `XPInstall <https://developer.mozilla.org/docs/XPInstall>`__ and
the `XPInstall project
page <https://www.mozilla.org/projects/xpinstall/>`__.

tools
-----

Some tools which are optionally built during the mozilla build process.

tools/lint
----------

The linter declarations and configurations.
See `linting documentation </code-quality/lint/>`_

uriloader
---------

uriloader/base
--------------

Content dispatch in Mozilla. Used to load uris and find an appropriate
content listener for the data. Also manages web progress notifications.
See `Document Loading: From Load Start to Finding a
Handler <https://www.mozilla.org/docs/docshell/uri-load-start.html>`__
and `The Life Of An HTML HTTP
Request <https://www.mozilla.org/docs/url_load.html>`__.


uriloader/exthandler
--------------------

Used to handle content that Mozilla can't handle itself. Responsible for
showing the helper app dialog, and generally for finding information
about helper applications.

uriloader/prefetch
------------------

Service to prefetch documents in order to have them cached for faster
loading.

view
----

View manager. Contains cross-platform code used for painting, scrolling,
event handling, z-ordering, and opacity. Soon to become obsolete,
gradually.

widget
------

A cross-platform API, with implementations on each platform, for dealing
with operating system/environment widgets, i.e., code related to
creation and handling of windows, popups, and other native widgets and
to converting the system's messages related to painting and events into
the messages used by other parts of Mozilla (e.g., `view/` and
`content/`, the latter of which converts many of the
messages to yet another API, the DOM event API).

xpcom
-----

`Cross-Platform Component Object Model </en-US/docs/XPCOM>`__. Also
contains data structures used by the rest of the mozilla code. See also
`XPCOM Project <https://www.mozilla.org/projects/xpcom/>`__.

xpfe
----

XPFE (Cross Platform Front End) is the SeaMonkey frontend. It contains
the XUL files for the browser interface, common files used by the other
parts of the mozilla suite, and the XBL files for the parts of the XUL
language that are implemented in XBL. Much of this code has been copied
to `browser/` and `toolkit/` for use in
Firefox, Thunderbird, etc.


xpfe/components
---------------

Components used by the Mozilla frontend, as well as implementations of
interfaces that other parts of mozilla expect.

---

### Contributing Editor (`docs/contributing/editor.rst`)

Editor / IDE integration
========================

You can use any editor or IDE to contribute to Firefox, as long as it can edit
text files. However, there are some steps specific to mozilla-central that may
be useful for a better development experience. This page attempts to document
them.

.. note::

    Visual Studio Code is the recommended editor for Firefox development.
    Not because it is better than the other editors but because we decided to
    focus our energy on a single editor.

.. note::

    This page is a work in progress. Please enhance this page with instructions
    for your favourite editor.

.. toctree::
    :maxdepth: 1

    editors/vscode
    editors/emacs
    editors/vim
    editors/others

---

### Contributing Engineering Show And Tell (`docs/contributing/engineering_show_and_tell.rst`)

Engineering Show and Tell
=========================

The engineering teams at Mozilla have put together a series of 5 minute long
tips and tricks to help boost productivity. You can find the recordings below.

August 2021
-----------

`Link to the August 2021 recording <https://mozilla.hosted.panopto.com/Panopto/Pages/Viewer.aspx?id=bd0c503d-903f-4829-9c9d-ad7c011cee9b>`_

Links

- mak: Gmail filtering with Google Apps Script

  - https://script.google.com/home
  - https://developers.google.com/apps-script/reference/

- mhowell: Windows Tools You Might Not Know About

  - https://docs.google.com/document/d/1DyeTPIEz3SIcw7ldvSGKUVp4XP34Ue-_pV8lYmRJX6I/

- bryce: Debugging Remote Resources Via Proxy

  - https://www.telerik.com/fiddler
  - https://www.charlesproxy.com/
  - https://mitmproxy.org/

- jody: CircleCI for VS Code

  - https://marketplace.visualstudio.com/items?itemName=jodyh.circleci-vscode

- sfink: Moz workflow aids for post-landing pruning, taskcluster job replication & more

  - https://github.com/hotsphink/sfink-tools
  - https://hg.sr.ht/~sfink/sfink-tools

- mconley: Multiple mozconfigs with mozconfigwrapper

  - https://github.com/ahal/mozconfigwrapper

February 2021
-------------

`Link to the February 2021 recording <https://mozilla.zoom.us/rec/share/RvN62-Y3ByGmeyQChmsqXy6WXAE3iJETeB2yNj1xq4-z3c80ewwFaz-EAVnoHSo-.8FbmZF3nQEWBPFSr>`_

Slide decks:

- `bash scripts and keyboard shortcuts <https://docs.google.com/presentation/d/1T8z99Hy0rI-_W3wJIZsG-edKRiicxgl-QeBoJuM90qQ/edit?usp=sharing>`_
- `sccache-dist <https://docs.google.com/presentation/d/1_mN5rgV2LrzRKEOn06j4uaryYC9zRQJOdomgeBrJ8RA/edit#slide=id.g832b271044_1_1173>`_
- `How to animate things smoothly <https://docs.google.com/presentation/d/11csNTR1GnVs2BdjN1alJcTbjXMhKyhpv9GIx2jNMJ6U/edit#slide=id.p>`_
- `How I learned to love the M-C <https://docs.google.com/presentation/d/13O06nyDWqfbZyLeGRdLztd234zJ2SQcJu7LkBFDLnYg/edit?usp=sharing>`_

Links for "Editor, Lint, & More" talk:

- :ref:`Linting`
- :ref:`lint-vcs-hook`
- https://eslint.org/docs/user-guide/integrations

Links for "Stupid Mac Tricks" talk:

- https://www.obdev.at/products/launchbar/index.html
- Moom: https://itunes.apple.com/app/id496437906?mt=12&ls=1
- https://kapeli.com/dash
- https://git-fork.com/
- https://www.usboverdrive.com/
- https://manytricks.com/download/butler/
- https://bjango.com/mac/istatmenus/
- https://iterm2.com/

Other links:

- https://twitter.com/asutherland/status/1274942012316319744
- https://scootersoftware.com/
- https://pasteapp.io/
- https://github.com/acreskeyMoz/browsertime_scripts
- https://chuttenblog.wordpress.com/2021/01/18/doubling-the-speed-of-windows-firefox-builds-using-sccache-dist/

---

### Contributing Filing Good Bugs (`docs/contributing/filing-good-bugs.rst`)

Filing good bugs
================

Getting started working on a bug can be hard, specially if you lack
context.

This guide is meant to provide a list of steps to provide the necessary
information to open an actionable bug.

-  **Use a descriptive title**. Avoid jargon and abbreviations where
   possible, they make it hard for other people to find existing bugs,
   and to understand them.
-  **Explain the problem in depth** and provide the steps to reproduce. Be
   as specific as possible, and include things such as operating system
   and version if reporting a bug.
-  If you can, **list files and lines of code** that may need to be
   modified. Ideally provide a patch for getting started.
   Do not hesitate to add permalinks to `Searchfox <https://searchfox.org/firefox-main/source/>`_
   pointing to the file and lines.
-  If applicable, **provide a test case** or document that can be used to
   test the bug is solved. For example, if the bug title was “HTML
   inspector fails when inspecting a page with one million of nodes”,
   you would provide an HTML document with one million of nodes, and we
   could use it to test the implementation, and make sure you’re looking
   at the same thing we’re looking at. You could use services like
   jsfiddle, codepen or jsbin to share your test cases. Other people use
   GitHub, or their own web server.

Good first bugs
---------------

If you're looking to open a bug as a "good first bug" for new contributors, please adhere to the following guidelines:

1. **Complexity**
   Ensure the bug is not overly complex. New contributors are already navigating the learning curve of Firefox's codebase and workflows. An overly complicated bug can be overwhelming.

2. **Tagging**
   Use the Bugzilla keyword ``good-first-bug`` to mark it appropriately.

3. **Language Specification**
   In the whiteboard section, specify the primary language of the bug using the ``[lang=XX]`` format. For instance, ``[lang=C++]`` for C++ or ``[lang=py]`` for Python.

4. **Mentorship**
   Commit to guiding the new contributor by adding yourself as a mentor for the bug. Please keep the mentor field up to date, if you no longer have time set it to empty or find another available mentor.


5. **Documentation**
   Provide links to essential documentation that can assist the contributor. For example, you might include:

   - :ref:`How To Contribute Code To Firefox`
   - :ref:`Firefox Contributors' Quick Reference`
   - :ref:`Working with stack of patches Quick Reference`

By following these guidelines, you'll be setting up new contributors for success and fostering a welcoming environment for them.

These good first bugs can be browsed on https://codetribute.mozilla.org/

---

### Contributing Git Tricks (`docs/contributing/git-tricks.md`)

# Git Tricks

This is a list of Git tricks to help you be more productive. Pick the ones you
like and ignore the rest — it's not an official guide.

## Worktrees

[Git worktrees](https://git-scm.com/docs/git-worktree) allow you to have
multiple parallel checkouts of a single `.git` repo. This can be useful if you
are working on more than one thing at a time, or if you need to temporarily
checkout another branch (e.g. for an uplift) but you don't want to rebuild the
world.

## Use a personal fork repository to track your work

:::{note}
Having a personal fork is **not required** to contribute to Firefox. But it can
be useful if you want to share in-progress patches with others or across
machines. There are also other alternatives to this, like sending patches
generated via `git format-patch`.
:::

:::{warning}
Be mindful of not pushing security-sensitive commits to your personal fork.
See [](<Fixing Security Bugs>).
:::

1. Ensure you have a Git checkout already set up.
1. Go to the [Firefox repository](https://github.com/mozilla-firefox/firefox).
1. Log into GitHub and [create a fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo?tool=webui#forking-a-repository) under your username.
1. Go to your checkout directory and run:

```
$ git remote add fork git@github.com:<yourusername>/firefox.git
$ git remote set-url --push origin git@github.com:<yourusername>/firefox.git
```

Remember to `git fetch fork` if you need to fetch from a different machine for
example.

## `git-revise`: Efficiently update, split, and rearrange git commits

[`git-revise`](https://git-revise.readthedocs.io/en/latest/man.html) is an
in-memory rebase tool which allows you to reword, reorder and split patches in
memory, without touching the disk checkout. That means that you can reorder and
split patches really fast, without having to rebuild afterwards.

## `git wip`

If you have a set up like the above, you can use something like this to show
the branches in which you have unmerged work:

```
$ git config alias.wip "log --branches --remotes=fork --not --remotes=origin --simplify-by-decoration --decorate --oneline --graph"
```

That would generate some output like:

```
$ git wip
* 0577f64ec6e2 (HEAD -> git-docs) WIP: Add some more advanced git docs.
* 5c15717818ff (view-transition-scrolling) fixup! Bug 1961140 - Null out ASR for view transition captured contents. r=nical,mstange,botond
* fa8d2785fa3c (fork/kill-html-button-frame, remove-focus-outer) Fix combobox end padding.
* b9af5ad6a613 (fork/canvas-bg-clean-up, canvas-bg-clean-up) Bug 1956128 - Clean up AddCanvasBackgroundColorItem callers. r=mstange
... etc
```

## `git-absorb`: Automatically fixup! commits

[`git-absorb`](https://github.com/tummychow/git-absorb) automatically creates
fixup commits for your staged changes. It analyzes your changes and determines
which commits they should be integrated into.

Install with:

```
$ cargo install git-absorb
```

Usage:

```
$ git add -p
$ git absorb --and-rebase
```

## Git Maintenance

[Git maintenance](https://git-scm.com/docs/git-maintenance) can set up a job to
fetch, potentially clean-up, and much more, from time to time.

To use the default configuration just:

```
$ git maintenance start
```

For more advanced configuration please see the doc linked above.

(git-mercurial-transplant)=

## Transplanting Patches To and From Mercurial Repositories

A simple mercurial changeset series can be transplanted to a git repository for the current directory using:

```bash
for id in `hg --repository $mercurial_repository_root log --template '{node|short} ' --rev $ancestor_first_revset`; do
  hg --repository $mercurial_repository_root export $id | git am --patch-format=hg || break
done
```

`git am` fails with the following output if `--patch-format=hg` is missing:
>
> ```text
> Applying: # HG changeset patch
> fatal: empty ident name (for <>) not allowed
> ```

A simple git commit series can be transplanted to a mercurial repository for the current directory using:

```bash
git -C $git_work_tree_dir format-patch --stdout --find-copies $since_or_revision_range | hg import -
```

[git-cinnabar](https://github.com/glandium/git-cinnabar) can
[fetch](https://github.com/glandium/git-cinnabar?tab=readme-ov-file#fetching-a-specific-mercurial-changeset)
changesets with their ancestors from mercurial repositories, such as
<https://hg.mozilla.org/try/> or local repositories, with histories matching the
git repository. Fetching from <https://hg.mozilla.org/mozilla-central/> or
<https://hg.mozilla.org/mozilla-unified/> first can make fetches from other
mercurial repositories much faster. After fetching from a mercurial
repository, git commits and their ancestors not fetched from that mercurial
repository can be pushed to that mercurial repository or to a clone of that
mercurial repository.

---

### Contributing Helpful Error Messages (`docs/contributing/helpful-error-messages.rst`)

Helpful error messages for web developers
===========================================

When errors are surfaced to the web platform, developers see them in the console on their local machine, or they may be using an error tracking system to record errors happening on their users' machines.

This means developers may be exposed to our error messages even if they aren't developing in Firefox.

Vague error messages are frustrating experiences and negatively impacts Firefox, especially if, in their logs, developers are seeing more helpful messages from other browsers.

Instead:

- Explain why this specific error happened.
- Use terms familiar to web developers.
- If there's a likely solution, suggest it.
- Link to MDN, so the developer has an immediate way to learn about the requirements of the API.

Example
-------

Given error-throwing code like:

.. code-block:: js

   const urlPattern = new URLPattern('/blog/:year/:title');

.. admonition:: Bad example
   :class: warning

   Uncaught TypeError: URLPattern constructor: Failed to create URLPattern (from string)

.. admonition:: Better example
   :class: tip

   Throw something like: Uncaught TypeError: URLPattern constructor: Relative pattern '/blog/:year/:title' must have a base URL passed as the second argument, or use an object as the first argument to match specific parts of URLs. See https://developer.mozilla.org/docs/Web/API/URLPattern/URLPattern

---

### Contributing How To Submit A Patch (`docs/contributing/how_to_submit_a_patch.rst`)

How to submit a patch
=====================

Submitting a patch, getting it reviewed, and committed to the Firefox
source tree involves several steps. This article explains how.

.. note::

   We are also providing a :ref:`Firefox Contributors Quick Reference <Firefox Contributors' Quick Reference>` for contributors.

The process of submission is illustrated by the following diagram, and
each step is detailed below:

.. mermaid::

     graph TD;
         Preparation --> Bugzilla[(Bugzilla)];
         Bugzilla[(Bugzilla)] --> Git[(Git)];
         Git[(Git)] --> c[Working on a patch];
         c[Working on a patch] --> Testing;
         Testing --> c[Working on a patch];
         Testing --> e[Submit the patch];
         e[Submit the patch] --> Phabricator[(Phabricator)];
         Phabricator[(Phabricator)] --> d[Getting Reviews];
         d[Getting Reviews] -- Addressing Review comment --> c[Working on a patch];
         d[Getting Reviews] --> Lando[(Lando)];
         Lando[(Lando)] --> h[Push the change];
         h[Push the change] --> Git2[(Git)];
         style Bugzilla fill:#e1f5ff,stroke:#0366d6
         style Git fill:#e1f5ff,stroke:#0366d6
         style Phabricator fill:#e1f5ff,stroke:#0366d6
         style Lando fill:#e1f5ff,stroke:#0366d6
         style Git2 fill:#e1f5ff,stroke:#0366d6




Preparation
-----------

Every change to the code is tracked by a bug report
in `bugzilla.mozilla.org <https://bugzilla.mozilla.org/>`__. Without a
bug, code will not be reviewed, and without review, code will not be
accepted. To avoid duplication, `search for an existing
bug <https://bugzilla.mozilla.org/query.cgi?format=specific>`__ about
your change, and only if none exists, file a new one. Most communication
about code changes take place in the associated code
review, so be sure the bug describes the exact problem being solved.

Please verify the bug is for the correct product and component. For more
information, ask questions on the newsgroups, or on the #developers room
on `chat.mozilla.org <https://chat.mozilla.org>`__.

The person working on a bug should be the 'assignee' of that bug in
Bugzilla. If somebody else is currently the assignee of a bug, email
this person to coordinate changes. If the bug is unassigned, leave a
message in the bug's comments, stating that you intend working on it,
and suggest that someone with bug-editing privileges assign it to you.

Some teams wait for new contributors to attach their first patch before
assigning a bug. This makes it available for other contributors, in case
the new contributor is unable to level up to patch creation. By
expressing interest in a bug comment, someone from that team should
guide you through their process.


Module ownership
----------------

All code is supervised by a `module
owner <https://www.mozilla.org/en-US/about/governance/policies/module-ownership/>`__.
This person will be responsible for reviewing and accepting the change.
Before writing your code, determine the module owner, verifying your
proposed change is considered acceptable. They may want to look over any
new user interface (UI review), functions (API review), or testcases for
the proposed change.

If module ownership is not clear, ask on the newsgroups or `on
Matrix <https://chat.mozilla.org>`__. The revision log for the relevant
file might also be helpful. For example, see the change log for
``browser/base/content/browser.js``, by clicking the "Git Log"
link at the top of `Searchfox <https://searchfox.org/firefox-main/source/>`__, or
by running ``git log browser/base/content/browser.js``. The corresponding
checkin message will contain something like "r=nickname", identifying
active code submissions, and potential code reviewers.


Working on a patch
------------------

Changes to the Firefox source code are presented in the form of a patch.
A patch is a commit to version control. Firefox and related code is
stored in our `git repository <https://github.com/mozilla-firefox/firefox>`__.

Each patch should represent a single complete change, separating
distinct changes into multiple individual patches. If your change
results in a large, complex patch, seek if it can be broken into
`smaller, easy to understand patches representing complete
steps <https://we.phorge.it/book/flavor/article/writing_reviewable_code/#many-small-commits>`__,
applied on top of each other. This makes it easier to review your
changes, `leading to quicker
reviews, <https://groups.google.com/group/mozilla.dev.planning/msg/2f99460f57f776ef?hl=en>`__
and improved confidence in this review outcome.

Also ensure that your commit message is formatted appropriately. A
simple commit message should look like this:

::

   Bug 123456 - Change this thing to work better by doing something. r=reviewers

The text of the message should be what you did to fix the bug, not a
description of what the bug was. If it is not obvious why this change is
appropriate, then `explain why in the commit
message <https://we.phorge.it/book/flavor/article/writing_reviewable_code/#write-sensible-commit-messages>`__.
If this does not fit on one line, then leave a blank line and add
further lines for more detail and/or reasoning.

The ``r=reviewers`` part specifies that ``reviewers`` should review the patch
and provide feedback before it is integrated into the Firefox codebase. For
choosing reviewers, and the full reviewer syntax, please see
:ref:`Getting reviews`.

You can edit the message of the current commit at any time using
``git commit --amend`` or ``git rebase -i``.

Also look at our :ref:`Reviewer Checklist` for a list
of best practices for patch content that reviewers will check for or
require.


Testing
-------

All changes must be tested. In most cases, :ref:`Automated Testing` is required for every
change to the code.

While we desire to have automated tests for all code, we also have a
linter tool which runs static analysis on our JavaScript, for best
practices and common mistakes. See :ref:`ESLint` for more information.

Ensure that your change has not caused regressions, by running the
automated test suite locally, or using the `Mozilla try
server <https://wiki.mozilla.org/Build:TryServer>`__. Module owners, or
developers `on Matrix <https://chat.mozilla.org>`__ may be willing to
submit jobs for those currently without try server privileges.


Submit the patch
----------------

.. note::

   Make sure you rebase your patch on top of the latest build before you
   submit to prevent any merge conflicts.

Mozilla uses Phabricator for code review. See the `Mozilla Phabricator
User
Guide <https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html>`__
for instructions.

Don't be shy in posting partial patches, demonstrating potential
approaches, and asking for preliminary feedback. It is easier for others
to comment, and offer suggestions, when a question is accompanied by
some code.


Getting reviews for my patch
----------------------------

See the dedicated page :ref:`Getting reviews`


Addressing review comments
--------------------------

It is unusual for patches to be perfect the first time around. The
reviewer may use the ‘Request Changes’
`action <http://moz-conduit.readthedocs.io/en/latest/phabricator-user.html#reviewing-patches>`__
and list problems that must be addressed before the patch can be
accepted. Please remember that requesting revisions is not meant to
discourage participation, but rather to encourage the best possible
resolution of a bug. Carefully work through the changes that the
reviewer recommends, attach a new patch, and request review again.

Sometimes a reviewer will grant conditional review with the ‘Accept
Revision’ action but will also indicate minor necessary changes, such as
spelling, or indentation fixes. All recommended corrections should be
made, but a re-review is unnecessary. Make the changes and submit a new
patch. If there is any confusion about the revisions, another review
should be requested.

Sometimes, after a patch is reviewed, but before it can be committed,
someone else makes a conflicting change. If the merge is simple, and
non-invasive, post an updated version of the patch. For all non-trivial
changes, another review is necessary.

If at any point the review process stalls for more than two weeks, see
the previous 'Getting attention' section.

In many open source projects, developers will accept patches in an
unfinished state, finish them, and apply the completed code. In
Mozilla's culture, **the reviewer will only review and comment on a
patch**. If a submitter declines to make the revisions, the patch will
sit idle, until someone chooses to take it on.


Pushing the change
------------------

A patch can be pushed (aka. 'landed') after it has been properly
reviewed.

.. note::

   Be sure to build the application with the patch applied. This
   ensures it runs as expected, passing automated tests, and/or runs
   through the `try
   server <https://wiki.mozilla.org/Build:TryServerAsBranch>`__. In the
   bug, please also mention you have completed this step.

   Submitting untested patches wastes the committer's time, and may burn
   the release tree. Please save everyone's time and effort by
   completing all necessary verifications.


Ask the reviewer to land the patch for you.
For more details, see :ref:`push_a_change`

`Lando <https://moz-conduit.readthedocs.io/en/latest/lando-user.html>`__ is used
to automatically land your code.


Regressions
-----------

It is possible your code causes functional or performance regressions.
There is a tight
`policy <https://www.mozilla.org/about/governance/policies/regressions/>`__ on
performance regressions, in particular. This means your code may be
dropped, leaving you to fix and resubmit it. Regressions, ultimately
mean the tests you ran before checking in are not comprehensive enough.
A resubmitted patch, or a patch to fix the regression, should be
accompanied by appropriate tests.

After authoring a few patches, consider `getting commit access to
Mozilla source code <https://www.mozilla.org/about/governance/policies/commit/>`__.

---

### Contributing Index (`docs/contributing/index.rst`)

Working on Firefox
==================

Welcome to the Firefox codebase. This is the home of the Firefox
development process and source code documentation.

.. toctree::
   :caption: Making Changes To Firefox
   :maxdepth: 1

   contribution_quickref
   stack_quickref
   pocket-guide-shipping-firefox
   editor
   reviews
   levelling-up
   how_to_submit_a_patch
   data-collection
   data-review
   jujutsu
   searchfox
   ai-coding


.. toctree::
   :caption: Code reviews
   :maxdepth: 1

   Code_Review_FAQ
   reviewer_checklist


.. toctree::
   :caption: Debugging
   :maxdepth: 1
   :glob:

   debugging/*


.. toctree::
   :caption: Signing
   :maxdepth: 1
   :glob:

   signing/*


.. toctree::
   :caption: Additional Information
   :maxdepth: 1

   directory_structure
   build/artifact_builds
   build/building_mobile_firefox
   build/supported
   build/working_with_esr_115
   engineering_show_and_tell
   filing-good-bugs

---

### Contributing Jujutsu (`docs/contributing/jujutsu.rst`)

Introduction to Jujutsu
#######################

Jujutsu (``jj`` on the command-line) is a modern DVCS, that uses ``git``
repositorie as its storage backend. It borrows extensively from Mercurial,
but has many more features.

.. note::

   Jujutsu is an optional alternative to plain Git for managing your
   patch stack. If you prefer Git, see :ref:`Working with stack of
   patches Quick Reference`.

.. contents:: Table of Contents

Links and Resources
-------------------

- Hope page https://jj-vcs.github.io/jj/latest/
- In-progress tutorial: https://steveklabnik.github.io/jujutsu-tutorial/
- Good introduction and context: https://v5.chriskrycho.com/essays/jj-init/
- Short introduction:
  https://neugierig.org/software/blog/2024/12/jujutsu.html
- Introduction for Mercurial users:
  https://ahal.ca/blog/2024/jujutsu-mercurial-haven/
- ``:ahal``'s configuration: https://github.com/ahal/dot-files/blob/main/dot-files/jj-config.toml

Quick Start
-----------

To get up and running with a fresh checkout, run the following commands
(line-separated) after installing ``git`` and ``jj`` (jujutsu):

::

   # Create a clone and enter the directory. Use one of the following

   # (1) Fresh clone:
   jj git clone https://github.com/mozilla-firefox/firefox
   cd firefox
   ./mach vcs-setup

   # (2) Or if you have a Git clone already:
   ./mach vcs-setup --vcs=jj

   # Set up jujutsu default configuration (which will affect e.g. the default `jj log` output)
   ./mach vcs-setup

   # Track remote bookmarks (you can do this for the other bookmarks, too)
   jj bookmark track main@origin autoland@origin beta@origin release@origin

   # To see the other untracked bookmarks on that remote:
   jj bookmark list --remote origin -T 'if(!tracked && remote, name ++ "@" ++ remote ++ "\n")'

   # Move the working copy commit to bookmarks/central
   jj new main

General Tips
------------

Changes and Commits
~~~~~~~~~~~~~~~~~~~

``changes`` and ``commits`` are distinct concepts. While in git there’s
a one-to-one record of ``changes`` *as* ``commits`` (plus, perhaps,
staging), in jujutsu ``commits`` occur fairly frequently (basically any
time there’s a change and you run ``jj``, which results in a snapshot).
In this sense, ``commits`` can be considered literal snapshot/state
commits, whereas ``changes`` are the user-friendly unit-of-work that
developers are doing. ``changes`` have hashes that are alphabetic using the letters k..z,
whereas ``commits`` have hashes which are the same as their git
counterparts (sha1, represented as hex characters).

Thus, a particular ``change`` points to one ``commit`` at a time,
however there is a history of ``commits`` recorded for each ``change``
(see ``jj evolog``, for example). You can specify either ``change``
hashes *or* ``commit`` hashes in revsets.

Co-located Jujutsu and Git
~~~~~~~~~~~~~~~~~~~~~~~~~~

A `co-located repository
<https://jj-vcs.github.io/jj/latest/git-compatibility/#co-located-jujutsugit-repos>`__
allows running ``jj`` and ``git`` commands in the same repository rather than
syncing changes between ``jj`` and ``git`` repositories to switch between the
different tools. Recent versions of ``jj`` default to being co-located.

Git commands can be useful because some features are not yet implemented in
Jujutsu, such as ``git log`` and ``git rebase`` for `interactions with file
renames <https://github.com/jj-vcs/jj/issues/6940>`__ and ``git am`` for
`importing patches <https://github.com/jj-vcs/jj/issues/2702>`__.  See also
:ref:`Transplanting Patches To and From Mercurial Repositories
<git-mercurial-transplant>`.

Firefox Main Tips
-----------------

Other Useful revset aliases (place in ``.jj/repo/config.toml``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

::

   [revset-aliases]
   # Get all changes with "Bug 12345" in the subject (can be improved with https://github.com/jj-vcs/jj/issues/5895)
   'bug_all(x)' = 'mutable() & subject(glob:"Bug *") & subject(x)'
   # Get head change(s) with "Bug 12345" in the subject
   'bug(x)' = 'heads(bug_all(x))'
   # Get root change(s) with "Bug 12345" in the subject
   'bug_root(x)' = 'roots(bug_all(x))'

``moz-phab``
~~~~~~~~~~~~

As of ``moz-phab`` 2.0.0, Jujutsu is officially supported! This applies to both
colocated Git/Jujutsu repositories, as well as standalone Jujutsu repositories
and workspaces.

If you are using a colocated repository, you can make ``moz-phab`` use Git
instead of Jujutsu by calling it with ``--avoid-jj-vcs``. Note that if you are
using ``moz-phab`` with Git like that, most operations require your repo to not
be in a detached ``HEAD`` state, which Jujutsu frequently leaves it in. One
simple solution is to wrap the ``moz-phab`` command with a script like:

::

   #!/bin/sh
   git checkout -B moz-phab && moz-phab --avoid-jj-vcs "$@"

You could instead make this a shell alias/function, if preferred.

``mach lint``
~~~~~~~~~~~~~

| ``./mach lint`` can be integrated with ``jj fix``. Follow the
  instructions here:
| https://firefox-source-docs.mozilla.org/code-quality/lint/usage.html#jujutsu-integration

(adding the config to ``jj config edit --repo``)

The benefit of running ``jj fix`` over ``./mach lint --fix`` directly,
is that it will step through all your mutable commits and checkout each
file at that revision before running the fixers on it. So you’re
guaranteed to get the fix directly in the commit that introduced the
issue.

Rebasing work in progress (and automatically drop changes that have landed)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You want something like:

::

   jj git fetch && jj rebase --skip-emptied -r 'mutable() & mine()' --onto main

This will:

1. Pull from the main repo
2. Rebase any mutable changesets you’ve made onto the (updated, tracked
   bookmark) ``main`` changeset, and drop any that become empty (because
   they have landed)

Of course you could narrow the scope of what you want to rebase by
altering the ``-r`` argument and providing specific revisions, or rebase
onto autoland or beta or other bookmarks if you want.

Dropping/pruning/removing obsolete commits
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

(Note: you may want to look at the `previous
tip <#rebasing-work-in-progress-(and-automatically-drop-changes-that-have-landed)>`__!)

You can use any of:

::

   jj abandon x     # just revision ``x``
   jj abandon x y   # revisions ``x`` and ``y``
   jj abandon x..z  # revisions leading to z that have not been merged into x
   jj abandon x::y  # revisions in the commit graph between x and y

``x::y`` is similar to ``x..y``. The main difference is that the former includes
``x`` and the latter does not, but they are for different purposes. ``x..y`` has
the same meaning as in git, where ``x`` and ``y`` are used to denote entire
branches of work ending in ``x``/``y``. So ``main..y`` for example includes
everything past the branch point from the ``main`` branch up to ``y``. The exact
definition is "all ancestors of (aka all commits leading up to) ``y``) that are
not also ancestors of `main`", or in brief: ``::y ~ ::x``. This is especially
useful when ``main`` has advanced past the common ancestor with ``y``.

When you’re dealing with temporary changes that you have not committed
(“working directory changes”) this is also an easy way to revert those
(a la ``hg revert --no-backup –all``).

Watchman integration
~~~~~~~~~~~~~~~~~~~~

Tired of the frequent Snapshotting… message? Edit your global ``jj``
configuration by doing:

::

   jj config edit --user

and add the following:

::

   [fsmonitor]
   backend = "watchman"

Instead of scanning the file system, ``jj`` will (much like ``hg``\ ’s
``fsmonitor`` extension) use file system events to be notified about
file changes, resulting in much shorter operation time, without having
to disable the snapshotting mechanism.

Working with multiple workspaces
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

By default, ``./mach vcs-setup`` configures ``snapshot.auto-update-stale = true``, which
causes ``jj`` to automatically update a workspace’s working copy when it becomes
stale. A workspace becomes stale when a commit it depends on is rewritten from
another workspace, for example by rebasing, editing, or squashing. We recommend this
default because some ``mach`` commands invoke ``jj`` and can fail, sometimes
silently, if the working copy is stale.

If you use multiple workspaces and want to control when each workspace picks up
changes, for example to avoid triggering a slow rebuild after rebasing patches
in bulk from another workspace, you can disable this per-workspace:

::

   jj config set --workspace snapshot.auto-update-stale false

With auto-update disabled, most ``jj`` commands will refuse to run on a stale
workspace until you manually update with ``jj workspace update-stale``. (Note
that this is only relevant when you modify one workspace's ancestor from another
workspace, which is what causes the former workspace to become stale. If you
choose to be selecting with your rebases, edits, and squashes, such that you
only touch the current workspace's ancestors, then you won't encounter stale
workspaces very often.)

---

### Contributing Levelling Up (`docs/contributing/levelling-up.rst`)

Levelling up
============

Once you’ve fixed a few bugs, it’s quite likely that we’ll ask you to
complete one or more of the following steps. They will grant you access
to useful Mozilla infrastructure for testing or landing code
automatically, so you can be more autonomous and able to contribute with
less supervision.

If you’re curious, the `Mozilla Commit Access
Policy <https://www.mozilla.org/en-US/about/governance/policies/commit/access-policy/>`__
page explains what does each level mean.

Request commit access level 1
-----------------------------

Once this is granted, you can use the
`Try server <https://wiki.mozilla.org/ReleaseEngineering/TryServer>`__ for
running automated tests of your code.

To request this, follow the instructions on the `Becoming A Mozilla Committer <https://www.mozilla.org/en-US/about/governance/policies/commit/>`__ page
to file a bug with the title “Commit Access (Level 1) for ${your name}”,
and continue with steps such as adding the public SSH key, etc (it’s not
enough with just filing the bug!).

The person that asked you to request this can also vouch for you.

Request commit access level 3
-----------------------------

After you landed a few bugs, that are more advanced than the
``good-first-bugs`` and you feel confident about your contributions as
well as the process, you can request level 3 access. Once this is
granted, you will get access to Lando, the autoland feature.

To request this, follow the instructions on the `Becoming A Mozilla Committer <https://www.mozilla.org/en-US/about/governance/policies/commit/>`__ page
to file a bug with the title “Commit Access (Level 3) for ${your name}”.

The person that asked you to request this can also vouch for you, and at
this point you might already know a few other people who will vouch for
you. You need two vouchers.

If you reach this level, well done! That’s amazing, and we’re glad to
have you on board 😄

---

### Contributing Pocket Guide Shipping Firefox (`docs/contributing/pocket-guide-shipping-firefox.rst`)

Pocket Guide: Shipping Firefox
==============================

*Estimated read time:* 15min


Introduction
------------

The purpose of this document is to provide a high level understanding of
how Mozilla ships Firefox. With the intention of helping new Mozillians
(and those who would like a refresher) understand the basics of our
release process, tools, common terms, and mechanisms employed in
shipping Firefox to our users. Often this document will introduce a
concept, explain how it fits into the process, and then provide a link
to learn more if interested.

Repositories & Channels
-----------------------

Shipping Firefox follows a software release :ref:`train model <train model>`
along 3 primary code branches; firefox-main (aka “f-m” or “m-c”),
firefox-beta, and firefox-release. Each of these branches are updated within
a defined cadence and built into one of our Firefox products which are released
through what is commonly referred to as :ref:`Channels <channels>`:
Firefox Nightly, Firefox Beta, and Firefox Release.

`Firefox Nightly <https://whattrainisitnow.com/release/?version=nightly>`__ offers access
to the latest feature work still under active development. Released every 12 hours with all
the changes that have :ref:`landed <landing>` on firefox-main for Desktop and Android.

Every `4 weeks <https://whattrainisitnow.com/calendar/>`__, we :ref:`merge <merge>` the code
for Desktop and Android builds from firefox-main to the firefox-beta branch. New code or
features can be added to firefox-beta outside of this 4 week cadence but are required to land
on firefox-main before being :ref:`uplifted <uplift>` to firefox-beta.

`Firefox Beta <https://whattrainisitnow.com/release/?version=beta>`__ is for developers and early
adopters who want to see and test what’s coming next in Firefox. We ship new Desktop and Android
Beta builds three times a week.

.. note::

  The first and second beta builds of a new cycle are shipped to a
  subset of our Beta population. The full Beta population gets updated
  starting with Beta 3 only.

.. note::

  **Firefox Developer Edition** is a separate Desktop-only product based on
  the firefox-beta branch and is specifically tailored for Web Developers.

`Firefox Release <https://whattrainisitnow.com/release/?version=release>`__ is updated every 4 weeks
when a given version reaches the end of its Beta cycle. This is the primary product we ship to end users.
While a release is live, interim updates (dot releases) are used to ship important bug fixes prior to
the next major release. These can happen on an as-needed basis when there is an important-enough
:ref:`driver <dot release drivers>` to do so (such as a critical bug severely impairing the usability
of the product for some users). In order to provide better predictability, there are also three planned
dot releases scheduled for the three weeks following the initial go-live for less-critical fixes and other
:ref:`ride-along fixes <ride alongs>` deemed low-risk enough to include.

.. note::
  `Firefox ESR (Extended Support Release) <https://whattrainisitnow.com/release/?version=esr>`__ is
  a separate product intended for enterprise use. Major updates are rolled out once per year to maintain
  stability and predictability. ESR also contains a number of enterprise policy options not available on
  the standard Firefox Release channel. Minor updates are shipped in sync with the Firefox Release
  schedule and generally only contain security and select quality fixes.

Further Reading/Useful links:

-  `Firefox Trains <https://whattrainisitnow.com/>`__
-  `Release Calendar <https://whattrainisitnow.com/calendar/>`__
-  `Firefox Release Process <https://wiki.mozilla.org/Release_Management/Release_Process>`__
-  `Firefox Delivery dashboard <https://mozilla.github.io/delivery-dashboard/>`__

Landing Code and Shipping Features
----------------------------------

Mozillians (those employed by MoCo and the broader community) land lots of code in
the Mozilla repositories: fixes, enhancements, compatibility, new features, etc. which are
managed by git. All code development is tracked in
:ref:`Bugzilla <bugzilla>`, reviewed in :ref:`Phabricator <Phabricator>`, and then checked
into the Firefox repository using :ref:`Lando <Lando>`.

.. note::

  Some teams use separate :ref:`GitHub <github>` repositories during development but are
  still required to use Phabricator (tracked in Bugzilla) to check their code into the
  main Firefox git repository.

The standard process for code to be delivered to our users is by ‘riding the trains’, meaning that
it’s landed in firefox-main to ship in Nightly builds while it waits for the next Beta cycle to
begin. After merging to Beta, the code stabilizes over a 4 week period (along with everything else
that merged from firefox-main from that development cycle). At the end of the Beta cycle, a
release candidate (:ref:`RC <rc>`) build is generated, tested thoroughly, and eventually is released
as the next major version of Firefox.

Further Reading/Useful links:

-  `Phabricator and why we use it <https://wiki.mozilla.org/Phabricator>`__
-  `Firefox Release Notes Process <https://wiki.mozilla.org/Release_Management/Release_Notes>`__
-  `Firefox Release Notes Nomination <https://wiki.mozilla.org/Release_Management/Release_Notes_Nomination>`__

An exception to this process...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Not all code can simply wait for the normal train model to be included in a Firefox build.
There are a variety of reasons for this; critical fixes, security concerns, stabilizing a feature
that’s already in Beta, shipping high-priority features/enhancements faster, and so on.

In these situations, an uplift can be requested to take a recent landing in firefox-main and
merge specific bits to the Beta or Release repository outside the standard train model. After the
request is made, :ref:`Release Management <release management>` will assess the potential risk and
make a decision on whether it will be accepted or not.

While uplifts are generally not the preferred way to ship new feature work, it is understood that there
are times when business needs to do so justify the required effort. Our release process is designed to
have the flexibility to accommodate these requests, though in general they need to be handled on a case
by case basis to determine the suitability. Teams are encouraged to reach out to Release Management in
the `#release-coordination` channel on Slack or `@relman` so their specific needs can be assessed.

Factors that will need to be taken into account include:

-  Size and scope of patches to be uplifted
-  QA availability to test prior to shipping and during development
-  Engineering resources to resolve any conflicts between different development branches
-  String additions/changes which may impact available locales

Further Reading/Useful links:

-  `Patch uplifting rules <https://wiki.mozilla.org/Release_Management/Uplift_rules>`__
-  `Requesting an uplift <https://wiki.mozilla.org/Release_Management/Requesting_an_Uplift>`__

Ensuring build stability
~~~~~~~~~~~~~~~~~~~~~~~~

Throughout the process of landing code in firefox-main to riding the trains to Firefox Release,
there are many milestones and quality checkpoints from a variety of teams. This process is designed
to ensure a quality and compelling product will be consistently delivered to our users with each new
version. See below for a detailed list of those milestones.

===================================================== ================ ================= =======================================================================================
Milestone                                             Week             Day of Week
----------------------------------------------------- ---------------- ----------------- ---------------------------------------------------------------------------------------
QA Request & Feature technical documentation deadline Nightly W0       Friday            QA feature testing should be requested prior to the start of the Nightly cycle
Merge Day                                             Nightly W1       Monday            Day 1 of the new Nightly Cycle
Feature Complete Milestone                            Nightly W2       Friday            Last day to land risky patches and/or enable new features
QA Test Plan approval due                             Nightly W2       Friday            Last day to provide QA with feature Test Plan sign-offs
Nightly features Go/No-Go decisions                   Nightly W4       Wednesday
Beta release notes draft                              Nightly W4       Wednesday
QA pre-merge regression testing completed             Nightly W4       Friday
String freeze                                         Nightly W4       Friday            Modification or deletion of strings exposed to the end-users is not allowed
Merge Day                                             Beta W1          Monday            Day 1 of the new Beta cycle
User affecting changes identified & provided to SUMO  Beta W1          Friday
End of Early Beta & intended pref state deadline      Beta W2          Friday            Post-B5
Pre-release sign off                                  Beta W3          Wednesday         Final round of QA testing prior to Release
Go/No-Go for features riding train                    Beta W3          Friday
Deadline for security-approval requests               Beta W3          Friday
Release note submission deadline                      Beta W4          Tuesday
What’s new page & release notes ready                 Beta W4          Wednesday
Firefox Release Candidate build creation              Beta W4          Wednesday         End of the current Beta cycle in preparation for the upcoming Firefox Release
Firefox go-live @ 6am PT                              Release W1       Tuesday           Day 1 of the new Firefox Release to 25% of Release users
Firefox Release bump to 100%                          Release W1       Thursday          Increase deployment of new Firefox Release to 100% of Release users
Scheduled dot release 1 approval requests due         Release W1       Friday            All requests required by EOD
Scheduled dot release 1 go-live                       Release W2       Tuesday           By default, ships when ready. Specific time available upon request.
Scheduled dot release 2 approval requests due         Release W2       Friday            All requests required by EOD
Scheduled dot release 2 go-live                       Release W3       Tuesday           By default, ships when ready. Specific time available upon request.
Scheduled dot release 3 approval requests due         Release W3       Friday            All requests required by EOD
Scheduled dot release 3 go-live                       Release W4       Tuesday           By default, ships when ready. Specific time available upon request.
===================================================== ================ ================= =======================================================================================


The Release Management team (aka “Relman”) monitors and enforces this process to protect the
stability of Firefox. Each member of Relman rotates through end-to-end ownership of a given
:ref:`release cycle <release cycle>`. The Relman owner of a cycle will focus on the overall release,
blocker bugs, risks, backout rates, stability/crash reports, etc. Go here for a complete overview of
the `Relman Release Process Checklist <https://wiki.mozilla.org/Release_Management/Release_Process_Checklist_Documentation>`__.

.. note::

  While Relman continually monitors the overall health of each release, it is the responsibility
  of the engineering organization to ensure that the code they are landing is of high quality and the
  potential risks are understood. Every release has an assigned :ref:`Regression Engineering
  Owner <reo>` (REO) to ensure a decision is made about each regression reported in the release.

Further Reading/Useful links:

-  `Release Tracking Rules <https://wiki.mozilla.org/Release_Management/Tracking_rules>`__
-  `Release Owners <https://wiki.mozilla.org/Release_Management/Release_owners>`__
-  `Commonly used Bugzilla queries for all Channels <https://trainqueries.herokuapp.com/>`__

Enabling/Disabling code (Prefs)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Within Firefox we allow the ability to enable/disable bits of code or entire features using
:ref:`Preferences <preferences>`. There are many reasons why this is useful. For example:

-  Continual development over multiple release cycles without exposing partially-completed
   features to our users
-  Provide the ability to quickly disable a feature if there is a problem found during the
   release process
-  Control features which are experimental or not ready to be shown to a specific channel
   population (e.g. enabled for Beta but disabled for Release)
-  A/B testing via :ref:`telemetry <telemetry>` experiments

.. note::

  :ref:`Nimbus <nimbus>` Pref Rollout is a feature that allows Mozilla to change the state of a
  preference for a targeted set of users, without deploying an update to Firefox. This is
  especially useful when conducting experiments or a gradual rollout of high risk features
  to our Release population.

  A Pref Rollout can also be used to mitigate an incident, see `Incident Response Pref Flips <https://experimenter.info/desktop-incident-response>`__ for details.

Further Reading/Useful links:

-  `Mozilla preferences documentation <https://firefox-source-docs.mozilla.org/modules/libpref/index.html>`__
-  `Nimbus documentation <https://experimenter.info/>`__

Release & Feature QA
~~~~~~~~~~~~~~~~~~~~

The Desktop Test Engineering team is responsible for testing all critical browser areas,
core and new. Organized in two-week sprints its primary goals are:


-  qualifying builds for release,
-  new feature testing based on Jira request,
-  smoke, functional, exploratory and other recurring testing activities conducted each release cycle,
-  bug work (such as bug fix verification and investigation),
-  various process improvement initiatives,
-  and community engagement.


Features that can have significant impact and/or pose risk to the code base should be
nominated for QA support by the :ref:`feature owner <feature owner>` in its intended
release by submitting a new request in Jira. This process is kicked off by filing a new
Jira ticket `here <https://mozilla-hub.atlassian.net/jira/software/c/projects/QA/boards/261>`__
(detailed steps in `How to file a QA
request <https://docs.google.com/document/d/1oz1YyaaBI-oHUDsktWA-dLtX7WzhYqs7C121yOPKo2w/edit?usp=sharing>`__).
These are due by the end of week 4 of the previous Nightly cycle in which the feature needs testing.

Further Reading/Useful links:

-  `DTE team overview <https://mozilla-hub.atlassian.net/wiki/spaces/FDPDT/pages/10617155/Desktop+Test+Engineering>`__
-  `DTE feature testing process <https://docs.google.com/document/d/1AIgAs78HWAPA3ROOdHzVW8fwRqfj8mog0sutaxp3Xfw/edit?usp=sharing>`__
-  `How to file a QA request <https://docs.google.com/document/d/1oz1YyaaBI-oHUDsktWA-dLtX7WzhYqs7C121yOPKo2w/edit?usp=sharing>`__

Experiments
~~~~~~~~~~~

As we deliver new features to our users, we continually ask ourselves about the potential impacts,
both positive and negative. For many new features, we will run an experiment to gather data around
these impacts. A simple definition of an experiment is a way to measure how a change to our product
affects how people use it.

An experiment has three parts:

1. A new feature that can be selectively enabled
2. A group of users to test the new feature
3. Telemetry to measure how people interact with the new feature

Experiments are managed by an in-house tool called `Experimenter <https://experimenter.services.mozilla.com/>`__.

Further Reading/Useful links:

-  `More about experiments and Experimenter <https://github.com/mozilla/experimenter>`__
-  `Requesting a new Experiment <https://experimenter.services.mozilla.com/experiments/new/>`__
   (Follow the ‘help’ links to learn more)
-  `Telemetry <https://wiki.mozilla.org/Telemetry>`__

Train-Hop
~~~~~~~~~~~

Extensions in browser/extensions/ can run inside of Firefox as a “built-in addon”.
Unlike traditional WebExtensions, these add-ons ship with Firefox and run with the same privilege level as the rest of the browser code.

When a built-in add-on is packaged up as an XPI and deployed to Beta or Release clients, it is referred to as a “train-hop”.
A train-hop supplements the default Firefox train release model by allowing teams to ship code changes without requiring a dot release.

By default, the code for built-in add-ons rides the standard Firefox release train.
A train-hop only occurs when the extension is intentionally packaged and shipped off-train.

The extensions that currently support train-hops are New Tab and Web Compatibility.

Further Reading/Useful links:

- `Web Compatibility Release Process <https://wiki.mozilla.org/Compatibility/System_Addon/Release_Process#Shipping_interventions_with_an_out-of-band_System_Addon_Update>`__
- `Train-hopping for New Tab <https://firefox-source-docs.mozilla.org/browser/extensions/newtab/docs/v2-system-addon/train_hopping.html>`__

Definitions
-----------

.. _approval flag:

**Approval Flag** - A flag that represents a security approval or uplift
request on a patch.

.. _bugzilla:

**Bugzilla** - Web-based general purpose bug tracking system and testing
tool.

.. _channel:

**Channel** - Development channels producing concurrent releases of
Firefox for Windows, Mac, Linux, and Android.

.. _chemspill:

**Chemspill** - Short for Chemical Spill. A chemspill is a rapid
security-driven or critical stsbility dot release of our product.

.. _channel meeting:

**Channel Meeting** - A twice weekly time to check in on the status
of the active releases with the release team.

.. _dot release drivers:

**Dot Release Drivers** - Issues/Fixes that are significant enough to
warrant a minor dot release to the Firefox Release Channel. Usually to
fix a stability (top-crash) or Security (Chemspill) issue.

.. _early beta:

**Early Beta** - Beta releases with the features gated by EARLY_BETA_OR_EARLIER
enabled. The first 2 weeks of Beta releases during the cycle are early beta releases.

.. _feature owner:

**Feature Owner** - The person who is ultimately responsible for
developing a high quality feature. This is typically an Engineering
Manager or Product Manager.

.. _github:

**Github** - Web-based version control and collaboration platform for
software developers

.. _gtb:

**GTB** - Acronym for Go to build.  Mostly used in the release schedule
communication ("Go to build on March 18"), this means that we initiate the
building of a specific release.

.. _landing:

**Landing** - A general term used for when code is merged into a
particular source code repository

.. _lando:

**Lando** - Automated code lander for Mozilla. It is integrated with
our `Phabricator instance <https://phabricator.services.mozilla.com>`__
and can be used to land revisions to various repositories.

.. _merge:

**Merge** - General term used to describe the process of integrating and
reconciling file changes within the mozilla repositories

.. _nimbus:

**Nimbus** - Nimbus is a collection of servers, workflows, and
Firefox components that enables Mozilla to remotely control Firefox
clients in the wild based on precise criteria

.. _nucleus:

**Nucleus** - Name of the internal application used by release managers
to prepare and publish release notes. The data in this application is
fetched by mozilla.org.

.. _orange_factor:

**Orange** - Also called flaky or intermittent tests. Describes a state
when a test or a testsuite can intermittently fail.

.. _phabricator:

**Phabricator** - Mozilla’s instance of the web-based software
development collaboration tool suite. Read more about `Phabricator as a
product <https://phacility.com/phabricator/>`__.

.. _preferences:

**Preferences** - A preference is any value or defined behavior that can
be set (e.g. enabled or disabled). Preference changes via user interface
usually take effect immediately. The values are saved to the user’s
Firefox profile on disk (in prefs.js).

.. _rc:

**Release Candidate** - Beta version with potential to be a final
product, which is ready to release unless significant bugs emerge.

.. _rc week:

**RC Week** - The week prior to release go-live is known as RC week.
During this week an RC is produced and tested.

.. _release cycle:

**Release Cycle** - The sum of stages of development and maturity for
the Firefox Release Product.

.. _reo:

**Regression Engineering Owner** - A partner for release management
assigned to each release. They both keep a mental state of how we are
doing and ensure a decision is made about each regression reported in
the release. AKA *REO*.

.. _release engineering:

**Release engineering** - Team primarily responsible for maintaining
the build pipeline, the signature mechanisms, the update servers, etc. aka *releng*

.. _release management:

**Release Management** - Team primarily responsible for the process of
managing, planning, scheduling and controlling a software build through
different stages and environments. aka *relman*.

.. _relnotes:

**Relnotes** - Short for release notes. Firefox Nightly, Beta, and Release each ship
with release notes.

.. _Repository:

**Repository** - a collection of stored data from existing databases
merged into one so that it may be shared, analyzed or updated throughout
an organization.

.. _ride alongs:

**Ride Alongs** - Bug fixes that are impacting release users but not
considered severe enough to ship without an identified dot release
driver.

.. _rollout:

**Rollout** - Shipping a release to a percentage of the release population.

.. _status flags:

**Status Flags** - A flag that represents the status of the bug with
respect to a Firefox release.

.. _string freeze:

**String Freeze** - Period during which the introduction, modification, or
deletion of strings exposed to the end-users is not allowed so as to allow our
localizers to translate our product.

.. _taskcluster:

**taskcluster** - Our execution framework to build, run tests on multiple
operating system, hardware and cloud providers.

.. _telemetry:

**Telemetry** - Firefox measures and collects non-personal information,
such as performance, hardware, usage and customizations. This
information is used by Mozilla to improve Firefox.

.. _train model:

**Train model** - a form of software release schedule in which a number
of distinct series of versioned software releases are released as a
number of different "trains" on a regular schedule.

.. _tracking flags:

**Tracking Flags** - A Bugzilla flag that shows whether a bug is being investigated
for possible resolution in a Firefox release. Bugs marked tracking-Firefox XX are
bugs that must be resolved one way or another before a particular release ship.

.. _throttle unthrottle:

**Throttle/Unthrottle a rollout** - Throttle is restricting a release rollout to 0%
of the release population, users can still choose to update but are not updated
automatically. Unthrottle is removing the release rollout restriction.

.. _uplift:

**Uplift** - the action of taking parts from a newer version of a
software system (firefox-main or firefox-beta) and porting them to an
older version of the same software (firefox-beta, firefox-release or ESR)

---

### Contributing Reviewer Checklist (`docs/contributing/reviewer_checklist.rst`)

Reviewer Checklist
==================

   Submitting patches to Mozilla source code needn't be complex. This
   article provides a list of best practices for your patch content that
   reviewers will check for or require. Following these best practices
   will lead to a smoother, more rapid process of review and acceptance.


Good web citizenship
--------------------

-  Make sure new web-exposed APIs actually make sense and are either
   standards track or preffed off by default.
-  In C++, wrapper-cache as needed. If your object can be gotten from
   somewhere without creating it in the process, it needs to be
   wrapper-cached.


Correctness
-----------

-  The bug being fixed is a valid bug and should be fixed.
-  The patch fixes the issue.
-  The patch is not unnecessarily complicated.
-  The patch does not add duplicates of existing code ('almost
   duplicates' could mean a refactor is needed). Commonly this results
   in "part 0" of a bug, which is "tidy things up to make the fix easier
   to write and review".
-  If QA needs to verify the fix, you should provide steps to reproduce
   (STR).


Quality
-------

-  If you can unit-test it, you should unit-test it.
-  If it's JS, try to design and build so that xpcshell can exercise
   most functionality. It's quicker.
-  Make sure the patch doesn't create any unused code (e.g., remove
   strings when removing a feature)
-  All caught exceptions should be logged at the appropriate level,
   bearing in mind personally identifiable information, but also
   considering the expense of computing and recording log output.
   [Fennec: Checking for log levels is expensive unless you're using
   Logger.]
-  Error messages that appear in web platform environments should
   explain the reason for the error, and use web platform terminology
   (as opposed to internal Firefox terminology). More details can be
   found in the :ref:`helpful error messages guide
   <Helpful error messages for web developers>`.


Style
-----

-  Follow the `style
   guide <https://firefox-source-docs.mozilla.org/code-quality/coding-style/index.html>`__
   for the language and module in question.
-  Follow local style for the surrounding code, even if that local style
   isn't formally documented.
-  New files have license declarations and modelines.
-  New JS files should use strict mode.
-  Trailing whitespace (git diff highlight this). You can use git rebase --whitespace=fix.


Security issues
---------------

-  There should be no writing to arbitrary files outside the profile
   folder.
-  Be careful when reading user input, network input, or files on disk.
   Assume that inputs will be too big, too short, empty, malformed, or
   malicious.
-  Tag for sec review if unsure.
-  If you're writing code that uses JSAPI, chances are you got it wrong.
   Try hard to avoid doing that.


Privacy issues
--------------

-  There should be no logging of URLs or content from which URLs may be
   inferred.
-  [Fennec: Android Services has Logger.pii() for this purpose (e.g.,
   logging profile dir)].
-  Tag for privacy review if needed.


Resource leaks
--------------

-  In Java, memory leaks are largely due to singletons holding on to
   caches and collections, or observers sticking around, or runnables
   sitting in a queue.
-  In C++, cycle-collect as needed. If JavaScript can see your object,
   it probably needs to be cycle-collected.
-  [Fennec: If your custom view does animations, it's better to clean up
   runnables in onDetachFromWindow().]
-  Ensure all file handles and other closeable resources are closed
   appropriately.
-  [Fennec: When writing tests that use PaintedSurface, ensure the
   PaintedSurface is closed when you're done with it.]


Performance impact
------------------

-  Check for main-thread IO [Fennec: Android may warn about this with
   strictmode].
-  Remove debug logging that is not needed in production.


Threading issues
----------------

-  Enormous: correct use of locking and volatility; livelock and
   deadlock; ownership.
-  [Fennec: All view methods should be touched only on UI thread.]
-  [Fennec: Activity lifecycle awareness (works with "never keep
   activities"). Also test with oom-fennec
   (`https://hg.mozilla.org/users/blassey_mozilla.com/oom-fennec/) <https://hg.mozilla.org/users/blassey_mozilla.com/oom-fennec/%29>`__].


Compatibility
-------------

-  Version files, databases, messages
-  Tag messages with ids to disambiguate callers.
-  IDL UUIDs are updated when the interface is updated.
-  Android permissions should be 'grouped' into a common release to
   avoid breaking auto-updates.
-  Android APIs added since Froyo should be guarded by a version check.


Preffability
------------

-  If the feature being worked on is covered by prefs, make sure they
   are hooked up.
-  If working on a new feature, consider adding prefs to control the
   behavior.
-  Consider adding prefs to disable the feature entirely in case bugs
   are found later in the release cycle.
-  [Fennec: "Prefs" can be Gecko prefs, SharedPreferences values, or
   build-time flags. Which one you choose depends on how the feature is
   implemented: a pure Java service can't easily check Gecko prefs, for
   example.]


Strings
-------

-  There should be no string changes in patches that will be uplifted
   (including string removals).
-  Rev entity names for string changes.
-  When making UI changes, be aware of the fact that strings will be
   different lengths in different locales.


Documentation
-------------

-  The commit message should describe what the patch is changing (not be
   a copy of the bug summary). The first line should be a short
   description (since only the first line is shown in the log), and
   additional description, if needed, should be present, properly
   wrapped, in later lines.
-  Adequately document any potentially confusing pieces of code.
-  Flag a bug with dev-doc-needed if any addon or web APIs are affected.
-  Use Javadocs extensively, especially on any new non-private methods.
-  When moving files, ensure blame/annotate is preserved.


Accessibility
-------------

-  For HTML pages, images should have the alt attribute set when
   appropriate. Similarly, a button that is not a native HTML button
   should have role="button" and the aria-label attribute set.
-  [Fennec: Make sure contentDescription is set for parts of the UI that
   should be accessible]

---

### Contributing Reviews (`docs/contributing/reviews.rst`)

Getting reviews
===============


Thorough code reviews are one of Mozilla's ways of ensuring code quality.
Every patch must be reviewed by the module owner of the code, or one of their designated peers.

Commit message syntax
---------------------

When submitting your commit(s), use the following syntax to request review for your patch:

.. list-table::
   :header-rows: 1

   * - Request
     - Syntax
     - Description
   * - Single reviewer
     - ``r=reviewer``
     - Request a review from a single reviewer (``reviewer``). Historically, the syntax ``r?reviewer`` requested a review, and ``r=reviewer`` marked the reviewer who accepted the patch before landing. Both can now be used interchangeably when requesting a review.
   * - Multiple reviewers
     - ``r=reviewer1,reviewer2``
     - Request reviews from *both* ``reviewer1`` and ``reviewer2``.
   * - Blocking review
     - ``r=reviewer!``
     - Request a *blocking* review from ``reviewer``. This means that ``reviewer`` *must* review the patch before it can be landed.
   * - Both optional and blocking reviews
     - ``r=reviewer1,reviewer2!``
     - Request a *blocking* review from ``reviewer2``, and an *optional* review from ``reviewer1``.
   * - Review groups
     - ``r=#review-group``
     - Request a review from members of ``#review-group``. A full list can be found below.
   * - Blocking review groups
     - ``r=#review-group!``
     - Request a blocking review from a review group. This will require *at least one member* of the group to approve before landing.

For example, the commit syntax to request review from group ``group-name`` or ``developer-nickname`` would be:

.. code-block::

     Bug xxxx - explain what you are doing and why r?#group-name

     or

     Bug xxxx - explain what you are doing and why r?developer-nickname

Reviews, and review groups, can be selected or adjusted after submission in the phabricator UI.

Sometimes when publishing a patch, groups will automatically be added as blocking reviewers due to the code being touched. In this case, you may want to check that the reviewers you requested review from are set to blocking as well.

Choosing reviewers
------------------

* If you have a mentor assigned on the bug you are fixing, the mentor can usually either also review or find a suitable reviewer on your behalf.
* If you do not have a mentor, see if your code fits into one of the review groups below, and request review from that group.
* Otherwise, try looking at the history of the file to see who has modified it recently (for example, ``git log <modified-file>``).
* Finally if you are still unable to identify someone, try asking in the `#introduction channel on Matrix <https://chat.mozilla.org/#/room/#introduction:mozilla.org>`_.


Getting attention
-----------------

Generally most reviews will happen within roughly a week. If, however, a reviewer doesn't respond within a week or so of the review request:

  * Contact the reviewer directly (either via e-mail or on Matrix).
  * Join developers on `Mozilla's Matrix server <https://chat.mozilla.org>`_, and ask if anyone knows why a review may be delayed. Please link to the bug too.
  * If the review is still not addressed, mail the reviewer directly, asking if/when they'll have time to review the patch, or might otherwise be able to review it.

Remember that reviewers are human too, and may have complex reasons that prevent them from reviewing your patch in a timely manner. Be confident in reaching out to your reviewer, but be mindful of the `Mozilla Community Participation Guidelines <https://www.mozilla.org/en-US/about/governance/policies/participation/>`_ while doing so.

For simple documentation changes, reviews are not required.

For more information about the review process, see the :ref:`Code Review FAQ`.

Review groups
-------------


.. list-table::
   :header-rows: 1

   * - Name
     - Owns
     - Members
   * - #anchor-positioning-reviewers
     - Anchor positioning - related style and layout code
     - `Member list <https://phabricator.services.mozilla.com/project/members/216/>`__
   * - #anti-tracking
     - `Core: Anti-Tracking </mots/index.html#core-anti-tracking>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/157/>`__
   * - #build or #firefox-build-system-reviewers
     - The configure & build system
     - `Member list <https://phabricator.services.mozilla.com/project/members/20/>`__
   * - #cookies
     - `Core: Cookies </mots/index.html#core-cookies>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/177/>`__
   * - #cubeb-reviewers
     - cubeb, Gecko's audio input/output library and associated projects (audioipc, cubeb-rs, rust cubeb backends)
     - `Member list <https://phabricator.services.mozilla.com/project/profile/129/>`__
   * - #desktop-theme-reviewers
     - `User interface CSS </mots/index.html#desktop-theme>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/141/>`__
   * - #devtools-reviewers
     - `Firefox DevTools </mots/index.html#devtools>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/153/>`__
   * - #dom-core
     - `Core: DOM <https://firefox-source-docs.mozilla.org/mots/index.html#core-document-object-model>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/178/>`__
   * - #dom-worker-reviewers
     - DOM Workers
     - `Member list <https://phabricator.services.mozilla.com/project/members/146/>`__
   * - #dom-storage-reviewers
     - DOM Storage
     - `Member list <https://phabricator.services.mozilla.com/project/members/147/>`__
   * - #extension-reviewers
     - `WebExtensions </mots/index.html#webextensions>`__ and `Toolkit::Add-ons Manager </mots/index.html#add-ons-manager>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/130/>`__
   * - #fluent-reviewers
     - Fluent (FTL) files (translation).
     - `Member list <https://phabricator.services.mozilla.com/project/members/105/>`__
   * - #firefox-source-docs-reviewers
     - Documentation files and its build
     - `Member list <https://phabricator.services.mozilla.com/project/members/118/>`__
   * - #firefox-ux-team
     - User experience (UX)
     - `Member list <https://phabricator.services.mozilla.com/project/members/91/>`__
   * - #firefox-svg-reviewers
     - SVG-related changes
     - `Member list <https://phabricator.services.mozilla.com/project/members/97/>`__
   * - #frontend-codestyle-reviewers
     - ESLint, Prettier or Stylelint configurations.
     - `Member list <https://phabricator.services.mozilla.com/project/members/208/>`__
   * - #android-reviewers
     - Fenix, Focus and Android Components.
     - `Member list <https://phabricator.services.mozilla.com/project/members/200/>`__
   * - #geckoview-reviewers
     - GeckoView
     - `Member list <https://phabricator.services.mozilla.com/project/members/92/>`__
   * - #gfx-reviewers
     - Graphics code
     - `Member list <https://phabricator.services.mozilla.com/project/members/122/>`__
   * - #intermittent-reviewers
     - Test manifest changes
     - `Member list <https://phabricator.services.mozilla.com/project/members/110/>`__
   * - #ipc-reviewers
     - `Core: IPC <https://firefox-source-docs.mozilla.org/mots/index.html#core-ipc>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/145/>`__
   * - #layout-reviewers
     - Layout
     - `Member list <https://phabricator.services.mozilla.com/project/members/126/>`__
   * - #layout-grid-reviewers
     - layout/grid
     - `Member list <https://phabricator.services.mozilla.com/project/members/215/>`__
   * - #linter-reviewers
     - tools/lint/*
     - `Member list <https://phabricator.services.mozilla.com/project/members/119/>`__
   * - #mac-reviewers
     - Mac-specific code
     - `Member list <https://phabricator.services.mozilla.com/project/members/149/>`__
   * - #media-playback-reviewers
     - `Media playback <https://wiki.mozilla.org/Modules/All#Media_Playback>`__
     - `Member list <https://phabricator.services.mozilla.com/project/profile/159/>`__
   * - #mozbase
     - Mozbase
     - `Member list <https://phabricator.services.mozilla.com/project/members/113/>`__
   * - #mozbase-rust
     - Mozbase in Rust
     - `Member list <https://phabricator.services.mozilla.com/project/members/114/>`__
   * - #necko-reviewers
     - network code (aka necko, aka netwerk)
     - `Member list <https://phabricator.services.mozilla.com/project/members/127/>`__
   * - #nss-reviewers
     - Network Security Services (NSS)
     - `Member list <https://phabricator.services.mozilla.com/project/members/156/>`__
   * - #perftest-reviewers
     - Perf Tests
     - `Member list <https://phabricator.services.mozilla.com/project/members/102/>`__
   * - #permissions or #permissions-reviewers
     - `Permissions </mots/index.html#core-permissions>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/158/>`__
   * - #places-reviewers
     - `Bookmarks & History (Places) </mots/index.html#bookmarks-history>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/186/>`__
   * - #platform-i18n-reviewers
     - Platform Internationalization
     - `Member list <https://phabricator.services.mozilla.com/project/members/150/>`__
   * - #preferences-reviewers
     - Firefox for Desktop Preferences (Options) user interface
     - `Member list <https://phabricator.services.mozilla.com/project/members/132/>`__
   * - #recomp-reviewers or #reusable-components-reviewers
     - UI Widgets, Design Tokens, Storybook
     - `Member list <https://phabricator.services.mozilla.com/project/members/185/>`__
   * - #remote-debugging-reviewers
     - Remote Debugging UI & tools
     - `Member list <https://phabricator.services.mozilla.com/project/members/108/>`__
   * - #search-reviewers
     - `Search </mots/index.html#search>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/169/>`__
   * - #sessionstore or #sessionstore-reviewers
     - `Firefox: Session Restore </mots/index.html#session-restore>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/179/>`__
   * - #spidermonkey-reviewers
     - SpiderMonkey JS/Wasm Engine
     - `Member list <https://phabricator.services.mozilla.com/project/members/173/>`__
   * - #static-analysis-reviewers
     - Static Analysis
     - `Member list <https://phabricator.services.mozilla.com/project/members/120/>`__
   * - #style or #firefox-style-system-reviewers
     - Firefox style system (servo, layout/style).
     - `Member list <https://phabricator.services.mozilla.com/project/members/90/>`__
   * - #supply-chain-reviewers
     - Third-party audits and vendoring (cargo-vet, supply_chain).
     - `Member list <https://phabricator.services.mozilla.com/project/members/164/>`__
   * - #tabbrowser or #tabbrowser-reviewers
     - `Firefox: Tabbed Browser </mots/index.html#tabbed-browser>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/180/>`__
   * - #theme or #desktop-theme-reviewers
     - `Firefox: Theme and Toolkit: Themes </mots/index.html#desktop-theme>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/141/>`__
   * - #translations-reviewers
     - `Firefox: Translation <https://firefox-source-docs.mozilla.org/mots/index.html#translation>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/192/>`__
   * - #urlbar-reviewers
     - `Urlbar (Address Bar) </mots/index.html#address-bar>`__
     - `Member list <https://phabricator.services.mozilla.com/project/members/211/>`__
   * - #view-transitions-reviewers or #view-transitions or #vt
     - View Transitions (dom/view-transitions, and the relevant style / layout / gfx code).
     - `Member list <https://phabricator.services.mozilla.com/project/members/217/>`__
   * - #webcompat-reviewers
     - System addons maintained by the Web Compatibility team
     - `Member list <https://phabricator.services.mozilla.com/project/members/124/>`__
   * - #webdriver-reviewers
     - Marionette and geckodriver (including MozBase Rust), and Remote Protocol with WebDriver BiDi, and CDP.
     - `Member list <https://phabricator.services.mozilla.com/project/members/103/>`__
   * - #webgpu-reviewers
     - WebGPU code
     - `Member list <https://phabricator.services.mozilla.com/project/members/170/>`__
   * - #webidl
     - WebIDL
     - `Member list <https://phabricator.services.mozilla.com/project/members/112/>`__
   * - #xpcom-reviewers
     - XPCOM
     - `Member list <https://phabricator.services.mozilla.com/project/members/125/>`__

To create a new group, fill a `new bug in Conduit::Administration <https://bugzilla.mozilla.org/enter_bug.cgi?product=Conduit&component=Administration>`__.
See `bug 1613306 <https://bugzilla.mozilla.org/show_bug.cgi?id=1613306>`__ as example.

---

--- METRICS ---
- Files Extracted: 100
- Estimated Token Budget: ~166722 tokens
- Canonical Reference: https://codewiki.google/github.com/BrowserWorks/waterfox
