Concepts — Contributing to Chromium
Phase 6 · Spec areas §24 (contribution workflow), §49 (OSS portfolio). Requires a working build.
Verify everything here against current upstream
docs/before acting. Contribution process changes, and a stale instruction wastes a reviewer's time — which is the one cost that matters in an open-source contribution.
0. Orientation
The 60-second version
Landing a change in Chromium is the point where reading becomes standing. Not because the patch matters — a first CL is usually tiny — but because the process is the thing you are learning, and it is the most rigorous code-review culture most engineers will ever encounter.
Two things are worth taking away regardless of whether you ever contribute again:
1. A web-visible change is a different kind of change. Anything a page can observe requires specification work, cross-engine signals, and a compatibility argument — because it cannot be un-shipped. Understanding that process is what lets you reason about why the platform moves slowly instead of complaining that it does.
2. What makes a CL easy to approve is a transferable skill. Small, single-purpose, tested, with the reasoning in the description rather than in the reviewer's head. That is not Chromium-specific etiquette; it is what makes any change reviewable, and most engineers learn it far later than they should.
Choosing a first bug that will actually land
The common failure is picking something interesting rather than something tractable. A bug that lands teaches you the whole pipeline; a bug that stalls teaches you nothing and costs a month. The selection criteria matter more than the fix.
What you should be able to do after this module
| Capability | Evidence you have it |
|---|---|
| Land a change | Through review, try jobs, and the commit queue, without special help |
| Write a reviewable CL | Small, single-purpose, tested, with the reasoning written down |
| Reason about web-visible change | Explain what shipping to the web irreversibly commits you to |
| Keep a record | Maintain evidence of what you learned, for the reasons in §3.8 |
1. Why a Principal Engineer needs this
Landing a change in Chromium is a credential, but the reason it belongs in this track is narrower and better: it forces every other skill to be real. You cannot land a fix without locating the subsystem, understanding the invariant, writing the right test, and defending the design to someone who owns the code. Reading Blink is unfalsifiable; a CL is not.
It also teaches something you cannot learn from your own codebase: how to make a change in a system you do not own, for reviewers who owe you nothing. That skill transfers directly to cross-org work at Principal level.
2. Mental Model
2.1 The pipeline
find a bug -> reproduce -> locate subsystem -> minimal failing test
-> fix -> local tests -> git cl upload -> Gerrit review
-> OWNERS approval -> presubmit + try jobs -> CQ -> landed
Facts that shape the work:
- Issue tracker:
issues.chromium.org. (Chromium's owndocs/contributing.mdstill contains abugs.chromium.orgreference — treat in-tree docs as authoritative but not infallible, and prefer what the live site does.) - CLA required; first-time contributors add themselves to
AUTHORS. - Review happens in Gerrit (
chromium-review.googlesource.com), not GitHub PRs. One change = one CL, revised as patchsets, not as new commits. - OWNERS approval is required per affected directory.
git cl ownerssuggests reviewers. Committers need oneCode-Review +1; non-committers need two. - Presubmit runs on upload; try jobs compile and test across platforms. A CQ dry run is how you check before asking for a human's time.
2.2 Choosing the change
The ladder from the specification, with what each actually teaches:
| Rung | Change | Teaches |
|---|---|---|
| 0 | Build Chromium | toolchain, targets, iteration |
| 1 | Docs or test-only | the process end to end, at low risk |
| 2 | Small isolated correctness fix | locating a cause; minimal reproduction |
| 3 | Blink behaviour bug + regression test | spec → test → implementation, the core loop |
| 4 | Small rendering/style/layout improvement | subsystem depth, performance argument |
| 5 | Cross-component change | Mojo boundaries, multiple OWNERS, design review |
Do rung 1 before rung 2, even though it feels trivial. The first CL's difficulty is entirely
process — CLA, git cl, Gerrit conventions, presubmit, try-job failures unrelated to your
change. Learning that with a doc fix costs a day; learning it while also defending a behaviour
change costs a week and a reviewer's patience.
2.3 Where to find work
TestExpectations(bi-13) — documented, accepted, currently-wrong behaviours with bugs attached. This is the best-quality source of rung-3 candidates in the tree.- Failing WPTs in a subsystem you have studied.
- The issue tracker, filtered to components you know. Look for hotlists aimed at new contributors; verify the current label names on the live tracker rather than trusting any written list, including this one.
- A bug you actually hit. The strongest motivation and the best reproduction.
Choose a bug in a subsystem you have already studied in this track. A contribution is not the place to learn the subsystem.
2.4 What reviewers actually check
In rough order:
- Is the behaviour correct per the specification?
- Is there a test that fails without the fix?
- Is it at the right layer, and does it fit the subsystem's design?
- Ownership/lifetime correctness (
bi-06). - Style, naming, and
git cl format. - Does it need a flag, a metric, or a spec discussion first?
Item 6 catches people out: a behaviour change visible to the web may need a launch process, metrics, and standards-body agreement — not because Chromium is bureaucratic, but because unilateral behaviour changes break sites and interop. If your fix changes what the web sees, expect the conversation to be about compatibility, not correctness.
3. Practice
Verify against your checkout's docs/contributing.md and the linked process docs. The
mechanical parts (git cl upload, git cl format, git cl owners, CQ dry run) are stable;
the surrounding policy is not.
Keep a record per attempt — the specification asks for exactly this, and it is what turns a contribution into learning:
bug · reproduction · spec · suspected subsystem · source path · call path
· test · proposed fix · reviewer feedback · architectural lesson
3.5 Deep dive: the web-visible change process
Rung 3 and above frequently touch behaviour the web can observe. That is a different process from a bug fix, and not knowing it is the fastest way to have a technically-correct CL stall for months.
The shape of it:
idea -> spec discussion (WHATWG/W3C issue, or a explainer)
-> design doc, if non-trivial
-> UseCounter metrics: how much of the web actually does this?
-> intent-to-prototype -> behind a flag -> origin trial (sometimes)
-> intent-to-experiment / intent-to-ship on blink-dev
-> API owners' approval
-> ship, with metrics watching for regressions
The single most important artefact in that list is UseCounter. Blink instruments feature
usage and aggregates it across the web, so questions like "how many page loads use this quirk?"
have a real number attached. A removal proposal without usage data will not proceed.
This is the part that most surprises engineers arriving from product work. In a product you change behaviour and watch your own metrics. Here, "correct per spec" is necessary and not sufficient — you must also show the web will survive it. Compatibility is a constraint of equal weight to correctness, and arguing otherwise marks you as someone who has not internalised the problem.
If your fix changes what pages observe, expect the review conversation to be about compatibility and data, not about whether you read the spec correctly.
3.6 Deep dive: what makes a CL easy to approve
Reviewers are rationing attention across many changes. Optimise for their time, not yours.
Structural:
- One change per CL. A fix plus a refactor plus a rename is three CLs.
- Small. A first CL over ~200 lines is asking a stranger for a large favour.
- Test first in the description: state what fails without the fix.
git cl formatbefore every upload; never spend credibility on whitespace.
In the description:
- What the bug is, in one sentence a non-expert can follow.
- Why this layer is the right place to fix it — pre-empting the most likely objection.
- What you considered and rejected. This converts "why didn't you just…" into "they already thought about it."
Bug:footer, always.
In the code:
- Match the newest pattern in the file, not the nearest (
bi-06: migrations in progress). - Add a
DCHECKstating any new invariant. - Correct handle types (
Membervsraw_ptrvsunique_ptr) — the most likely substantive comment.
Handling review feedback
- Reply to every comment, even if only "Done."
- If you disagree, say so once, with reasoning, and ask a question rather than restating.
- If a reviewer wants a design change you think is wrong, ask what failure mode they are protecting against. Usually they know something you do not; occasionally the question reveals they misread. Either outcome is progress.
- Going quiet is worse than being wrong. An abandoned CL costs the reviewer more than a bad one.
3.7 Deep dive: how to pick a first bug that will actually land
Bad first bugs share a shape: they are interesting. Interesting bugs are unfixed because they are hard, contested, or blocked on a design decision.
A good first bug:
- is in a subsystem you have already studied in this track,
- has a reliable reproduction,
- has a clear expected behaviour, ideally spec-defined or in
TestExpectations, - is small — one file, one behaviour,
- is not load-bearing for a feature someone is actively rewriting (check
git logfor recent churn in the directory — heavy recent activity means you will conflict with a bigger change).
That last check takes thirty seconds and saves weeks:
git log --since=90.days --oneline -- <directory> | wc -l
A directory with a hundred commits in ninety days is being actively rewritten. Pick elsewhere for your first CL.
3.8 Deep dive: the record to keep, and why
The specification asks for a record per contribution. Here is why each field earns its place:
| Field | Why |
|---|---|
| bug | the problem, as the project sees it |
| reproduction | the thing you will lose first if you do not write it down |
| spec | what should happen, independent of any implementation |
| suspected subsystem | your prediction — score it later (bi-01 discipline) |
| source path + call path | the navigation, so it transfers |
| test | what would have caught this |
| proposed fix | including alternatives rejected |
| reviewer feedback | the highest-value field |
| architectural lesson | what you now believe that you did not before |
Reviewer feedback is the field to protect. It is the only part of this you cannot generate yourself: a domain expert telling you what you missed, for free, on your own work. Most engineers read it, fix the code, and forget it. Writing it down converts a code review into a durable lesson.
And write the record for rejected CLs too. A rejected CL with a clear architectural lesson is a successful lab; the goal of rungs 1–3 is competence, not a merge count.
4. Anti-Patterns
A first CL that is large. Reviewers ration attention; so should you.
Fixing a symptom at a call site because the real cause is in unfamiliar code.
Arguing with a reviewer about style. Run git cl format and spend your credibility on
substance.
Changing web-visible behaviour without checking compatibility. Expect to be asked for usage metrics and interop evidence.
Going quiet after review feedback. An abandoned CL costs the reviewer more than a bad one.
Starting at rung 3 to skip the boring parts. The boring parts are where the process failures live.
5. Trade-offs
Small safe changes vs meaningful ones. Rung 1 teaches process and nothing else. Rung 3 teaches the subsystem and risks stalling. Do both, in order.
Fixing vs filing. A well-written bug with a minimal reproduction is a real contribution and sometimes the better one, especially when the fix requires design agreement you cannot yet obtain.
Chromium vs WPT. A WPT contribution needs no C++, improves every browser, and lands faster. For an application engineer it is frequently higher leverage — and it is the right rung-1 alternative if a doc fix feels too trivial.
6. Lab
- Rung 0 — a build that runs. (Blocked here; see the roadmap's build guide §2.0.)
- Rung 1 — land a docs or test-only change. Goal: complete the process once. Record every step that surprised you.
- Rung 2 — from your
bi-13candidate list, pick the smallest defensible correctness fix. Write the failing test first. - Rung 3 — a Blink behaviour bug with a regression test, in a subsystem you studied.
- Maintain the record above for each, and write the architectural lesson even when the CL is rejected. A rejected CL with a clear lesson is a successful lab.
7. References
docs/contributing.mdin your checkout — the authority.docs/cl_tips.md,docs/code_reviews.md, and theOWNERSdocumentation.issues.chromium.org— the live tracker.- The Chromium blink-dev process for web-visible behaviour changes (intent-to-ship and friends).
- web-platform-tests contribution guide.
Core terminology
| Term | Definition |
|---|---|
| CL | Change List — the unit of review, on Gerrit |
| Gerrit | Chromium's review system; patchsets, not force-pushed branches |
| Patchset | One revision of a CL; reviewers compare between them |
| OWNERS | Per-directory file listing who must approve changes there |
| LGTM | Approval from an owner |
| Try job | Pre-submit run of build and tests against your CL |
| CQ (commit queue) | The automated gate that lands a CL once it passes |
| Presubmit | Local checks (style, DEPS, formatting) run before upload |
| Web-visible change | Anything page script can observe; requires the heavier process |
| Intent to Ship / Prototype / Experiment | The stages of the web-visible change process |
| TAG review | Cross-cutting API design review |
| Cross-engine signals | Positions from other browser vendors on a proposed change |
| Origin trial | Time-limited real-world experiment before shipping |
Feature flag / RuntimeEnabled | Gating so a change can ship dark and be enabled separately |
| Revert | The default response to a breakage; landing is reversible, shipping to the web is not |
| Flaky-test triage | Attributing and tracking flakes rather than retrying past them |
Mental models
The process is the deliverable, not the patch. A first CL is usually trivial. What you are acquiring is the ability to move a change through an unfamiliar, rigorous system — which is precisely the skill that transfers to every large codebase you will ever join.
Reversibility determines rigour. A landed CL can be reverted in minutes; a shipped web API cannot be un-shipped. That asymmetry is the entire explanation for why the web-visible process is heavy and the ordinary review process is not. Once you see it that way, "the platform moves slowly" stops being a complaint and becomes a design property.
Make the reviewer's job small. Single purpose, small diff, tests that demonstrate the change, and the reasoning in the description rather than reconstructible only from the code. This is the highest-leverage habit in the module and it is not Chromium-specific.
Pick tractable over interesting. A bug that lands teaches the whole pipeline. A bug that stalls teaches nothing and costs a month. Selection is the skill; the fix usually is not.
Feature flags decouple landing from shipping. RuntimeEnabled means code can land, be reviewed,
be tested, and be enabled separately. Any organisation shipping risky changes wants this separation,
and most reinvent it badly.
Keep the record. What you tried, what you were wrong about, and what the review taught you. The
value is not sentimental — it is that classification skills (fw-11) need evidence, and evidence
needs to have been written down at the time.
Common misconceptions
-
"I need a significant change to contribute." A small, well-scoped, well-tested CL is a better first contribution and teaches the same pipeline.
-
"Review rigour is gatekeeping." It scales with reversibility. Ordinary CLs are reverted in minutes; web-visible behaviour cannot be recalled.
-
"The reviewer will figure out why I did this." The reasoning belongs in the description. A reviewer reconstructing intent from a diff is how good changes get rejected.
-
"Landing means shipping." Not with a feature flag. Decoupling those is what makes risky work safe to land.
-
"A revert is a failure." It is the intended, cheap response to a breakage, and treating it as a stigma makes people defend broken changes.
-
"Standards work is for spec people." A web-visible change requires an argument about compatibility that engineers are usually best placed to make.
-
"Big diffs are more efficient to review." They are more efficient to write and much worse to review, which is where the time actually goes.
Interview talking points
- "The deliverable of a first Chromium contribution isn't the patch, it's the ability to move a change through an unfamiliar rigorous system. That transfers to every large codebase you'll ever join, and the patch itself is usually trivial."
- "Review rigour scales with reversibility, and that's the whole explanation for why the web-visible process is heavy. A landed CL is reverted in minutes; a shipped web API can't be un-shipped. Once you frame it that way, 'the platform moves slowly' becomes a design property rather than a complaint."
- "The habit I'd take anywhere is making the reviewer's job small: single purpose, small diff, tests that demonstrate the change, and the reasoning in the description rather than reconstructible only from the code. A reviewer reconstructing intent from a diff is how good changes get rejected."
- "Feature flags decoupling landing from shipping is a pattern most organisations reinvent badly. Code can land, be reviewed, be tested, and be enabled separately — that's what makes risky work safe to land at all."
- "For a first bug I optimise for tractable over interesting. One that lands teaches you the whole pipeline; one that stalls teaches you nothing and costs a month. The selection is the skill."
8. Principal Engineer Review
-
Your fix is correct per spec but would break a measurable fraction of sites. What happens next, and what is your role in it?
-
A reviewer asks for a design change that doubles the work and you think it is wrong. How do you handle it, and what would change your mind?
-
Argue that a well-written bug report is more valuable than a mediocre fix. Give the case where it is not.
-
Chromium requires OWNERS approval per directory. Argue this scales; then name its failure mode and what you would do as an owner to mitigate it.
-
You have one week of a team's time for open-source contribution. Chromium, WPT, or a framework? Justify from leverage, not from prestige.
-
Your CL sits unreviewed for three weeks. Enumerate your options in order of escalation, and say which you would actually use.
-
What makes a change "cross-component," and why is that qualitatively harder than a large change within one component?
-
You are onboarding an engineer to contribute upstream. Design their first month. What do you deliberately not let them do yet?
Connections to other modules
bi-01— archaeology finds the CL; here you write one.bi-06— the style documents that govern are what your CL is reviewed against.bi-13— try jobs and the commit queue are the gates; a web-visible change adds more.bi-12— diagnosing a try-job failure uses those instruments.fw-11— classification needs evidence, and evidence needs to have been recorded at the time.fe-04— why the platform ships conservative, hard-to-reverse defaults.