proto/processor: Add typed TrackEvent args for three chrome messages.

Adds protos for Chrome user events, legacy IPCs, and keyed services and
corresponding importer code in TraceProcessor.

Bug: 123864183,130786981
Change-Id: Id97259516a4f9fdbbd47e348ea1884a037f54c46
diff --git a/Android.bp b/Android.bp
index a41c143..b722a95 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3827,6 +3827,9 @@
   name: "perfetto_protos_perfetto_trace_track_event_lite_gen",
   srcs: [
     "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
+    "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
+    "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_user_event.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
@@ -3842,6 +3845,9 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pb.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pb.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pb.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.cc",
@@ -3858,6 +3864,9 @@
   name: "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
   srcs: [
     "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
+    "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
+    "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_user_event.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
@@ -3873,6 +3882,9 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pb.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pb.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pb.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.h",
@@ -3893,6 +3905,9 @@
   name: "perfetto_protos_perfetto_trace_track_event_zero_gen",
   srcs: [
     "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
+    "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
+    "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_user_event.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
@@ -3909,6 +3924,9 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.cc",
@@ -3925,6 +3943,9 @@
   name: "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
   srcs: [
     "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
+    "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
+    "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_user_event.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
@@ -3941,6 +3962,9 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.h",
diff --git a/BUILD b/BUILD
index 30d9281..4d81a97 100644
--- a/BUILD
+++ b/BUILD
@@ -2273,6 +2273,9 @@
     name = "protos_perfetto_trace_track_event_protos",
     srcs = [
         "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
+        "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
+        "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+        "protos/perfetto/trace/track_event/chrome_user_event.proto",
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 1df23ca..43840f0 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -3986,6 +3986,87 @@
 
 // End of protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
 
+// Begin of protos/perfetto/trace/track_event/chrome_keyed_service.proto
+
+// Details about one of Chrome's keyed services associated with the event.
+message ChromeKeyedService {
+  // Name of the service, e.g. "MediaRouter", "PreviewsService", etc. (in
+  // Chrome, these are static strings known at compile time).
+  optional string name = 1;
+}
+
+// End of protos/perfetto/trace/track_event/chrome_keyed_service.proto
+
+// Begin of protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
+
+// Details about a legacy Chrome IPC message that is either sent by the event.
+// TODO(eseckler): Also use this message on the receiving side?
+message ChromeLegacyIpc {
+  enum MessageClass {
+    CLASS_UNSPECIFIED = 0;
+    CLASS_AUTOMATION = 1;
+    CLASS_FRAME = 2;
+    CLASS_PAGE = 3;
+    CLASS_VIEW = 4;
+    CLASS_WIDGET = 5;
+    CLASS_INPUT = 6;
+    CLASS_TEST = 7;
+    CLASS_WORKER = 8;
+    CLASS_NACL = 9;
+    CLASS_GPU_CHANNEL = 10;
+    CLASS_MEDIA = 11;
+    CLASS_PPAPI = 12;
+    CLASS_CHROME = 13;
+    CLASS_DRAG = 14;
+    CLASS_PRINT = 15;
+    CLASS_EXTENSION = 16;
+    CLASS_TEXT_INPUT_CLIENT = 17;
+    CLASS_BLINK_TEST = 18;
+    CLASS_ACCESSIBILITY = 19;
+    CLASS_PRERENDER = 20;
+    CLASS_CHROMOTING = 21;
+    CLASS_BROWSER_PLUGIN = 22;
+    CLASS_ANDROID_WEB_VIEW = 23;
+    CLASS_NACL_HOST = 24;
+    CLASS_ENCRYPTED_MEDIA = 25;
+    CLASS_CAST = 26;
+    CLASS_GIN_JAVA_BRIDGE = 27;
+    CLASS_CHROME_UTILITY_PRINTING = 28;
+    CLASS_OZONE_GPU = 29;
+    CLASS_WEB_TEST = 30;
+    CLASS_NETWORK_HINTS = 31;
+    CLASS_EXTENSIONS_GUEST_VIEW = 32;
+    CLASS_GUEST_VIEW = 33;
+    CLASS_MEDIA_PLAYER_DELEGATE = 34;
+    CLASS_EXTENSION_WORKER = 35;
+    CLASS_SUBRESOURCE_FILTER = 36;
+    CLASS_UNFREEZABLE_FRAME = 37;
+  }
+
+  // Corresponds to the message class type defined in Chrome's IPCMessageStart
+  // enum, e.g. FrameMsgStart,
+  optional MessageClass message_class = 1;
+
+  // Line number of the message definition. See Chrome's IPC_MESSAGE_ID and
+  // IPC_MESSAGE_START macros.
+  optional uint32 message_line = 2;
+}
+
+// End of protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
+
+// Begin of protos/perfetto/trace/track_event/chrome_user_event.proto
+
+// Details about a UI interaction initiated by the user, such as opening or
+// closing a tab or a context menu.
+message ChromeUserEvent {
+  // Name of the action, e.g. "NewTab", "ShowBookmarkManager", etc. (in
+  // Chrome, these are usually static strings known at compile time, or
+  // concatenations of multiple such static strings).
+  optional string action = 1;
+}
+
+// End of protos/perfetto/trace/track_event/chrome_user_event.proto
+
 // Begin of protos/perfetto/trace/track_event/debug_annotation.proto
 
 // Key/value annotations provided in untyped TRACE_EVENT macros. These
@@ -4278,7 +4359,7 @@
 // their default track association) can be emitted as part of a
 // TrackEventDefaults message.
 //
-// Next reserved id: 12 (up to 15). Next id: 25.
+// Next reserved id: 12 (up to 15). Next id: 28.
 message TrackEvent {
   // Names of categories of the event. In the client library, categories are a
   // way to turn groups of individual events on or off.
@@ -4374,6 +4455,9 @@
   optional TaskExecution task_execution = 5;
   optional LogMessage log_message = 21;
   optional ChromeCompositorSchedulerState cc_scheduler_state = 24;
+  optional ChromeUserEvent chrome_user_event = 25;
+  optional ChromeKeyedService chrome_keyed_service = 26;
+  optional ChromeLegacyIpc chrome_legacy_ipc = 27;
   // New argument types go here :)
 
   // ---------------------------------------------------------------------------
diff --git a/protos/perfetto/trace/track_event/BUILD.gn b/protos/perfetto/trace/track_event/BUILD.gn
index afb3630..a897601 100644
--- a/protos/perfetto/trace/track_event/BUILD.gn
+++ b/protos/perfetto/trace/track_event/BUILD.gn
@@ -17,6 +17,9 @@
 perfetto_proto_library("@TYPE@") {
   sources = [
     "chrome_compositor_scheduler_state.proto",
+    "chrome_keyed_service.proto",
+    "chrome_legacy_ipc.proto",
+    "chrome_user_event.proto",
     "debug_annotation.proto",
     "log_message.proto",
     "process_descriptor.proto",
diff --git a/protos/perfetto/trace/track_event/chrome_keyed_service.proto b/protos/perfetto/trace/track_event/chrome_keyed_service.proto
new file mode 100644
index 0000000..95ce21d
--- /dev/null
+++ b/protos/perfetto/trace/track_event/chrome_keyed_service.proto
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+// Details about one of Chrome's keyed services associated with the event.
+message ChromeKeyedService {
+  // Name of the service, e.g. "MediaRouter", "PreviewsService", etc. (in
+  // Chrome, these are static strings known at compile time).
+  optional string name = 1;
+}
diff --git a/protos/perfetto/trace/track_event/chrome_legacy_ipc.proto b/protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
new file mode 100644
index 0000000..df6dcce
--- /dev/null
+++ b/protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+// Details about a legacy Chrome IPC message that is either sent by the event.
+// TODO(eseckler): Also use this message on the receiving side?
+message ChromeLegacyIpc {
+  enum MessageClass {
+    CLASS_UNSPECIFIED = 0;
+    CLASS_AUTOMATION = 1;
+    CLASS_FRAME = 2;
+    CLASS_PAGE = 3;
+    CLASS_VIEW = 4;
+    CLASS_WIDGET = 5;
+    CLASS_INPUT = 6;
+    CLASS_TEST = 7;
+    CLASS_WORKER = 8;
+    CLASS_NACL = 9;
+    CLASS_GPU_CHANNEL = 10;
+    CLASS_MEDIA = 11;
+    CLASS_PPAPI = 12;
+    CLASS_CHROME = 13;
+    CLASS_DRAG = 14;
+    CLASS_PRINT = 15;
+    CLASS_EXTENSION = 16;
+    CLASS_TEXT_INPUT_CLIENT = 17;
+    CLASS_BLINK_TEST = 18;
+    CLASS_ACCESSIBILITY = 19;
+    CLASS_PRERENDER = 20;
+    CLASS_CHROMOTING = 21;
+    CLASS_BROWSER_PLUGIN = 22;
+    CLASS_ANDROID_WEB_VIEW = 23;
+    CLASS_NACL_HOST = 24;
+    CLASS_ENCRYPTED_MEDIA = 25;
+    CLASS_CAST = 26;
+    CLASS_GIN_JAVA_BRIDGE = 27;
+    CLASS_CHROME_UTILITY_PRINTING = 28;
+    CLASS_OZONE_GPU = 29;
+    CLASS_WEB_TEST = 30;
+    CLASS_NETWORK_HINTS = 31;
+    CLASS_EXTENSIONS_GUEST_VIEW = 32;
+    CLASS_GUEST_VIEW = 33;
+    CLASS_MEDIA_PLAYER_DELEGATE = 34;
+    CLASS_EXTENSION_WORKER = 35;
+    CLASS_SUBRESOURCE_FILTER = 36;
+    CLASS_UNFREEZABLE_FRAME = 37;
+  }
+
+  // Corresponds to the message class type defined in Chrome's IPCMessageStart
+  // enum, e.g. FrameMsgStart,
+  optional MessageClass message_class = 1;
+
+  // Line number of the message definition. See Chrome's IPC_MESSAGE_ID and
+  // IPC_MESSAGE_START macros.
+  optional uint32 message_line = 2;
+}
diff --git a/protos/perfetto/trace/track_event/chrome_user_event.proto b/protos/perfetto/trace/track_event/chrome_user_event.proto
new file mode 100644
index 0000000..5ba91d1
--- /dev/null
+++ b/protos/perfetto/trace/track_event/chrome_user_event.proto
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+// Details about a UI interaction initiated by the user, such as opening or
+// closing a tab or a context menu.
+message ChromeUserEvent {
+  // Name of the action, e.g. "NewTab", "ShowBookmarkManager", etc. (in
+  // Chrome, these are usually static strings known at compile time, or
+  // concatenations of multiple such static strings).
+  optional string action = 1;
+}
diff --git a/protos/perfetto/trace/track_event/track_event.proto b/protos/perfetto/trace/track_event/track_event.proto
index b4a20cc..4d8b1fb 100644
--- a/protos/perfetto/trace/track_event/track_event.proto
+++ b/protos/perfetto/trace/track_event/track_event.proto
@@ -21,6 +21,9 @@
 import "protos/perfetto/trace/track_event/log_message.proto";
 import "protos/perfetto/trace/track_event/task_execution.proto";
 import "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto";
+import "protos/perfetto/trace/track_event/chrome_keyed_service.proto";
+import "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto";
+import "protos/perfetto/trace/track_event/chrome_user_event.proto";
 
 package perfetto.protos;
 
@@ -83,7 +86,7 @@
 // their default track association) can be emitted as part of a
 // TrackEventDefaults message.
 //
-// Next reserved id: 12 (up to 15). Next id: 25.
+// Next reserved id: 12 (up to 15). Next id: 28.
 message TrackEvent {
   // Names of categories of the event. In the client library, categories are a
   // way to turn groups of individual events on or off.
@@ -179,6 +182,9 @@
   optional TaskExecution task_execution = 5;
   optional LogMessage log_message = 21;
   optional ChromeCompositorSchedulerState cc_scheduler_state = 24;
+  optional ChromeUserEvent chrome_user_event = 25;
+  optional ChromeKeyedService chrome_keyed_service = 26;
+  optional ChromeLegacyIpc chrome_legacy_ipc = 27;
   // New argument types go here :)
 
   // ---------------------------------------------------------------------------
diff --git a/src/protozero/test/example_proto/test_messages.descriptor.h b/src/protozero/test/example_proto/test_messages.descriptor.h
index 9d0affc..6e0ff15 100644
--- a/src/protozero/test/example_proto/test_messages.descriptor.h
+++ b/src/protozero/test/example_proto/test_messages.descriptor.h
@@ -209,19 +209,19 @@
      0x72, 0x42, 0x61, 0x7a, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x61, 0x72, 0x42,
      0x61, 0x7a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x62, 0x61,
      0x72, 0x42, 0x61, 0x7a, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x6f, 0x6f, 0x4d,
-     0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6d, 0x6f,
+     0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x4d, 0x6f,
      0x6f, 0x4d, 0x6f, 0x6f, 0x12, 0x1e, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x45,
      0x6e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
-     0x52, 0x0a, 0x75, 0x52, 0x4c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x72,
+     0x52, 0x0a, 0x55, 0x52, 0x4c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x72,
      0x12, 0x12, 0x0a, 0x04, 0x58, 0x4d, 0x61, 0x70, 0x18, 0x05, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x04, 0x78, 0x4d, 0x61, 0x70, 0x12, 0x21, 0x0a, 0x0d,
+     0x28, 0x08, 0x52, 0x04, 0x58, 0x4d, 0x61, 0x70, 0x12, 0x21, 0x0a, 0x0d,
      0x55, 0x72, 0x4c, 0x45, 0x5f, 0x6e, 0x63, 0x6f, 0x5f, 0x5f, 0x64, 0x65,
-     0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x72, 0x4c,
+     0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x55, 0x72, 0x4c,
      0x45, 0x4e, 0x63, 0x6f, 0x44, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x09, 0x5f,
      0x5f, 0x62, 0x69, 0x67, 0x42, 0x61, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x07, 0x62, 0x69, 0x67, 0x42, 0x61, 0x6e, 0x67, 0x12,
+     0x28, 0x08, 0x52, 0x07, 0x42, 0x69, 0x67, 0x42, 0x61, 0x6e, 0x67, 0x12,
      0x0e, 0x0a, 0x02, 0x55, 0x32, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52,
-     0x02, 0x75, 0x32, 0x12, 0x1a, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x67, 0x42,
+     0x02, 0x55, 0x32, 0x12, 0x1a, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x67, 0x42,
      0x69, 0x67, 0x5f, 0x5f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
      0x62, 0x61, 0x6e, 0x67, 0x42, 0x69, 0x67, 0x22, 0x8f, 0x01, 0x0a, 0x14,
      0x50, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74,
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index 8c90648..9f0560f 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -28,6 +28,9 @@
 
 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
 #include "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_user_event.pbzero.h"
 #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
 #include "protos/perfetto/trace/track_event/log_message.pbzero.h"
 #include "protos/perfetto/trace/track_event/source_location.pbzero.h"
@@ -133,7 +136,54 @@
           context->storage->InternString("legacy_event.flow_direction")),
       flow_direction_value_in_id_(context->storage->InternString("in")),
       flow_direction_value_out_id_(context->storage->InternString("out")),
-      flow_direction_value_inout_id_(context->storage->InternString("inout")) {}
+      flow_direction_value_inout_id_(context->storage->InternString("inout")),
+      chrome_user_event_action_args_key_id_(
+          context->storage->InternString("user_event.action")),
+      chrome_legacy_ipc_class_args_key_id_(
+          context->storage->InternString("legacy_ipc.class")),
+      chrome_legacy_ipc_line_args_key_id_(
+          context->storage->InternString("legacy_ipc.line")),
+      chrome_keyed_service_name_args_key_id_(
+          context->storage->InternString("keyed_service.name")),
+      chrome_legacy_ipc_class_ids_{
+          {context->storage->InternString("UNSPECIFIED"),
+           context->storage->InternString("AUTOMATION"),
+           context->storage->InternString("FRAME"),
+           context->storage->InternString("PAGE"),
+           context->storage->InternString("VIEW"),
+           context->storage->InternString("WIDGET"),
+           context->storage->InternString("INPUT"),
+           context->storage->InternString("TEST"),
+           context->storage->InternString("WORKER"),
+           context->storage->InternString("NACL"),
+           context->storage->InternString("GPU_CHANNEL"),
+           context->storage->InternString("MEDIA"),
+           context->storage->InternString("PPAPI"),
+           context->storage->InternString("CHROME"),
+           context->storage->InternString("DRAG"),
+           context->storage->InternString("PRINT"),
+           context->storage->InternString("EXTENSION"),
+           context->storage->InternString("TEXT_INPUT_CLIENT"),
+           context->storage->InternString("BLINK_TEST"),
+           context->storage->InternString("ACCESSIBILITY"),
+           context->storage->InternString("PRERENDER"),
+           context->storage->InternString("CHROMOTING"),
+           context->storage->InternString("BROWSER_PLUGIN"),
+           context->storage->InternString("ANDROID_WEB_VIEW"),
+           context->storage->InternString("NACL_HOST"),
+           context->storage->InternString("ENCRYPTED_MEDIA"),
+           context->storage->InternString("CAST"),
+           context->storage->InternString("GIN_JAVA_BRIDGE"),
+           context->storage->InternString("CHROME_UTILITY_PRINTING"),
+           context->storage->InternString("OZONE_GPU"),
+           context->storage->InternString("WEB_TEST"),
+           context->storage->InternString("NETWORK_HINTS"),
+           context->storage->InternString("EXTENSIONS_GUEST_VIEW"),
+           context->storage->InternString("GUEST_VIEW"),
+           context->storage->InternString("MEDIA_PLAYER_DELEGATE"),
+           context->storage->InternString("EXTENSION_WORKER"),
+           context->storage->InternString("SUBRESOURCE_FILTER"),
+           context->storage->InternString("UNFREEZABLE_FRAME")}} {}
 
 void TrackEventParser::ParseTrackEvent(int64_t ts,
                                        int64_t tts,
@@ -410,6 +460,16 @@
       ParseCcScheduler(event.cc_scheduler_state(), sequence_state,
                        sequence_state_generation, args_tracker, row_id);
     }
+    if (event.has_chrome_user_event()) {
+      ParseChromeUserEvent(event.chrome_user_event(), args_tracker, row_id);
+    }
+    if (event.has_chrome_legacy_ipc()) {
+      ParseChromeLegacyIpc(event.chrome_legacy_ipc(), args_tracker, row_id);
+    }
+    if (event.has_chrome_keyed_service()) {
+      ParseChromeKeyedService(event.chrome_keyed_service(), args_tracker,
+                              row_id);
+    }
 
     if (legacy_tid) {
       args_tracker->AddArg(row_id, legacy_event_original_tid_id_,
@@ -998,5 +1058,55 @@
       cc, ".perfetto.protos.ChromeCompositorSchedulerState", row);
 }
 
+void TrackEventParser::ParseChromeUserEvent(
+    protozero::ConstBytes chrome_user_event,
+    ArgsTracker* args_tracker,
+    RowId row) {
+  protos::pbzero::ChromeUserEvent::Decoder event(chrome_user_event.data,
+                                                 chrome_user_event.size);
+  if (event.has_action()) {
+    StringId action_id = context_->storage->InternString(event.action());
+    args_tracker->AddArg(row, chrome_user_event_action_args_key_id_,
+                         chrome_user_event_action_args_key_id_,
+                         Variadic::String(action_id));
+  }
+}
+
+void TrackEventParser::ParseChromeLegacyIpc(
+    protozero::ConstBytes chrome_legacy_ipc,
+    ArgsTracker* args_tracker,
+    RowId row) {
+  protos::pbzero::ChromeLegacyIpc::Decoder event(chrome_legacy_ipc.data,
+                                                 chrome_legacy_ipc.size);
+  if (event.has_message_class()) {
+    size_t message_class_index = static_cast<size_t>(event.message_class());
+    if (message_class_index >= chrome_legacy_ipc_class_ids_.size())
+      message_class_index = 0;
+    args_tracker->AddArg(
+        row, chrome_legacy_ipc_class_args_key_id_,
+        chrome_legacy_ipc_class_args_key_id_,
+        Variadic::String(chrome_legacy_ipc_class_ids_[message_class_index]));
+  }
+  if (event.has_message_line()) {
+    args_tracker->AddArg(row, chrome_legacy_ipc_line_args_key_id_,
+                         chrome_legacy_ipc_line_args_key_id_,
+                         Variadic::Integer(event.message_line()));
+  }
+}
+
+void TrackEventParser::ParseChromeKeyedService(
+    protozero::ConstBytes chrome_keyed_service,
+    ArgsTracker* args_tracker,
+    RowId row) {
+  protos::pbzero::ChromeKeyedService::Decoder event(chrome_keyed_service.data,
+                                                    chrome_keyed_service.size);
+  if (event.has_name()) {
+    StringId action_id = context_->storage->InternString(event.name());
+    args_tracker->AddArg(row, chrome_keyed_service_name_args_key_id_,
+                         chrome_keyed_service_name_args_key_id_,
+                         Variadic::String(action_id));
+  }
+}
+
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_parser.h b/src/trace_processor/importers/proto/track_event_parser.h
index fe809f5..e44b76d 100644
--- a/src/trace_processor/importers/proto/track_event_parser.h
+++ b/src/trace_processor/importers/proto/track_event_parser.h
@@ -80,6 +80,15 @@
                         size_t sequence_state_generation,
                         ArgsTracker*,
                         RowId row);
+  void ParseChromeUserEvent(protozero::ConstBytes chrome_user_event,
+                            ArgsTracker*,
+                            RowId);
+  void ParseChromeLegacyIpc(protozero::ConstBytes chrome_legacy_ipc,
+                            ArgsTracker*,
+                            RowId);
+  void ParseChromeKeyedService(protozero::ConstBytes chrome_keyed_service,
+                               ArgsTracker*,
+                               RowId);
 
  private:
   TraceProcessorContext* context_;
@@ -109,6 +118,12 @@
   const StringId flow_direction_value_in_id_;
   const StringId flow_direction_value_out_id_;
   const StringId flow_direction_value_inout_id_;
+  const StringId chrome_user_event_action_args_key_id_;
+  const StringId chrome_legacy_ipc_class_args_key_id_;
+  const StringId chrome_legacy_ipc_line_args_key_id_;
+  const StringId chrome_keyed_service_name_args_key_id_;
+
+  std::array<StringId, 38> chrome_legacy_ipc_class_ids_;
 };
 
 }  // namespace trace_processor
diff --git a/test/synth_common.py b/test/synth_common.py
index 142e76e..984105b 100644
--- a/test/synth_common.py
+++ b/test/synth_common.py
@@ -296,35 +296,6 @@
       buffer_event.type = event_type
     buffer_event.duration_ns = duration
 
-  def add_thread_track_descriptor(self,
-                                  ps,
-                                  ts,
-                                  uuid,
-                                  pid,
-                                  tid,
-                                  thread_name,
-                                  inc_state_cleared=False):
-    packet = self.add_packet()
-    packet.trusted_packet_sequence_id = ps
-    packet.timestamp = ts
-    if inc_state_cleared:
-      packet.incremental_state_cleared = True
-    track = packet.track_descriptor
-    track.uuid = uuid
-    track.thread.pid = pid
-    track.thread.tid = tid
-    track.thread.thread_name = thread_name
-
-  def add_track_event(self, ps, ts, track_uuid, cat, name, type):
-    packet = self.add_packet()
-    packet.trusted_packet_sequence_id = ps
-    packet.timestamp = ts
-    event = packet.track_event
-    event.track_uuid = track_uuid
-    event.categories.append(cat)
-    event.name = name
-    event.type = type
-
 
 def create_trace():
   parser = argparse.ArgumentParser()
diff --git a/test/trace_processor/index b/test/trace_processor/index
index 9c78fec..4a9db38 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -144,8 +144,10 @@
 heap_graph.textproto heap_graph_reference.sql heap_graph_reference.out
 
 # TrackEvent tests.
-track_event_same_tids.py process_tracking.sql track_event_same_tids_threads.out
-track_event_same_tids.py track_event_slices.sql track_event_same_tids_slices.out
+track_event_same_tids.textproto process_tracking.sql track_event_same_tids_threads.out
+track_event_same_tids.textproto track_event_slices.sql track_event_same_tids_slices.out
+track_event_typed_args.textproto track_event_slices.sql track_event_typed_args_slices.out
+track_event_typed_args.textproto track_event_args.sql track_event_typed_args_args.out
 
 # Parsing of an html file with systrace data inside
 ../data/systrace.html systrace_html.sql systrace_html.out
diff --git a/test/trace_processor/track_event_args.sql b/test/trace_processor/track_event_args.sql
new file mode 100644
index 0000000..49d4b65
--- /dev/null
+++ b/test/trace_processor/track_event_args.sql
@@ -0,0 +1 @@
+select arg_set_id, flat_key, key, int_value, string_value from args where arg_set_id >= 2 order by arg_set_id, key asc;
\ No newline at end of file
diff --git a/test/trace_processor/track_event_same_tids.py b/test/trace_processor/track_event_same_tids.py
deleted file mode 100644
index c838d6d..0000000
--- a/test/trace_processor/track_event_same_tids.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-
-# Chrome renderer processes don't know their "true" tids on some platforms.
-# Instead, they each write tids that start at 1 - which means, the same tids are
-# used in multiple different processes at the same time. This trace replicates
-# such a situation.
-
-trace.add_thread_track_descriptor(
-    ps=1, ts=0, uuid=1, pid=5, tid=1, thread_name="t1", inc_state_cleared=True)
-trace.add_thread_track_descriptor(
-    ps=1, ts=0, uuid=2, pid=10, tid=1, thread_name="t2")
-
-trace.add_track_event(
-    ps=1, ts=1000, track_uuid=1, cat="cat", name="name1", type=3)
-trace.add_track_event(
-    ps=1, ts=2000, track_uuid=2, cat="cat", name="name2", type=3)
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/track_event_same_tids.textproto b/test/trace_processor/track_event_same_tids.textproto
new file mode 100644
index 0000000..d8d7ca2
--- /dev/null
+++ b/test/trace_processor/track_event_same_tids.textproto
@@ -0,0 +1,45 @@
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 1
+    thread {
+      pid: 5
+      tid: 1
+      thread_name: "t1"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  track_descriptor {
+    uuid: 2
+    thread {
+      pid: 10
+      tid: 1
+      thread_name: "t2"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 1000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name1"
+    type: 3
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 2000
+  track_event {
+    track_uuid: 2
+    categories: "cat"
+    name: "name2"
+    type: 3
+  }
+}
diff --git a/test/trace_processor/track_event_same_tids_slices.out b/test/trace_processor/track_event_same_tids_slices.out
index f66b8ce..350acf9 100644
--- a/test/trace_processor/track_event_same_tids_slices.out
+++ b/test/trace_processor/track_event_same_tids_slices.out
@@ -1,3 +1,3 @@
-"ts","dur","category","name"
-1000,0,"cat","name1"
-2000,0,"cat","name2"
+"ts","dur","category","name","arg_set_id"
+1000,0,"cat","name1",0
+2000,0,"cat","name2",0
diff --git a/test/trace_processor/track_event_slices.sql b/test/trace_processor/track_event_slices.sql
index b69c990..bf05ca0 100644
--- a/test/trace_processor/track_event_slices.sql
+++ b/test/trace_processor/track_event_slices.sql
@@ -1 +1 @@
-select ts, dur, category, name from slice order by ts asc;
\ No newline at end of file
+select ts, dur, category, name, arg_set_id from slice order by ts asc;
\ No newline at end of file
diff --git a/test/trace_processor/track_event_typed_args.textproto b/test/trace_processor/track_event_typed_args.textproto
new file mode 100644
index 0000000..3c49c21
--- /dev/null
+++ b/test/trace_processor/track_event_typed_args.textproto
@@ -0,0 +1,53 @@
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 0
+  incremental_state_cleared: true
+  track_descriptor {
+    uuid: 1
+    thread {
+      pid: 5
+      tid: 1
+      thread_name: "t1"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 1000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name1"
+    type: 3
+    chrome_user_event {
+      action: "NewTab"
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 2000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name2"
+    type: 3
+    chrome_legacy_ipc {
+      message_class: 1
+      message_line: 10
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 3000
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    name: "name3"
+    type: 3
+    chrome_keyed_service {
+      name: "MediaRouter"
+    }
+  }
+}
diff --git a/test/trace_processor/track_event_typed_args_args.out b/test/trace_processor/track_event_typed_args_args.out
new file mode 100644
index 0000000..f08c63e
--- /dev/null
+++ b/test/trace_processor/track_event_typed_args_args.out
@@ -0,0 +1,5 @@
+"arg_set_id","flat_key","key","int_value","string_value"
+2,"user_event.action","user_event.action","[NULL]","NewTab"
+3,"legacy_ipc.class","legacy_ipc.class","[NULL]","AUTOMATION"
+3,"legacy_ipc.line","legacy_ipc.line",10,"[NULL]"
+4,"keyed_service.name","keyed_service.name","[NULL]","MediaRouter"
diff --git a/test/trace_processor/track_event_typed_args_slices.out b/test/trace_processor/track_event_typed_args_slices.out
new file mode 100644
index 0000000..d280266
--- /dev/null
+++ b/test/trace_processor/track_event_typed_args_slices.out
@@ -0,0 +1,4 @@
+"ts","dur","category","name","arg_set_id"
+1000,0,"cat","name1",2
+2000,0,"cat","name2",3
+3000,0,"cat","name3",4
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index 3d807c7..52bcf76 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -96,6 +96,9 @@
     'protos/perfetto/trace/trace_packet.proto',
     'protos/perfetto/trace/trace_packet_defaults.proto',
     'protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto',
+    'protos/perfetto/trace/track_event/chrome_keyed_service.proto',
+    'protos/perfetto/trace/track_event/chrome_legacy_ipc.proto',
+    'protos/perfetto/trace/track_event/chrome_user_event.proto',
     'protos/perfetto/trace/track_event/debug_annotation.proto',
     'protos/perfetto/trace/track_event/log_message.proto',
     'protos/perfetto/trace/track_event/process_descriptor.proto',