Re-enable index-basics-workers test to see if still times
[chromium-blink-merge.git] / tools / metrics / actions / extract_actions.py
blob06db55ceee598fe1650c00c2ee33357690aa5390
1 #!/usr/bin/env python
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 """Extract UserMetrics "actions" strings from the Chrome source.
9 This program generates the list of known actions we expect to see in the
10 user behavior logs. It walks the Chrome source, looking for calls to
11 UserMetrics functions, extracting actions and warning on improper calls,
12 as well as generating the lists of possible actions in situations where
13 there are many possible actions.
15 See also:
16 content/browser/user_metrics.h
17 http://wiki.corp.google.com/twiki/bin/view/Main/ChromeUserExperienceMetrics
19 If run with a "--hash" argument, chromeactions.txt will be updated.
20 """
22 __author__ = 'evanm (Evan Martin)'
24 import hashlib
25 from HTMLParser import HTMLParser
26 import os
27 import re
28 import sys
30 sys.path.insert(1, os.path.join(sys.path[0], '..', '..', 'python'))
31 from google import path_utils
33 # Files that are known to use content::RecordComputedAction(), which means
34 # they require special handling code in this script.
35 # To add a new file, add it to this list and add the appropriate logic to
36 # generate the known actions to AddComputedActions() below.
37 KNOWN_COMPUTED_USERS = (
38 'back_forward_menu_model.cc',
39 'options_page_view.cc',
40 'render_view_host.cc', # called using webkit identifiers
41 'user_metrics.cc', # method definition
42 'new_tab_ui.cc', # most visited clicks 1-9
43 'extension_metrics_module.cc', # extensions hook for user metrics
44 'safe_browsing_blocking_page.cc', # various interstitial types and actions
45 'language_options_handler_common.cc', # languages and input methods in CrOS
46 'cros_language_options_handler.cc', # languages and input methods in CrOS
47 'about_flags.cc', # do not generate a warning; see AddAboutFlagsActions()
48 'external_metrics.cc', # see AddChromeOSActions()
49 'core_options_handler.cc', # see AddWebUIActions()
50 'browser_render_process_host.cc' # see AddRendererActions()
53 # Language codes used in Chrome. The list should be updated when a new
54 # language is added to app/l10n_util.cc, as follows:
56 # % (cat app/l10n_util.cc | \
57 # perl -n0e 'print $1 if /kAcceptLanguageList.*?\{(.*?)\}/s' | \
58 # perl -nle 'print $1, if /"(.*)"/'; echo 'es-419') | \
59 # sort | perl -pe "s/(.*)\n/'\$1', /" | \
60 # fold -w75 -s | perl -pe 's/^/ /;s/ $//'; echo
62 # The script extracts language codes from kAcceptLanguageList, but es-419
63 # (Spanish in Latin America) is an exception.
64 LANGUAGE_CODES = (
65 'af', 'am', 'ar', 'az', 'be', 'bg', 'bh', 'bn', 'br', 'bs', 'ca', 'co',
66 'cs', 'cy', 'da', 'de', 'de-AT', 'de-CH', 'de-DE', 'el', 'en', 'en-AU',
67 'en-CA', 'en-GB', 'en-NZ', 'en-US', 'en-ZA', 'eo', 'es', 'es-419', 'et',
68 'eu', 'fa', 'fi', 'fil', 'fo', 'fr', 'fr-CA', 'fr-CH', 'fr-FR', 'fy',
69 'ga', 'gd', 'gl', 'gn', 'gu', 'ha', 'haw', 'he', 'hi', 'hr', 'hu', 'hy',
70 'ia', 'id', 'is', 'it', 'it-CH', 'it-IT', 'ja', 'jw', 'ka', 'kk', 'km',
71 'kn', 'ko', 'ku', 'ky', 'la', 'ln', 'lo', 'lt', 'lv', 'mk', 'ml', 'mn',
72 'mo', 'mr', 'ms', 'mt', 'nb', 'ne', 'nl', 'nn', 'no', 'oc', 'om', 'or',
73 'pa', 'pl', 'ps', 'pt', 'pt-BR', 'pt-PT', 'qu', 'rm', 'ro', 'ru', 'sd',
74 'sh', 'si', 'sk', 'sl', 'sn', 'so', 'sq', 'sr', 'st', 'su', 'sv', 'sw',
75 'ta', 'te', 'tg', 'th', 'ti', 'tk', 'to', 'tr', 'tt', 'tw', 'ug', 'uk',
76 'ur', 'uz', 'vi', 'xh', 'yi', 'yo', 'zh', 'zh-CN', 'zh-TW', 'zu',
79 # Input method IDs used in Chrome OS. The list should be updated when a
80 # new input method is added to
81 # chrome/browser/chromeos/input_method/input_methods.txt in the Chrome tree, as
82 # follows:
84 # % sort chrome/browser/chromeos/input_method/input_methods.txt | \
85 # perl -ne "print \"'\$1', \" if /^([^#]+?)\s/" | \
86 # fold -w75 -s | perl -pe 's/^/ /;s/ $//'; echo
88 # The script extracts input method IDs from input_methods.txt.
89 INPUT_METHOD_IDS = (
90 'english-m', 'm17n:am:sera', 'm17n:ar:kbd', 'm17n:bn:itrans',
91 'm17n:fa:isiri', 'm17n:gu:itrans', 'm17n:hi:itrans', 'm17n:kn:itrans',
92 'm17n:ml:itrans', 'm17n:mr:itrans', 'm17n:ta:inscript', 'm17n:ta:itrans',
93 'm17n:ta:phonetic', 'm17n:ta:tamil99', 'm17n:ta:typewriter',
94 'm17n:te:itrans', 'm17n:th:kesmanee', 'm17n:th:pattachote',
95 'm17n:th:tis820', 'm17n:vi:tcvn', 'm17n:vi:telex', 'm17n:vi:viqr',
96 'm17n:vi:vni', 'm17n:zh:cangjie', 'm17n:zh:quick', 'mozc', 'mozc-chewing',
97 'mozc-dv', 'mozc-hangul', 'mozc-jp', 'pinyin', 'pinyin-dv', 'xkb:be::fra',
98 'xkb:be::ger', 'xkb:be::nld', 'xkb:bg::bul', 'xkb:bg:phonetic:bul',
99 'xkb:br::por', 'xkb:ca::fra', 'xkb:ca:eng:eng', 'xkb:ch::ger',
100 'xkb:ch:fr:fra', 'xkb:cz::cze', 'xkb:de::ger', 'xkb:de:neo:ger',
101 'xkb:dk::dan', 'xkb:ee::est', 'xkb:es::spa', 'xkb:es:cat:cat',
102 'xkb:fi::fin', 'xkb:fr::fra', 'xkb:gb:dvorak:eng', 'xkb:gb:extd:eng',
103 'xkb:gr::gre', 'xkb:hr::scr', 'xkb:hu::hun', 'xkb:il::heb', 'xkb:it::ita',
104 'xkb:jp::jpn', 'xkb:kr:kr104:kor', 'xkb:latam::spa', 'xkb:lt::lit',
105 'xkb:lv:apostrophe:lav', 'xkb:no::nob', 'xkb:pl::pol', 'xkb:pt::por',
106 'xkb:ro::rum', 'xkb:rs::srp', 'xkb:ru::rus', 'xkb:ru:phonetic:rus',
107 'xkb:se::swe', 'xkb:si::slv', 'xkb:sk::slo', 'xkb:tr::tur', 'xkb:ua::ukr',
108 'xkb:us::eng', 'xkb:us:altgr-intl:eng', 'xkb:us:colemak:eng',
109 'xkb:us:dvorak:eng', 'xkb:us:intl:eng',
112 # The path to the root of the repository.
113 REPOSITORY_ROOT = os.path.join(path_utils.ScriptDir(), '..', '..', '..')
115 number_of_files_total = 0
118 def AddComputedActions(actions):
119 """Add computed actions to the actions list.
121 Arguments:
122 actions: set of actions to add to.
125 # Actions for back_forward_menu_model.cc.
126 for dir in ('BackMenu_', 'ForwardMenu_'):
127 actions.add(dir + 'ShowFullHistory')
128 actions.add(dir + 'Popup')
129 for i in range(1, 20):
130 actions.add(dir + 'HistoryClick' + str(i))
131 actions.add(dir + 'ChapterClick' + str(i))
133 # Actions for new_tab_ui.cc.
134 for i in range(1, 10):
135 actions.add('MostVisited%d' % i)
137 # Actions for safe_browsing_blocking_page.cc.
138 for interstitial in ('Phishing', 'Malware', 'Multiple'):
139 for action in ('Show', 'Proceed', 'DontProceed', 'ForcedDontProceed'):
140 actions.add('SBInterstitial%s%s' % (interstitial, action))
142 # Actions for language_options_handler.cc (Chrome OS specific).
143 for input_method_id in INPUT_METHOD_IDS:
144 actions.add('LanguageOptions_DisableInputMethod_%s' % input_method_id)
145 actions.add('LanguageOptions_EnableInputMethod_%s' % input_method_id)
146 actions.add('InputMethodOptions_Open_%s' % input_method_id)
147 for language_code in LANGUAGE_CODES:
148 actions.add('LanguageOptions_UiLanguageChange_%s' % language_code)
149 actions.add('LanguageOptions_SpellCheckLanguageChange_%s' % language_code)
151 def AddWebKitEditorActions(actions):
152 """Add editor actions from editor_client_impl.cc.
154 Arguments:
155 actions: set of actions to add to.
157 action_re = re.compile(r'''\{ [\w']+, +\w+, +"(.*)" +\},''')
159 editor_file = os.path.join(REPOSITORY_ROOT, 'webkit', 'api', 'src',
160 'EditorClientImpl.cc')
161 for line in open(editor_file):
162 match = action_re.search(line)
163 if match: # Plain call to RecordAction
164 actions.add(match.group(1))
166 def AddClosedSourceActions(actions):
167 """Add actions that are in code which is not checked out by default
169 Arguments
170 actions: set of actions to add to.
172 actions.add('PDF.PrintPage')
173 actions.add('PDF.FitToHeightButton')
174 actions.add('PDF.FitToWidthButton')
175 actions.add('PDF.LoadFailure')
176 actions.add('PDF.LoadSuccess')
177 actions.add('PDF.PreviewDocumentLoadFailure')
178 actions.add('PDF.ZoomFromBrowser')
179 actions.add('PDF.ZoomOutButton')
180 actions.add('PDF.ZoomInButton')
181 actions.add('PDF_Unsupported_Rights_Management')
182 actions.add('PDF_Unsupported_XFA')
183 actions.add('PDF_Unsupported_3D')
184 actions.add('PDF_Unsupported_Movie')
185 actions.add('PDF_Unsupported_Sound')
186 actions.add('PDF_Unsupported_Screen')
187 actions.add('PDF_Unsupported_Portfolios_Packages')
188 actions.add('PDF_Unsupported_Attachment')
189 actions.add('PDF_Unsupported_Digital_Signature')
190 actions.add('PDF_Unsupported_Shared_Review')
191 actions.add('PDF_Unsupported_Shared_Form')
192 actions.add('PDF_Unsupported_Bookmarks')
194 def AddAndroidActions(actions):
195 """Add actions that are used by Chrome on Android.
197 Arguments
198 actions: set of actions to add to.
200 actions.add('MobileBeamCallbackSuccess')
201 actions.add('MobileBeamInvalidAppState')
202 actions.add('MobileBreakpadUploadAttempt')
203 actions.add('MobileBreakpadUploadFailure')
204 actions.add('MobileBreakpadUploadSuccess')
205 actions.add('MobileContextMenuCopyImageLinkAddress')
206 actions.add('MobileContextMenuCopyLinkAddress')
207 actions.add('MobileContextMenuCopyLinkText')
208 actions.add('MobileContextMenuImage')
209 actions.add('MobileContextMenuLink')
210 actions.add('MobileContextMenuOpenImageInNewTab')
211 actions.add('MobileContextMenuOpenLink')
212 actions.add('MobileContextMenuOpenLinkInIncognito')
213 actions.add('MobileContextMenuOpenLinkInNewTab')
214 actions.add('MobileContextMenuSaveImage')
215 actions.add('MobileContextMenuShareLink')
216 actions.add('MobileContextMenuText')
217 actions.add('MobileContextMenuViewImage')
218 actions.add('MobileFreAttemptSignIn')
219 actions.add('MobileFreSignInSuccessful')
220 actions.add('MobileFreSkipSignIn')
221 actions.add('MobileMenuAddToBookmarks')
222 actions.add('MobileMenuAllBookmarks')
223 actions.add('MobileMenuBack')
224 actions.add('MobileMenuCloseAllTabs')
225 actions.add('MobileMenuCloseTab')
226 actions.add('MobileMenuFeedback')
227 actions.add('MobileMenuFindInPage')
228 actions.add('MobileMenuForward')
229 actions.add('MobileMenuFullscreen')
230 actions.add('MobileMenuNewIncognitoTab')
231 actions.add('MobileMenuNewTab')
232 actions.add('MobileMenuOpenTabs')
233 actions.add('MobileMenuQuit')
234 actions.add('MobileMenuReload')
235 actions.add('MobileMenuSettings')
236 actions.add('MobileMenuShare')
237 actions.add('MobileMenuShow')
238 actions.add('MobileNTPBookmark')
239 actions.add('MobileNTPForeignSession')
240 actions.add('MobileNTPMostVisited')
241 actions.add('MobileNTPSwitchToBookmarks')
242 actions.add('MobileNTPSwitchToIncognito')
243 actions.add('MobileNTPSwitchToMostVisited')
244 actions.add('MobileNTPSwitchToOpenTabs')
245 actions.add('MobileNewTabOpened')
246 actions.add('MobileOmniboxSearch')
247 actions.add('MobileOmniboxVoiceSearch')
248 actions.add('MobilePageLoaded')
249 actions.add('MobilePageLoadedDesktopUserAgent')
250 actions.add('MobilePageLoadedWithKeyboard')
251 actions.add('MobileReceivedExternalIntent')
252 actions.add('MobileRendererCrashed')
253 actions.add('MobileShortcutAllBookmarks')
254 actions.add('MobileShortcutFindInPage')
255 actions.add('MobileShortcutNewIncognitoTab')
256 actions.add('MobileShortcutNewTab')
257 actions.add('MobileSideSwipeFinished')
258 actions.add('MobileStackViewCloseTab')
259 actions.add('MobileStackViewSwipeCloseTab')
260 actions.add('MobileTabClobbered')
261 actions.add('MobileTabClosed')
262 actions.add('MobileTabStripCloseTab')
263 actions.add('MobileTabStripNewTab')
264 actions.add('MobileTabSwitched')
265 actions.add('MobileToolbarBack')
266 actions.add('MobileToolbarForward')
267 actions.add('MobileToolbarNewTab')
268 actions.add('MobileToolbarReload')
269 actions.add('MobileToolbarShowMenu')
270 actions.add('MobileToolbarShowStackView')
271 actions.add('MobileToolbarStackViewNewTab')
272 actions.add('MobileToolbarToggleBookmark')
273 actions.add('SystemBack')
274 actions.add('SystemBackForNavigation')
276 def AddAboutFlagsActions(actions):
277 """This parses the experimental feature flags for UMA actions.
279 Arguments:
280 actions: set of actions to add to.
282 about_flags = os.path.join(REPOSITORY_ROOT, 'chrome', 'browser',
283 'about_flags.cc')
284 flag_name_re = re.compile(r'\s*"([0-9a-zA-Z\-_]+)",\s*// FLAGS:RECORD_UMA')
285 for line in open(about_flags):
286 match = flag_name_re.search(line)
287 if match:
288 actions.add("AboutFlags_" + match.group(1))
289 # If the line contains the marker but was not matched by the regex, put up
290 # an error if the line is not a comment.
291 elif 'FLAGS:RECORD_UMA' in line and line[0:2] != '//':
292 print >>sys.stderr, 'WARNING: This line is marked for recording ' + \
293 'about:flags metrics, but is not in the proper format:\n' + line
295 def AddBookmarkManagerActions(actions):
296 """Add actions that are used by BookmarkManager.
298 Arguments
299 actions: set of actions to add to.
301 actions.add('BookmarkManager_Command_AddPage')
302 actions.add('BookmarkManager_Command_Copy')
303 actions.add('BookmarkManager_Command_Cut')
304 actions.add('BookmarkManager_Command_Delete')
305 actions.add('BookmarkManager_Command_Edit')
306 actions.add('BookmarkManager_Command_Export')
307 actions.add('BookmarkManager_Command_Import')
308 actions.add('BookmarkManager_Command_NewFolder')
309 actions.add('BookmarkManager_Command_OpenIncognito')
310 actions.add('BookmarkManager_Command_OpenInNewTab')
311 actions.add('BookmarkManager_Command_OpenInNewWindow')
312 actions.add('BookmarkManager_Command_OpenInSame')
313 actions.add('BookmarkManager_Command_Paste')
314 actions.add('BookmarkManager_Command_ShowInFolder')
315 actions.add('BookmarkManager_Command_Sort')
316 actions.add('BookmarkManager_Command_UndoDelete')
317 actions.add('BookmarkManager_Command_UndoGlobal')
318 actions.add('BookmarkManager_Command_UndoNone')
320 actions.add('BookmarkManager_NavigateTo_BookmarkBar')
321 actions.add('BookmarkManager_NavigateTo_Mobile')
322 actions.add('BookmarkManager_NavigateTo_Other')
323 actions.add('BookmarkManager_NavigateTo_Recent')
324 actions.add('BookmarkManager_NavigateTo_Search')
325 actions.add('BookmarkManager_NavigateTo_SubFolder')
327 def AddChromeOSActions(actions):
328 """Add actions reported by non-Chrome processes in Chrome OS.
330 Arguments:
331 actions: set of actions to add to.
333 # Actions sent by Chrome OS update engine.
334 actions.add('Updater.ServerCertificateChanged')
335 actions.add('Updater.ServerCertificateFailed')
337 # Actions sent by Chrome OS cryptohome.
338 actions.add('Cryptohome.PKCS11InitFail')
340 def AddExtensionActions(actions):
341 """Add actions reported by extensions via chrome.metricsPrivate API.
343 Arguments:
344 actions: set of actions to add to.
346 # Actions sent by Chrome OS File Browser.
347 actions.add('FileBrowser.CreateNewFolder')
348 actions.add('FileBrowser.PhotoEditor.Edit')
349 actions.add('FileBrowser.PhotoEditor.View')
351 # Actions sent by Google Now client.
352 actions.add('GoogleNow.MessageClicked')
353 actions.add('GoogleNow.ButtonClicked0')
354 actions.add('GoogleNow.ButtonClicked1')
355 actions.add('GoogleNow.Dismissed')
357 def GrepForActions(path, actions):
358 """Grep a source file for calls to UserMetrics functions.
360 Arguments:
361 path: path to the file
362 actions: set of actions to add to
364 global number_of_files_total
365 number_of_files_total = number_of_files_total + 1
366 # we look for the UserMetricsAction structure constructor
367 # this should be on one line
368 action_re = re.compile(r'[^a-zA-Z]UserMetricsAction\("([^"]*)')
369 malformed_action_re = re.compile(r'[^a-zA-Z]UserMetricsAction\([^"]')
370 computed_action_re = re.compile(r'RecordComputedAction')
371 line_number = 0
372 for line in open(path):
373 line_number = line_number + 1
374 match = action_re.search(line)
375 if match: # Plain call to RecordAction
376 actions.add(match.group(1))
377 elif malformed_action_re.search(line):
378 # Warn if this line is using RecordAction incorrectly.
379 print >>sys.stderr, ('WARNING: %s has malformed call to RecordAction'
380 ' at %d' % (path, line_number))
381 elif computed_action_re.search(line):
382 # Warn if this file shouldn't be calling RecordComputedAction.
383 if os.path.basename(path) not in KNOWN_COMPUTED_USERS:
384 print >>sys.stderr, ('WARNING: %s has RecordComputedAction at %d' %
385 (path, line_number))
387 class WebUIActionsParser(HTMLParser):
388 """Parses an HTML file, looking for all tags with a 'metric' attribute.
389 Adds user actions corresponding to any metrics found.
391 Arguments:
392 actions: set of actions to add to
394 def __init__(self, actions):
395 HTMLParser.__init__(self)
396 self.actions = actions
398 def handle_starttag(self, tag, attrs):
399 # We only care to examine tags that have a 'metric' attribute.
400 attrs = dict(attrs)
401 if not 'metric' in attrs:
402 return
404 # Boolean metrics have two corresponding actions. All other metrics have
405 # just one corresponding action. By default, we check the 'dataType'
406 # attribute.
407 is_boolean = ('dataType' in attrs and attrs['dataType'] == 'boolean')
408 if 'type' in attrs and attrs['type'] in ('checkbox', 'radio'):
409 if attrs['type'] == 'checkbox':
410 is_boolean = True
411 else:
412 # Radio buttons are boolean if and only if their values are 'true' or
413 # 'false'.
414 assert(attrs['type'] == 'radio')
415 if 'value' in attrs and attrs['value'] in ['true', 'false']:
416 is_boolean = True
418 if is_boolean:
419 self.actions.add(attrs['metric'] + '_Enable')
420 self.actions.add(attrs['metric'] + '_Disable')
421 else:
422 self.actions.add(attrs['metric'])
424 def GrepForWebUIActions(path, actions):
425 """Grep a WebUI source file for elements with associated metrics.
427 Arguments:
428 path: path to the file
429 actions: set of actions to add to
431 close_called = False
432 try:
433 parser = WebUIActionsParser(actions)
434 parser.feed(open(path).read())
435 # An exception can be thrown by parser.close(), so do it in the try to
436 # ensure the path of the file being parsed gets printed if that happens.
437 close_called = True
438 parser.close()
439 except Exception, e:
440 print "Error encountered for path %s" % path
441 raise e
442 finally:
443 if not close_called:
444 parser.close()
446 def WalkDirectory(root_path, actions, extensions, callback):
447 for path, dirs, files in os.walk(root_path):
448 if '.svn' in dirs:
449 dirs.remove('.svn')
450 if '.git' in dirs:
451 dirs.remove('.git')
452 for file in files:
453 ext = os.path.splitext(file)[1]
454 if ext in extensions:
455 callback(os.path.join(path, file), actions)
457 def GrepForRendererActions(path, actions):
458 """Grep a source file for calls to RenderThread::RecordUserMetrics.
460 Arguments:
461 path: path to the file
462 actions: set of actions to add to
464 # We look for the ViewHostMsg_UserMetricsRecordAction constructor.
465 # This should be on one line.
466 action_re = re.compile(
467 r'[^a-zA-Z]RenderThread::RecordUserMetrics\("([^"]*)')
468 line_number = 0
469 for line in open(path):
470 match = action_re.search(line)
471 if match: # Plain call to RecordAction
472 actions.add(match.group(1))
474 def AddLiteralActions(actions):
475 """Add literal actions specified via calls to UserMetrics functions.
477 Arguments:
478 actions: set of actions to add to.
480 EXTENSIONS = ('.cc', '.mm', '.c', '.m')
482 # Walk the source tree to process all .cc files.
483 chrome_root = os.path.normpath(os.path.join(REPOSITORY_ROOT, 'chrome'))
484 WalkDirectory(chrome_root, actions, EXTENSIONS, GrepForActions)
485 content_root = os.path.normpath(os.path.join(REPOSITORY_ROOT, 'content'))
486 WalkDirectory(content_root, actions, EXTENSIONS, GrepForActions)
487 webkit_root = os.path.normpath(os.path.join(REPOSITORY_ROOT, 'webkit'))
488 WalkDirectory(os.path.join(webkit_root, 'glue'), actions, EXTENSIONS,
489 GrepForActions)
490 WalkDirectory(os.path.join(webkit_root, 'port'), actions, EXTENSIONS,
491 GrepForActions)
493 def AddWebUIActions(actions):
494 """Add user actions defined in WebUI files.
496 Arguments:
497 actions: set of actions to add to.
499 resources_root = os.path.join(REPOSITORY_ROOT, 'chrome', 'browser',
500 'resources')
501 WalkDirectory(resources_root, actions, ('.html'), GrepForWebUIActions)
503 def AddRendererActions(actions):
504 """Add user actions sent via calls to RenderThread::RecordUserMetrics.
506 Arguments:
507 actions: set of actions to add to.
509 EXTENSIONS = ('.cc', '.mm', '.c', '.m')
511 chrome_renderer_root = os.path.join(REPOSITORY_ROOT, 'chrome', 'renderer')
512 content_renderer_root = os.path.join(REPOSITORY_ROOT, 'content', 'renderer')
513 WalkDirectory(chrome_renderer_root, actions, EXTENSIONS,
514 GrepForRendererActions)
515 WalkDirectory(content_renderer_root, actions, EXTENSIONS,
516 GrepForRendererActions)
518 def main(argv):
519 if '--hash' in argv:
520 hash_output = True
521 else:
522 hash_output = False
523 print >>sys.stderr, "WARNING: If you added new UMA tags, you must" + \
524 " use the --hash option to update chromeactions.txt."
525 # if we do a hash output, we want to only append NEW actions, and we know
526 # the file we want to work on
527 actions = set()
529 chromeactions_path = os.path.join(path_utils.ScriptDir(), "chromeactions.txt")
531 if hash_output:
532 f = open(chromeactions_path)
533 for line in f:
534 part = line.rpartition("\t")
535 part = part[2].strip()
536 actions.add(part)
537 f.close()
540 AddComputedActions(actions)
541 # TODO(fmantek): bring back webkit editor actions.
542 # AddWebKitEditorActions(actions)
543 AddAboutFlagsActions(actions)
544 AddWebUIActions(actions)
545 AddRendererActions(actions)
547 AddLiteralActions(actions)
549 # print "Scanned {0} number of files".format(number_of_files_total)
550 # print "Found {0} entries".format(len(actions))
552 AddClosedSourceActions(actions)
553 AddChromeOSActions(actions)
554 AddExtensionActions(actions)
555 AddAndroidActions(actions)
556 AddBookmarkManagerActions(actions)
558 if hash_output:
559 f = open(chromeactions_path, "wb")
562 # Print out the actions as a sorted list.
563 for action in sorted(actions):
564 if hash_output:
565 hash = hashlib.md5()
566 hash.update(action)
567 print >>f, '0x%s\t%s' % (hash.hexdigest()[:16], action)
568 else:
569 print action
571 if hash_output:
572 print "Done. Do not forget to add chromeactions.txt to your changelist"
573 return 0
576 if '__main__' == __name__:
577 sys.exit(main(sys.argv))