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.
16 base/metrics/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.
22 __author__ = 'evanm (Evan Martin)'
25 from HTMLParser import HTMLParser
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()
51 'render_thread_impl.cc', # impl of RenderThread::RecordComputedAction()
52 'render_process_host_impl.cc', # browser side impl for
53 # RenderThread::RecordComputedAction()
54 'mock_render_thread.cc', # mock of RenderThread::RecordComputedAction()
55 'ppb_pdf_impl.cc', # see AddClosedSourceActions()
56 'pepper_pdf_host.cc', # see AddClosedSourceActions()
57 'key_systems_support_uma.cc', # See AddKeySystemSupportActions()
60 # Language codes used in Chrome. The list should be updated when a new
61 # language is added to app/l10n_util.cc, as follows:
63 # % (cat app/l10n_util.cc | \
64 # perl -n0e 'print $1 if /kAcceptLanguageList.*?\{(.*?)\}/s' | \
65 # perl -nle 'print $1, if /"(.*)"/'; echo 'es-419') | \
66 # sort | perl -pe "s/(.*)\n/'\$1', /" | \
67 # fold -w75 -s | perl -pe 's/^/ /;s/ $//'; echo
69 # The script extracts language codes from kAcceptLanguageList, but es-419
70 # (Spanish in Latin America) is an exception.
72 'af', 'am', 'ar', 'az', 'be', 'bg', 'bh', 'bn', 'br', 'bs', 'ca', 'co',
73 'cs', 'cy', 'da', 'de', 'de-AT', 'de-CH', 'de-DE', 'el', 'en', 'en-AU',
74 'en-CA', 'en-GB', 'en-NZ', 'en-US', 'en-ZA', 'eo', 'es', 'es-419', 'et',
75 'eu', 'fa', 'fi', 'fil', 'fo', 'fr', 'fr-CA', 'fr-CH', 'fr-FR', 'fy',
76 'ga', 'gd', 'gl', 'gn', 'gu', 'ha', 'haw', 'he', 'hi', 'hr', 'hu', 'hy',
77 'ia', 'id', 'is', 'it', 'it-CH', 'it-IT', 'ja', 'jw', 'ka', 'kk', 'km',
78 'kn', 'ko', 'ku', 'ky', 'la', 'ln', 'lo', 'lt', 'lv', 'mk', 'ml', 'mn',
79 'mo', 'mr', 'ms', 'mt', 'nb', 'ne', 'nl', 'nn', 'no', 'oc', 'om', 'or',
80 'pa', 'pl', 'ps', 'pt', 'pt-BR', 'pt-PT', 'qu', 'rm', 'ro', 'ru', 'sd',
81 'sh', 'si', 'sk', 'sl', 'sn', 'so', 'sq', 'sr', 'st', 'su', 'sv', 'sw',
82 'ta', 'te', 'tg', 'th', 'ti', 'tk', 'to', 'tr', 'tt', 'tw', 'ug', 'uk',
83 'ur', 'uz', 'vi', 'xh', 'yi', 'yo', 'zh', 'zh-CN', 'zh-TW', 'zu',
86 # Input method IDs used in Chrome OS. The list should be updated when a
87 # new input method is added to
88 # chromeos/ime/input_methods.txt in the Chrome tree, as
91 # % sort chromeos/ime/input_methods.txt | \
92 # perl -ne "print \"'\$1', \" if /^([^#]+?)\s/" | \
93 # fold -w75 -s | perl -pe 's/^/ /;s/ $//'; echo
95 # The script extracts input method IDs from input_methods.txt.
97 'xkb:am:phonetic:arm', 'xkb:be::fra', 'xkb:be::ger', 'xkb:be::nld',
98 'xkb:bg::bul', 'xkb:bg:phonetic:bul', 'xkb:br::por', 'xkb:by::bel',
99 'xkb:ca::fra', 'xkb:ca:eng:eng', 'xkb:ca:multix:fra', 'xkb:ch::ger',
100 'xkb:ch:fr:fra', 'xkb:cz::cze', 'xkb:cz:qwerty:cze', 'xkb:de::ger',
101 'xkb:de:neo:ger', 'xkb:dk::dan', 'xkb:ee::est', 'xkb:es::spa',
102 'xkb:es:cat:cat', 'xkb:fi::fin', 'xkb:fr::fra', 'xkb:gb:dvorak:eng',
103 'xkb:gb:extd:eng', 'xkb:ge::geo', 'xkb:gr::gre', 'xkb:hr::scr',
104 'xkb:hu::hun', 'xkb:il::heb', 'xkb:is::ice', 'xkb:it::ita', 'xkb:jp::jpn',
105 'xkb:latam::spa', 'xkb:lt::lit', 'xkb:lv:apostrophe:lav', 'xkb:mn::mon',
106 'xkb:no::nob', 'xkb:pl::pol', 'xkb:pt::por', 'xkb:ro::rum', 'xkb:rs::srp',
107 'xkb:ru::rus', 'xkb:ru:phonetic:rus', 'xkb:se::swe', 'xkb:si::slv',
108 'xkb:sk::slo', 'xkb:tr::tur', 'xkb:ua::ukr', 'xkb:us::eng',
109 'xkb:us:altgr-intl:eng', 'xkb:us:colemak:eng', 'xkb:us:dvorak:eng',
113 # The path to the root of the repository.
114 REPOSITORY_ROOT = os.path.join(path_utils.ScriptDir(), '..', '..', '..')
116 number_of_files_total = 0
119 def AddComputedActions(actions):
120 """Add computed actions to the actions list.
123 actions: set of actions to add to.
126 # Actions for back_forward_menu_model.cc.
127 for dir in ('BackMenu_', 'ForwardMenu_'):
128 actions.add(dir + 'ShowFullHistory')
129 actions.add(dir + 'Popup')
130 for i in range(1, 20):
131 actions.add(dir + 'HistoryClick' + str(i))
132 actions.add(dir + 'ChapterClick' + str(i))
134 # Actions for new_tab_ui.cc.
135 for i in range(1, 10):
136 actions.add('MostVisited%d' % i)
138 # Actions for safe_browsing_blocking_page.cc.
139 for interstitial in ('Phishing', 'Malware', 'Multiple'):
140 for action in ('Show', 'Proceed', 'DontProceed', 'ForcedDontProceed'):
141 actions.add('SBInterstitial%s%s' % (interstitial, action))
143 # Actions for language_options_handler.cc (Chrome OS specific).
144 for input_method_id in INPUT_METHOD_IDS:
145 actions.add('LanguageOptions_DisableInputMethod_%s' % input_method_id)
146 actions.add('LanguageOptions_EnableInputMethod_%s' % input_method_id)
147 actions.add('InputMethodOptions_Open_%s' % input_method_id)
148 for language_code in LANGUAGE_CODES:
149 actions.add('LanguageOptions_UiLanguageChange_%s' % language_code)
150 actions.add('LanguageOptions_SpellCheckLanguageChange_%s' % language_code)
152 def AddWebKitEditorActions(actions):
153 """Add editor actions from editor_client_impl.cc.
156 actions: set of actions to add to.
158 action_re = re.compile(r'''\{ [\w']+, +\w+, +"(.*)" +\},''')
160 editor_file = os.path.join(REPOSITORY_ROOT, 'webkit', 'api', 'src',
161 'EditorClientImpl.cc')
162 for line in open(editor_file):
163 match = action_re.search(line)
164 if match: # Plain call to RecordAction
165 actions.add(match.group(1))
167 def AddClosedSourceActions(actions):
168 """Add actions that are in code which is not checked out by default
171 actions: set of actions to add to.
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.PrintButton')
179 actions.add('PDF.PrintPage')
180 actions.add('PDF.SaveButton')
181 actions.add('PDF.ZoomFromBrowser')
182 actions.add('PDF.ZoomInButton')
183 actions.add('PDF.ZoomOutButton')
184 actions.add('PDF_Unsupported_3D')
185 actions.add('PDF_Unsupported_Attachment')
186 actions.add('PDF_Unsupported_Bookmarks')
187 actions.add('PDF_Unsupported_Digital_Signature')
188 actions.add('PDF_Unsupported_Movie')
189 actions.add('PDF_Unsupported_Portfolios_Packages')
190 actions.add('PDF_Unsupported_Rights_Management')
191 actions.add('PDF_Unsupported_Screen')
192 actions.add('PDF_Unsupported_Shared_Form')
193 actions.add('PDF_Unsupported_Shared_Review')
194 actions.add('PDF_Unsupported_Sound')
195 actions.add('PDF_Unsupported_XFA')
197 def AddAndroidActions(actions):
198 """Add actions that are used by Chrome on Android.
201 actions: set of actions to add to.
203 actions.add('Cast_Sender_CastDeviceSelected');
204 actions.add('Cast_Sender_CastEnterFullscreen');
205 actions.add('Cast_Sender_CastMediaType');
206 actions.add('Cast_Sender_CastPlayRequested');
207 actions.add('Cast_Sender_YouTubeDeviceSelected');
208 actions.add('DataReductionProxy_PromoDisplayed');
209 actions.add('DataReductionProxy_PromoLearnMore');
210 actions.add('DataReductionProxy_TurnedOn');
211 actions.add('DataReductionProxy_TurnedOnFromPromo');
212 actions.add('DataReductionProxy_TurnedOff');
213 actions.add('MobileActionBarShown')
214 actions.add('MobileBeamCallbackSuccess')
215 actions.add('MobileBeamInvalidAppState')
216 actions.add('MobileBreakpadUploadAttempt')
217 actions.add('MobileBreakpadUploadFailure')
218 actions.add('MobileBreakpadUploadSuccess')
219 actions.add('MobileContextMenuCopyImageLinkAddress')
220 actions.add('MobileContextMenuCopyLinkAddress')
221 actions.add('MobileContextMenuCopyLinkText')
222 actions.add('MobileContextMenuDownloadImage')
223 actions.add('MobileContextMenuDownloadLink')
224 actions.add('MobileContextMenuDownloadVideo')
225 actions.add('MobileContextMenuImage')
226 actions.add('MobileContextMenuLink')
227 actions.add('MobileContextMenuOpenImageInNewTab')
228 actions.add('MobileContextMenuOpenLink')
229 actions.add('MobileContextMenuOpenLinkInIncognito')
230 actions.add('MobileContextMenuOpenLinkInNewTab')
231 actions.add('MobileContextMenuSaveImage')
232 actions.add('MobileContextMenuSearchByImage')
233 actions.add('MobileContextMenuShareLink')
234 actions.add('MobileContextMenuText')
235 actions.add('MobileContextMenuVideo')
236 actions.add('MobileContextMenuViewImage')
237 actions.add('MobileFirstEditInOmnibox')
238 actions.add('MobileFocusedFakeboxOnNtp')
239 actions.add('MobileFocusedOmniboxNotOnNtp')
240 actions.add('MobileFocusedOmniboxOnNtp')
241 actions.add('MobileFreAttemptSignIn')
242 actions.add('MobileFreSignInSuccessful')
243 actions.add('MobileFreSkipSignIn')
244 actions.add('MobileMenuAddToBookmarks')
245 actions.add('MobileMenuAllBookmarks')
246 actions.add('MobileMenuBack')
247 actions.add('MobileMenuCloseAllTabs')
248 actions.add('MobileMenuCloseTab')
249 actions.add('MobileMenuFeedback')
250 actions.add('MobileMenuFindInPage')
251 actions.add('MobileMenuForward')
252 actions.add('MobileMenuFullscreen')
253 actions.add('MobileMenuNewIncognitoTab')
254 actions.add('MobileMenuNewTab')
255 actions.add('MobileMenuOpenTabs')
256 actions.add('MobileMenuQuit')
257 actions.add('MobileMenuReload')
258 actions.add('MobileMenuSettings')
259 actions.add('MobileMenuShare')
260 actions.add('MobileMenuShow')
261 actions.add('MobileMWSession')
262 actions.add('MobileNTPBookmark')
263 actions.add('MobileNTPForeignSession')
264 actions.add('MobileNTPMostVisited')
265 actions.add('MobileNTPRecentlyClosed')
266 actions.add('MobileNTPSwitchToBookmarks')
267 actions.add('MobileNTPSwitchToIncognito')
268 actions.add('MobileNTPSwitchToMostVisited')
269 actions.add('MobileNTPSwitchToOpenTabs')
270 actions.add('MobileNewTabOpened')
271 actions.add('MobileOmniboxSearch')
272 actions.add('MobileOmniboxVoiceSearch')
273 actions.add('MobileOmniboxRefineSuggestion')
274 actions.add('MobilePageLoaded')
275 actions.add('MobilePageLoadedDesktopUserAgent')
276 actions.add('MobilePageLoadedWithKeyboard')
277 actions.add('MobileReceivedExternalIntent')
278 actions.add('MobileRendererCrashed')
279 actions.add('MobileShortcutAllBookmarks')
280 actions.add('MobileShortcutFindInPage')
281 actions.add('MobileShortcutNewIncognitoTab')
282 actions.add('MobileShortcutNewTab')
283 actions.add('MobileSideSwipeFinished')
284 actions.add('MobileStackViewCloseTab')
285 actions.add('MobileStackViewSwipeCloseTab')
286 actions.add('MobileTabClobbered')
287 actions.add('MobileTabClosed')
288 actions.add('MobileTabStripCloseTab')
289 actions.add('MobileTabStripNewTab')
290 actions.add('MobileTabSwitched')
291 actions.add('MobileToolbarBack')
292 actions.add('MobileToolbarForward')
293 actions.add('MobileToolbarNewTab')
294 actions.add('MobileToolbarReload')
295 actions.add('MobileToolbarShowMenu')
296 actions.add('MobileToolbarShowStackView')
297 actions.add('MobileToolbarStackViewNewTab')
298 actions.add('MobileToolbarToggleBookmark')
299 actions.add('MobileUsingMenuByHwButtonDragging')
300 actions.add('MobileUsingMenuByHwButtonTap')
301 actions.add('MobileUsingMenuBySwButtonDragging')
302 actions.add('MobileUsingMenuBySwButtonTap')
303 actions.add('SystemBack')
304 actions.add('SystemBackForNavigation')
306 def AddAboutFlagsActions(actions):
307 """This parses the experimental feature flags for UMA actions.
310 actions: set of actions to add to.
312 about_flags = os.path.join(REPOSITORY_ROOT, 'chrome', 'browser',
314 flag_name_re = re.compile(r'\s*"([0-9a-zA-Z\-_]+)",\s*// FLAGS:RECORD_UMA')
315 for line in open(about_flags):
316 match = flag_name_re.search(line)
318 actions.add("AboutFlags_" + match.group(1))
319 # If the line contains the marker but was not matched by the regex, put up
320 # an error if the line is not a comment.
321 elif 'FLAGS:RECORD_UMA' in line and line[0:2] != '//':
322 print >>sys.stderr, 'WARNING: This line is marked for recording ' + \
323 'about:flags metrics, but is not in the proper format:\n' + line
325 def AddBookmarkManagerActions(actions):
326 """Add actions that are used by BookmarkManager.
329 actions: set of actions to add to.
331 actions.add('BookmarkManager_Command_AddPage')
332 actions.add('BookmarkManager_Command_Copy')
333 actions.add('BookmarkManager_Command_Cut')
334 actions.add('BookmarkManager_Command_Delete')
335 actions.add('BookmarkManager_Command_Edit')
336 actions.add('BookmarkManager_Command_Export')
337 actions.add('BookmarkManager_Command_Import')
338 actions.add('BookmarkManager_Command_NewFolder')
339 actions.add('BookmarkManager_Command_OpenIncognito')
340 actions.add('BookmarkManager_Command_OpenInNewTab')
341 actions.add('BookmarkManager_Command_OpenInNewWindow')
342 actions.add('BookmarkManager_Command_OpenInSame')
343 actions.add('BookmarkManager_Command_Paste')
344 actions.add('BookmarkManager_Command_ShowInFolder')
345 actions.add('BookmarkManager_Command_Sort')
346 actions.add('BookmarkManager_Command_UndoDelete')
347 actions.add('BookmarkManager_Command_UndoGlobal')
348 actions.add('BookmarkManager_Command_UndoNone')
350 actions.add('BookmarkManager_NavigateTo_BookmarkBar')
351 actions.add('BookmarkManager_NavigateTo_Mobile')
352 actions.add('BookmarkManager_NavigateTo_Other')
353 actions.add('BookmarkManager_NavigateTo_Recent')
354 actions.add('BookmarkManager_NavigateTo_Search')
355 actions.add('BookmarkManager_NavigateTo_SubFolder')
357 def AddChromeOSActions(actions):
358 """Add actions reported by non-Chrome processes in Chrome OS.
361 actions: set of actions to add to.
363 # Actions sent by Chrome OS update engine.
364 actions.add('Updater.ServerCertificateChanged')
365 actions.add('Updater.ServerCertificateFailed')
367 # Actions sent by Chrome OS cryptohome.
368 actions.add('Cryptohome.PKCS11InitFail')
370 def AddExtensionActions(actions):
371 """Add actions reported by extensions via chrome.metricsPrivate API.
374 actions: set of actions to add to.
376 # Actions sent by Chrome OS File Browser.
377 actions.add('FileBrowser.CreateNewFolder')
378 actions.add('FileBrowser.PhotoEditor.Edit')
379 actions.add('FileBrowser.PhotoEditor.View')
380 actions.add('FileBrowser.SuggestApps.ShowDialog')
382 # Actions sent by Google Now client.
383 actions.add('GoogleNow.MessageClicked')
384 actions.add('GoogleNow.ButtonClicked0')
385 actions.add('GoogleNow.ButtonClicked1')
386 actions.add('GoogleNow.Dismissed')
388 # Actions sent by Chrome Connectivity Diagnostics.
389 actions.add('ConnectivityDiagnostics.LaunchSource.OfflineChromeOS')
390 actions.add('ConnectivityDiagnostics.LaunchSource.WebStore')
391 actions.add('ConnectivityDiagnostics.UA.LogsShown')
392 actions.add('ConnectivityDiagnostics.UA.PassingTestsShown')
393 actions.add('ConnectivityDiagnostics.UA.SettingsShown')
394 actions.add('ConnectivityDiagnostics.UA.TestResultExpanded')
395 actions.add('ConnectivityDiagnostics.UA.TestSuiteRun')
397 def GrepForActions(path, actions):
398 """Grep a source file for calls to UserMetrics functions.
401 path: path to the file
402 actions: set of actions to add to
404 global number_of_files_total
405 number_of_files_total = number_of_files_total + 1
406 # we look for the UserMetricsAction structure constructor
407 # this should be on one line
408 action_re = re.compile(r'[^a-zA-Z]UserMetricsAction\("([^"]*)')
409 malformed_action_re = re.compile(r'[^a-zA-Z]UserMetricsAction\([^"]')
410 computed_action_re = re.compile(r'RecordComputedAction')
412 for line in open(path):
413 line_number = line_number + 1
414 match = action_re.search(line)
415 if match: # Plain call to RecordAction
416 actions.add(match.group(1))
417 elif malformed_action_re.search(line):
418 # Warn if this line is using RecordAction incorrectly.
419 print >>sys.stderr, ('WARNING: %s has malformed call to RecordAction'
420 ' at %d' % (path, line_number))
421 elif computed_action_re.search(line):
422 # Warn if this file shouldn't be calling RecordComputedAction.
423 if os.path.basename(path) not in KNOWN_COMPUTED_USERS:
424 print >>sys.stderr, ('WARNING: %s has RecordComputedAction at %d' %
427 class WebUIActionsParser(HTMLParser):
428 """Parses an HTML file, looking for all tags with a 'metric' attribute.
429 Adds user actions corresponding to any metrics found.
432 actions: set of actions to add to
434 def __init__(self, actions):
435 HTMLParser.__init__(self)
436 self.actions = actions
438 def handle_starttag(self, tag, attrs):
439 # We only care to examine tags that have a 'metric' attribute.
441 if not 'metric' in attrs:
444 # Boolean metrics have two corresponding actions. All other metrics have
445 # just one corresponding action. By default, we check the 'dataType'
447 is_boolean = ('dataType' in attrs and attrs['dataType'] == 'boolean')
448 if 'type' in attrs and attrs['type'] in ('checkbox', 'radio'):
449 if attrs['type'] == 'checkbox':
452 # Radio buttons are boolean if and only if their values are 'true' or
454 assert(attrs['type'] == 'radio')
455 if 'value' in attrs and attrs['value'] in ['true', 'false']:
459 self.actions.add(attrs['metric'] + '_Enable')
460 self.actions.add(attrs['metric'] + '_Disable')
462 self.actions.add(attrs['metric'])
464 def GrepForWebUIActions(path, actions):
465 """Grep a WebUI source file for elements with associated metrics.
468 path: path to the file
469 actions: set of actions to add to
473 parser = WebUIActionsParser(actions)
474 parser.feed(open(path).read())
475 # An exception can be thrown by parser.close(), so do it in the try to
476 # ensure the path of the file being parsed gets printed if that happens.
480 print "Error encountered for path %s" % path
486 def WalkDirectory(root_path, actions, extensions, callback):
487 for path, dirs, files in os.walk(root_path):
493 ext = os.path.splitext(file)[1]
494 if ext in extensions:
495 callback(os.path.join(path, file), actions)
497 def AddLiteralActions(actions):
498 """Add literal actions specified via calls to UserMetrics functions.
501 actions: set of actions to add to.
503 EXTENSIONS = ('.cc', '.mm', '.c', '.m')
505 # Walk the source tree to process all .cc files.
506 ash_root = os.path.normpath(os.path.join(REPOSITORY_ROOT, 'ash'))
507 WalkDirectory(ash_root, actions, EXTENSIONS, GrepForActions)
508 chrome_root = os.path.normpath(os.path.join(REPOSITORY_ROOT, 'chrome'))
509 WalkDirectory(chrome_root, actions, EXTENSIONS, GrepForActions)
510 content_root = os.path.normpath(os.path.join(REPOSITORY_ROOT, 'content'))
511 WalkDirectory(content_root, actions, EXTENSIONS, GrepForActions)
512 net_root = os.path.normpath(os.path.join(REPOSITORY_ROOT, 'net'))
513 WalkDirectory(net_root, actions, EXTENSIONS, GrepForActions)
514 webkit_root = os.path.normpath(os.path.join(REPOSITORY_ROOT, 'webkit'))
515 WalkDirectory(os.path.join(webkit_root, 'glue'), actions, EXTENSIONS,
517 WalkDirectory(os.path.join(webkit_root, 'port'), actions, EXTENSIONS,
520 def AddWebUIActions(actions):
521 """Add user actions defined in WebUI files.
524 actions: set of actions to add to.
526 resources_root = os.path.join(REPOSITORY_ROOT, 'chrome', 'browser',
528 WalkDirectory(resources_root, actions, ('.html'), GrepForWebUIActions)
530 def AddHistoryPageActions(actions):
531 """Add actions that are used in History page.
534 actions: set of actions to add to.
536 actions.add('HistoryPage_BookmarkStarClicked')
537 actions.add('HistoryPage_EntryMenuRemoveFromHistory')
538 actions.add('HistoryPage_EntryLinkClick')
539 actions.add('HistoryPage_EntryLinkRightClick')
540 actions.add('HistoryPage_SearchResultClick')
541 actions.add('HistoryPage_EntryMenuShowMoreFromSite')
542 actions.add('HistoryPage_NewestHistoryClick')
543 actions.add('HistoryPage_NewerHistoryClick')
544 actions.add('HistoryPage_OlderHistoryClick')
545 actions.add('HistoryPage_Search')
546 actions.add('HistoryPage_InitClearBrowsingData')
547 actions.add('HistoryPage_RemoveSelected')
548 actions.add('HistoryPage_SearchResultRemove')
549 actions.add('HistoryPage_ConfirmRemoveSelected')
550 actions.add('HistoryPage_CancelRemoveSelected')
552 def AddKeySystemSupportActions(actions):
553 """Add actions that are used for key system support metrics.
556 actions: set of actions to add to.
558 actions.add('KeySystemSupport.Widevine.Queried')
559 actions.add('KeySystemSupport.WidevineWithType.Queried')
560 actions.add('KeySystemSupport.Widevine.Supported')
561 actions.add('KeySystemSupport.WidevineWithType.Supported')
563 def AddAutomaticResetBannerActions(actions):
564 """Add actions that are used for the automatic profile settings reset banners
565 in chrome://settings.
568 actions: set of actions to add to.
570 # These actions relate to the the automatic settings reset banner shown as
571 # a result of the reset prompt.
572 actions.add('AutomaticReset_WebUIBanner_BannerShown')
573 actions.add('AutomaticReset_WebUIBanner_ManuallyClosed')
574 actions.add('AutomaticReset_WebUIBanner_ResetClicked')
576 # These actions relate to the the automatic settings reset banner shown as
577 # a result of settings hardening.
578 actions.add('AutomaticSettingsReset_WebUIBanner_BannerShown')
579 actions.add('AutomaticSettingsReset_WebUIBanner_ManuallyClosed')
580 actions.add('AutomaticSettingsReset_WebUIBanner_LearnMoreClicked')
587 print >>sys.stderr, "WARNING: If you added new UMA tags, you must" + \
588 " use the --hash option to update chromeactions.txt."
589 # if we do a hash output, we want to only append NEW actions, and we know
590 # the file we want to work on
593 chromeactions_path = os.path.join(path_utils.ScriptDir(), "chromeactions.txt")
596 f = open(chromeactions_path)
598 part = line.rpartition("\t")
599 part = part[2].strip()
604 AddComputedActions(actions)
605 # TODO(fmantek): bring back webkit editor actions.
606 # AddWebKitEditorActions(actions)
607 AddAboutFlagsActions(actions)
608 AddWebUIActions(actions)
610 AddLiteralActions(actions)
612 # print "Scanned {0} number of files".format(number_of_files_total)
613 # print "Found {0} entries".format(len(actions))
615 AddAndroidActions(actions)
616 AddAutomaticResetBannerActions(actions)
617 AddBookmarkManagerActions(actions)
618 AddChromeOSActions(actions)
619 AddClosedSourceActions(actions)
620 AddExtensionActions(actions)
621 AddHistoryPageActions(actions)
622 AddKeySystemSupportActions(actions)
625 f = open(chromeactions_path, "wb")
628 # Print out the actions as a sorted list.
629 for action in sorted(actions):
633 print >>f, '0x%s\t%s' % (hash.hexdigest()[:16], action)
638 print "Done. Do not forget to add chromeactions.txt to your changelist"
642 if '__main__' == __name__:
643 sys.exit(main(sys.argv))