#!/usr/bin/env vpython3
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This script lists the features in RuntimeEnabledFeatures that are
# status: stable, with the first Chrome milestone in which they were
# status: stable. This is useful for finding feature flags that we
# might be able to remove.
import os.path
import re
import sys
from blinkpy.common import path_finder
from blinkpy.common.system.filesystem import FileSystem
from blinkpy.common.checkout.git import Git
finder = path_finder.PathFinder(FileSystem())
sys.path.append(finder.path_from_chromium_base('third_party', 'pyjson5',
'src'))
import json5
def version_to_ints(version):
return list(map(int, version.split(".")))
def list_milestone_tags(git):
"""Return the latest (by numeric sort) tag for each Chrome milestone."""
version_re = re.compile(r'^\d+\.\d+\.\d+\.\d+$')
milestones = dict()
for line in git.run(["tag", "-l"]).splitlines():
line = line.strip()
if version_re.match(line):
version = version_to_ints(line)
major = version[0]
if not major in milestones or version_to_ints(
milestones[major]) < version:
milestones[major] = line
result = []
for major in sorted(milestones.keys()):
result.append(milestones[major])
return result
def features_file(milestone=None):
# These paths use / rather than os.path.join() because we (mostly)
# want to pass them to git show.
if (milestone is None or milestone >= 67):
return "third_party/blink/renderer/platform/runtime_enabled_features.json5"
# Moved in 0aee4434a4dba42a42abaea9bfbc0cd196a63bc1 (M67)
if (milestone >= 63):
return "third_party/WebKit/Source/platform/runtime_enabled_features.json5"
# Moved in a9b51b33da012d575b69c1d535c85dd68a76c8ad (M63)
if (milestone >= 58):
return "third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5"
# Converted to json5 in 5821741047894731b6527b607edfb8ddef33fd1b (M58)
# return "third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in"
return None # We can't parse it
def main():
git = Git()
with open(
os.path.join(os.path.normpath(git.checkout_root),
os.path.normpath(features_file()))) as features_io:
current_features_data = json5.load(features_io)["data"]
stable_features = dict()
for feature in current_features_data:
if feature.get("status", "") == "stable":
stable_features[feature["name"]] = "current"
for version in reversed(list_milestone_tags(git)):
major = version_to_ints(version)[0]
features_filepath = features_file(major)
if features_filepath is not None:
old_file = git.run(
["show", "{}:{}".format(version, features_filepath)])
old_data = json5.loads(old_file)["data"]
for feature in old_data:
name = feature["name"]
if feature.get("status",
"") == "stable" and name in stable_features:
stable_features[name] = version
for (feature, version) in sorted(
stable_features.items(),
key=lambda t: [1000000, 0, 0, 0, t[0]]
if t[1] == "current" else version_to_ints(t[1]) + [t[0]]):
print(version, feature)
if __name__ == "__main__":
sys.exit(main())