File: update_protocol_commands_enum.py

package info (click to toggle)
chromium 120.0.6099.224-1~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,112,112 kB
  • sloc: cpp: 32,907,025; ansic: 8,148,123; javascript: 3,679,536; python: 2,031,248; asm: 959,718; java: 804,675; xml: 617,256; sh: 111,417; objc: 100,835; perl: 88,443; cs: 53,032; makefile: 29,579; fortran: 24,137; php: 21,162; tcl: 21,147; sql: 20,809; ruby: 17,735; pascal: 12,864; yacc: 8,045; lisp: 3,388; lex: 1,323; ada: 727; awk: 329; jsp: 267; csh: 117; exp: 43; sed: 37
file content (149 lines) | stat: -rwxr-xr-x 4,563 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env python
# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import os
import re
import sys
import hashlib
import ctypes

from xml.dom import minidom

sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common'))
import path_util

sys.path.append(
    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'third_party',
                 'inspector_protocol'))
import pdl

import update_histogram_enum
import histogram_paths


def GetCommandUMAId(cdp_command):
  """Generate a hash consistent with GetCommandUMAId() in ChromeDevToolsSession.

   Args:
    cdp_command: A string containing a CDP command.

   Returns:
    The hashed value for the CDP command.
  """
  digest = hashlib.md5(cdp_command.encode('utf-8')).hexdigest()
  first_eight_bytes = digest[:16]
  long_value = int(first_eight_bytes, 16)
  signed_32bit = ctypes.c_int(long_value).value
  return signed_32bit


def ParseProtocolCommandsFromPDL(file_path):
  """Parses a PDL file and returns a dictionary of all its commands and their
  hashes.

   Args:
    file_path: The path of the PDL file.

   Returns:
    A dictionary with the hashes as keys and the CDP commands as values.
  """
  file_name = path_util.GetInputFile(file_path)
  input_file = open(file_name, "r")
  pdl_string = input_file.read()
  protocol = pdl.loads(pdl_string, file_name, False)
  input_file.close()

  result = {}
  for domain in protocol["domains"]:
    if "commands" in domain:
      for command in domain["commands"]:
        command_name = domain["domain"] + "." + command["name"]
        hashed_command = GetCommandUMAId(command_name)
        if (hashed_command in result):
          print('Hash collision between "{}" and "{}" in {} when '\
          'generating CDPCommands for enums.xml'
          .format(result[hashed_command], command_name, file_path))
        result[hashed_command] = command_name

  return result


def ParseProtocolCommandsFromXML():
  """Parses the 'CDPCommands' enum in enums.xml.

   Returns:
    A dictionary with the hashes as keys and the CDP commands as values.
  """
  document = minidom.parse(
      path_util.GetInputFile(histogram_paths.ENUMS_XML_RELATIVE))
  result = {}

  # Get DOM of the <enum name="CDPCommands"> node.
  for enum_node in document.getElementsByTagName('enum'):
    if enum_node.attributes['name'].value == 'CDPCommands':
      break
  else:
    raise UserError('CDPCommands enum node not found in enums.xml')

  for child in enum_node.childNodes:
    if child.nodeName == 'int':
      enum_value = int(child.attributes['value'].value)
      enum_label = str(child.attributes['label'].value)
      result[enum_value] = enum_label

  return result


def CheckDictsForCollisions(first, second):
  """Compares 2 dictionaries and prints an error message for each key which
  is contained in both dics for which the corresponding value differs in the
  2 dicts.

   Args:
    first: A dictionary.
    second: A dictionary.
  """
  for hashedValue in first.keys():
    if (hashedValue in second and second[hashedValue] != first[hashedValue]):
      print(
        'Hash collision between "{}" and "{}" when generating CDPCommands '\
        'for enums.xml'
        .format(first[hashedValue], second[hashedValue]))


def MaybeUpdateEnumFromFile(file_path):
  """Gets the results of parsing a pdl file and of enums.xml, and updates
  enums.xml if necessary.

   Args:
    file_path: Path of the pdl file to be parsed.
  """
  print('Parsing {}'.format(file_path))
  pdl_dict = ParseProtocolCommandsFromPDL(file_path)
  xml_dict = ParseProtocolCommandsFromXML()
  CheckDictsForCollisions(pdl_dict, xml_dict)
  files_for_enum_comment = '*.pdl files'
  update_histogram_enum.UpdateHistogramFromDict('CDPCommands', pdl_dict,
                                                files_for_enum_comment,
                                                os.path.basename(__file__))


def main():
  """Checks that the 'CDPCommands' enum in enums.xml matches the content of
  the various pdl protocol definition files and updates the enum if necessary.
  """

  pdl_file_paths = [
      'third_party/blink/public/devtools_protocol/browser_protocol.pdl',
      'v8/include/js_protocol.pdl', 'chrome/browser/devtools/cros_protocol.pdl',
      'components/viz/common/debugger/viz_debugger.pdl',
      'content/browser/native_profiling.pdl'
  ]
  for pdl_file_path in pdl_file_paths:
    MaybeUpdateEnumFromFile(pdl_file_path)


if __name__ == '__main__':
  main()