Removing an API is easy. Proving nobody needs it, migrating every owner, and preventing it from coming back is the real work.
Status: ๐ Landed
Two Kinds of Time
Chromium has two clocks for two different jobs:
base::Timeis wall-clock time. It can be represented as a calendar date and related to the Unix epoch.base::TimeTicksis monotonic time. It is for durations and ordering events, and its zero point is deliberately arbitrary.
base::TimeTicks::UnixEpoch() blurred that boundary. It made a monotonic clock look as if it had a meaningful calendar epoch. To keep the result consistent across child processes, Chromium also passed a time-ticks-at-unix-epoch value at process startup and installed it through SetSharedUnixEpoch().
That was a lot of machinery to preserve a conversion callers generally should not perform. If code needs wall-clock time, it should use base::Time.
Why Not Delete It in One CL?
The API had users in networking, Chrome OS, session restore, page-load metrics, DevTools protocol handlers, Cronet, performance manager, Ozone input code, chromedriver, cast statistics, tests, and more. Those directories have different owners and different assumptions.
One large replacement would be difficult to review and risky to revert. The safer shape was deliberately boring:
- Add a PRESUBMIT rule banning new calls while existing ones are being removed.
- Move each directory to
base::Timein a small owner-scoped CL. - Delete the cross-process epoch switch and initialization plumbing.
- Delete the API itself.
The PRESUBMIT step happened early, not at the end. Otherwise the migration target moves while you are chasing it.
Removing the Plumbing
Once the last real users were gone, the architecture became simpler. Chromium no longer needed to launch child processes with a special time-ticks epoch or initialize a shared value before clients could use the API.
That CL removed the command-line switch and the SetSharedUnixEpoch() wiring. With that gone, TimeTicks::UnixEpoch() no longer had a cross-process definition to preserve.
Closing the Door
The final pair made the migration permanent:
The deletion CL is tiny because all the difficult decisions happened before it. That is a good sign: the final removal should be mechanical.
The Pattern
This is the reusable part of the story. For a codebase-wide API removal:
- state what the replacement means, not just what it is called;
- stop new callers before migrating old ones;
- split migrations along ownership boundaries;
- remove supporting infrastructure only after callers are gone;
- land the final deletion when it is uneventful.
The goal is not a dramatic cleanup CL. The goal is for the deletion to be the least interesting patch in the series.