| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "blimp/common/logging.h" | 5 #include "blimp/common/logging.h" |
| 6 | 6 |
| 7 #include <iostream> | 7 #include <iostream> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> |
| 9 #include <vector> | 10 #include <vector> |
| 10 | 11 |
| 11 #include "base/format_macros.h" | 12 #include "base/format_macros.h" |
| 12 #include "base/json/string_escape.h" | 13 #include "base/json/string_escape.h" |
| 13 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 14 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 15 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
| 17 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
| 18 #include "blimp/common/create_blimp_message.h" | 19 #include "blimp/common/create_blimp_message.h" |
| 19 #include "blimp/common/proto/blimp_message.pb.h" | 20 #include "blimp/common/proto/blimp_message.pb.h" |
| 20 | 21 |
| 21 namespace blimp { | 22 namespace blimp { |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| 24 static base::LazyInstance<BlimpMessageLogger> g_logger = | 25 using LogFields = std::vector<std::pair<std::string, std::string>>; |
| 25 LAZY_INSTANCE_INITIALIZER; | |
| 26 | 26 |
| 27 // The AddField() suite of functions are used to convert KV pairs with | 27 // The AddField() suite of functions are used to convert KV pairs with |
| 28 // arbitrarily typed values into string/string KV pairs for logging. | 28 // arbitrarily typed values into string/string KV pairs for logging. |
| 29 | 29 |
| 30 // Specialization for string values, surrounding them with quotes and escaping | 30 // Specialization for string values, surrounding them with quotes and escaping |
| 31 // characters as necessary. | 31 // characters as necessary. |
| 32 void AddField(const std::string& key, | 32 void AddField(const std::string& key, |
| 33 const std::string& value, | 33 const std::string& value, |
| 34 LogFields* output) { | 34 LogFields* output) { |
| 35 std::string escaped_value; | 35 std::string escaped_value; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 62 // Uses std::to_string() to serialize |value|. | 62 // Uses std::to_string() to serialize |value|. |
| 63 template <typename T> | 63 template <typename T> |
| 64 void AddField(const std::string& key, const T& value, LogFields* output) { | 64 void AddField(const std::string& key, const T& value, LogFields* output) { |
| 65 output->push_back(std::make_pair(key, std::to_string(value))); | 65 output->push_back(std::make_pair(key, std::to_string(value))); |
| 66 } | 66 } |
| 67 | 67 |
| 68 // The following LogExtractor subclasses contain logic for extracting loggable | 68 // The following LogExtractor subclasses contain logic for extracting loggable |
| 69 // fields from BlimpMessages. | 69 // fields from BlimpMessages. |
| 70 | 70 |
| 71 // Logs fields from COMPOSITOR messages. | 71 // Logs fields from COMPOSITOR messages. |
| 72 class CompositorLogExtractor : public LogExtractor { | 72 void ExtractCompositorMessageFields(const BlimpMessage& message, |
| 73 void ExtractFields(const BlimpMessage& message, | 73 LogFields* output) { |
| 74 LogFields* output) const override { | 74 AddField("render_widget_id", message.compositor().render_widget_id(), output); |
| 75 AddField("render_widget_id", message.compositor().render_widget_id(), | 75 } |
| 76 |
| 77 // Logs fields from IME messages. |
| 78 void ExtractImeMessageFields(const BlimpMessage& message, LogFields* output) { |
| 79 AddField("render_widget_id", message.ime().render_widget_id(), output); |
| 80 switch (message.ime().type()) { |
| 81 case ImeMessage::SHOW_IME: |
| 82 AddField("subtype", "SHOW_IME", output); |
| 83 AddField("text_input_type", message.ime().text_input_type(), output); |
| 84 break; |
| 85 case ImeMessage::HIDE_IME: |
| 86 AddField("subtype", "HIDE_IME", output); |
| 87 break; |
| 88 case ImeMessage::SET_TEXT: |
| 89 AddField("subtype", "SET_TEXT", output); |
| 90 AddField("ime_text(length)", message.ime().ime_text().size(), output); |
| 91 break; |
| 92 case ImeMessage::UNKNOWN: |
| 93 AddField("subtype", "UNKNOWN", output); |
| 94 break; |
| 95 } |
| 96 } |
| 97 |
| 98 // Logs fields from INPUT messages. |
| 99 void ExtractInputMessageFields(const BlimpMessage& message, LogFields* output) { |
| 100 AddField("render_widget_id", message.input().render_widget_id(), output); |
| 101 AddField("timestamp_seconds", message.input().timestamp_seconds(), output); |
| 102 switch (message.input().type()) { |
| 103 case InputMessage::Type_GestureScrollBegin: |
| 104 AddField("subtype", "GestureScrollBegin", output); |
| 105 break; |
| 106 case InputMessage::Type_GestureScrollEnd: |
| 107 AddField("subtype", "GestureScrollEnd", output); |
| 108 break; |
| 109 case InputMessage::Type_GestureScrollUpdate: |
| 110 AddField("subtype", "GestureScrollUpdate", output); |
| 111 break; |
| 112 case InputMessage::Type_GestureFlingStart: |
| 113 AddField("subtype", "GestureFlingStart", output); |
| 114 break; |
| 115 case InputMessage::Type_GestureFlingCancel: |
| 116 AddField("subtype", "GestureFlingCancel", output); |
| 117 AddField("prevent_boosting", |
| 118 message.input().gesture_fling_cancel().prevent_boosting(), |
| 119 output); |
| 120 break; |
| 121 case InputMessage::Type_GestureTap: |
| 122 AddField("subtype", "GestureTap", output); |
| 123 break; |
| 124 case InputMessage::Type_GesturePinchBegin: |
| 125 AddField("subtype", "GesturePinchBegin", output); |
| 126 break; |
| 127 case InputMessage::Type_GesturePinchEnd: |
| 128 AddField("subtype", "GesturePinchEnd", output); |
| 129 break; |
| 130 case InputMessage::Type_GesturePinchUpdate: |
| 131 AddField("subtype", "GesturePinchUpdate", output); |
| 132 break; |
| 133 case InputMessage::Type_GestureTapDown: |
| 134 AddField("subtype", "GestureTapDown", output); |
| 135 break; |
| 136 case InputMessage::Type_GestureTapCancel: |
| 137 AddField("subtype", "GestureTapCancel", output); |
| 138 break; |
| 139 case InputMessage::Type_GestureTapUnconfirmed: |
| 140 AddField("subtype", "GestureTapUnconfirmed", output); |
| 141 break; |
| 142 case InputMessage::Type_GestureShowPress: |
| 143 AddField("subtype", "GestureShowPress", output); |
| 144 break; |
| 145 case InputMessage::UNKNOWN: |
| 146 break; |
| 147 } |
| 148 } |
| 149 |
| 150 // Logs fields from NAVIGATION messages. |
| 151 void ExtractNavigationMessageFields(const BlimpMessage& message, |
| 152 LogFields* output) { |
| 153 switch (message.navigation().type()) { |
| 154 case NavigationMessage::NAVIGATION_STATE_CHANGED: |
| 155 AddField("subtype", "NAVIGATION_STATE_CHANGED", output); |
| 156 if (message.navigation().navigation_state_changed().has_url()) { |
| 157 AddField("url", message.navigation().navigation_state_changed().url(), |
| 158 output); |
| 159 } |
| 160 if (message.navigation().navigation_state_changed().has_favicon()) { |
| 161 AddField( |
| 162 "favicon_size", |
| 163 message.navigation().navigation_state_changed().favicon().size(), |
| 164 output); |
| 165 } |
| 166 if (message.navigation().navigation_state_changed().has_title()) { |
| 167 AddField("title", |
| 168 message.navigation().navigation_state_changed().title(), |
| 169 output); |
| 170 } |
| 171 if (message.navigation().navigation_state_changed().has_loading()) { |
| 172 AddField("loading", |
| 173 message.navigation().navigation_state_changed().loading(), |
| 174 output); |
| 175 } |
| 176 break; |
| 177 case NavigationMessage::LOAD_URL: |
| 178 AddField("subtype", "LOAD_URL", output); |
| 179 AddField("url", message.navigation().load_url().url(), output); |
| 180 break; |
| 181 case NavigationMessage::GO_BACK: |
| 182 AddField("subtype", "GO_BACK", output); |
| 183 break; |
| 184 case NavigationMessage::GO_FORWARD: |
| 185 AddField("subtype", "GO_FORWARD", output); |
| 186 break; |
| 187 case NavigationMessage::RELOAD: |
| 188 AddField("subtype", "RELOAD", output); |
| 189 break; |
| 190 case NavigationMessage::UNKNOWN: |
| 191 break; |
| 192 } |
| 193 } |
| 194 |
| 195 // Logs fields from PROTOCOL_CONTROL messages. |
| 196 void ExtractProtocolControlMessageFields(const BlimpMessage& message, |
| 197 LogFields* output) { |
| 198 switch (message.protocol_control().connection_message_case()) { |
| 199 case ProtocolControlMessage::kStartConnection: |
| 200 AddField("subtype", "START_CONNECTION", output); |
| 201 AddField("client_token", |
| 202 message.protocol_control().start_connection().client_token(), |
| 203 output); |
| 204 AddField("protocol_version", |
| 205 message.protocol_control().start_connection().protocol_version(), |
| 206 output); |
| 207 break; |
| 208 case ProtocolControlMessage::kCheckpointAck: |
| 209 AddField("subtype", "CHECKPOINT_ACK", output); |
| 210 AddField("checkpoint_id", |
| 211 message.protocol_control().checkpoint_ack().checkpoint_id(), |
| 212 output); |
| 213 break; |
| 214 case ProtocolControlMessage::kEndConnection: |
| 215 AddField("subtype", "END_CONNECTION", output); |
| 216 switch (message.protocol_control().end_connection().reason()) { |
| 217 case EndConnectionMessage::AUTHENTICATION_FAILED: |
| 218 AddField("reason", "AUTHENTICATION_FAILED", output); |
| 219 break; |
| 220 case EndConnectionMessage::PROTOCOL_MISMATCH: |
| 221 AddField("reason", "PROTOCOL_MISMATCH", output); |
| 222 break; |
| 223 case EndConnectionMessage::UNKNOWN: |
| 224 break; |
| 225 } |
| 226 break; |
| 227 case ProtocolControlMessage::CONNECTION_MESSAGE_NOT_SET: |
| 228 break; |
| 229 } |
| 230 } |
| 231 |
| 232 // Logs fields from RENDER_WIDGET messages. |
| 233 void ExtractRenderWidgetMessageFields(const BlimpMessage& message, |
| 234 LogFields* output) { |
| 235 switch (message.render_widget().type()) { |
| 236 case RenderWidgetMessage::INITIALIZE: |
| 237 AddField("subtype", "INITIALIZE", output); |
| 238 break; |
| 239 case RenderWidgetMessage::CREATED: |
| 240 AddField("subtype", "CREATED", output); |
| 241 break; |
| 242 case RenderWidgetMessage::DELETED: |
| 243 AddField("subtype", "DELETED", output); |
| 244 break; |
| 245 case RenderWidgetMessage::UNKNOWN: |
| 246 break; |
| 247 } |
| 248 AddField("render_widget_id", message.render_widget().render_widget_id(), |
| 249 output); |
| 250 } |
| 251 |
| 252 // Logs fields from SETTINGS messages. |
| 253 void ExtractSettingsMessageFields(const BlimpMessage& message, |
| 254 LogFields* output) { |
| 255 if (message.settings().has_engine_settings()) { |
| 256 const EngineSettingsMessage& engine_settings = |
| 257 message.settings().engine_settings(); |
| 258 AddField("subtype", "ENGINE_SETTINGS", output); |
| 259 AddField("record_whole_document", engine_settings.record_whole_document(), |
| 76 output); | 260 output); |
| 77 } | 261 AddField("client_os_info", engine_settings.client_os_info(), output); |
| 78 }; | 262 } |
| 79 | 263 } |
| 80 // Logs fields from IME messages. | |
| 81 class ImeLogExtractor : public LogExtractor { | |
| 82 void ExtractFields(const BlimpMessage& message, | |
| 83 LogFields* output) const override { | |
| 84 AddField("render_widget_id", message.ime().render_widget_id(), output); | |
| 85 switch (message.ime().type()) { | |
| 86 case ImeMessage::SHOW_IME: | |
| 87 AddField("subtype", "SHOW_IME", output); | |
| 88 AddField("text_input_type", message.ime().text_input_type(), output); | |
| 89 break; | |
| 90 case ImeMessage::HIDE_IME: | |
| 91 AddField("subtype", "HIDE_IME", output); | |
| 92 break; | |
| 93 case ImeMessage::SET_TEXT: | |
| 94 AddField("subtype", "SET_TEXT", output); | |
| 95 AddField("ime_text(length)", message.ime().ime_text().size(), output); | |
| 96 break; | |
| 97 case ImeMessage::UNKNOWN: | |
| 98 AddField("subtype", "UNKNOWN", output); | |
| 99 break; | |
| 100 } | |
| 101 } | |
| 102 }; | |
| 103 | |
| 104 // Logs fields from INPUT messages. | |
| 105 class InputLogExtractor : public LogExtractor { | |
| 106 void ExtractFields(const BlimpMessage& message, | |
| 107 LogFields* output) const override { | |
| 108 AddField("render_widget_id", message.input().render_widget_id(), output); | |
| 109 AddField("timestamp_seconds", message.input().timestamp_seconds(), output); | |
| 110 switch (message.input().type()) { | |
| 111 case InputMessage::Type_GestureScrollBegin: | |
| 112 AddField("subtype", "GestureScrollBegin", output); | |
| 113 break; | |
| 114 case InputMessage::Type_GestureScrollEnd: | |
| 115 AddField("subtype", "GestureScrollEnd", output); | |
| 116 break; | |
| 117 case InputMessage::Type_GestureScrollUpdate: | |
| 118 AddField("subtype", "GestureScrollUpdate", output); | |
| 119 break; | |
| 120 case InputMessage::Type_GestureFlingStart: | |
| 121 AddField("subtype", "GestureFlingStart", output); | |
| 122 break; | |
| 123 case InputMessage::Type_GestureFlingCancel: | |
| 124 AddField("subtype", "GestureFlingCancel", output); | |
| 125 AddField("prevent_boosting", | |
| 126 message.input().gesture_fling_cancel().prevent_boosting(), | |
| 127 output); | |
| 128 break; | |
| 129 case InputMessage::Type_GestureTap: | |
| 130 AddField("subtype", "GestureTap", output); | |
| 131 break; | |
| 132 case InputMessage::Type_GesturePinchBegin: | |
| 133 AddField("subtype", "GesturePinchBegin", output); | |
| 134 break; | |
| 135 case InputMessage::Type_GesturePinchEnd: | |
| 136 AddField("subtype", "GesturePinchEnd", output); | |
| 137 break; | |
| 138 case InputMessage::Type_GesturePinchUpdate: | |
| 139 AddField("subtype", "GesturePinchUpdate", output); | |
| 140 break; | |
| 141 default: // unknown | |
| 142 break; | |
| 143 } | |
| 144 } | |
| 145 }; | |
| 146 | |
| 147 // Logs fields from NAVIGATION messages. | |
| 148 class NavigationLogExtractor : public LogExtractor { | |
| 149 void ExtractFields(const BlimpMessage& message, | |
| 150 LogFields* output) const override { | |
| 151 switch (message.navigation().type()) { | |
| 152 case NavigationMessage::NAVIGATION_STATE_CHANGED: | |
| 153 AddField("subtype", "NAVIGATION_STATE_CHANGED", output); | |
| 154 if (message.navigation().navigation_state_changed().has_url()) { | |
| 155 AddField("url", message.navigation().navigation_state_changed().url(), | |
| 156 output); | |
| 157 } | |
| 158 if (message.navigation().navigation_state_changed().has_favicon()) { | |
| 159 AddField( | |
| 160 "favicon_size", | |
| 161 message.navigation().navigation_state_changed().favicon().size(), | |
| 162 output); | |
| 163 } | |
| 164 if (message.navigation().navigation_state_changed().has_title()) { | |
| 165 AddField("title", | |
| 166 message.navigation().navigation_state_changed().title(), | |
| 167 output); | |
| 168 } | |
| 169 if (message.navigation().navigation_state_changed().has_loading()) { | |
| 170 AddField("loading", | |
| 171 message.navigation().navigation_state_changed().loading(), | |
| 172 output); | |
| 173 } | |
| 174 break; | |
| 175 case NavigationMessage::LOAD_URL: | |
| 176 AddField("subtype", "LOAD_URL", output); | |
| 177 AddField("url", message.navigation().load_url().url(), output); | |
| 178 break; | |
| 179 case NavigationMessage::GO_BACK: | |
| 180 AddField("subtype", "GO_BACK", output); | |
| 181 break; | |
| 182 case NavigationMessage::GO_FORWARD: | |
| 183 AddField("subtype", "GO_FORWARD", output); | |
| 184 break; | |
| 185 case NavigationMessage::RELOAD: | |
| 186 AddField("subtype", "RELOAD", output); | |
| 187 break; | |
| 188 default: | |
| 189 break; | |
| 190 } | |
| 191 } | |
| 192 }; | |
| 193 | |
| 194 // Logs fields from PROTOCOL_CONTROL messages. | |
| 195 class ProtocolControlLogExtractor : public LogExtractor { | |
| 196 void ExtractFields(const BlimpMessage& message, | |
| 197 LogFields* output) const override { | |
| 198 switch (message.protocol_control().connection_message_case()) { | |
| 199 case ProtocolControlMessage::kStartConnection: | |
| 200 AddField("subtype", "START_CONNECTION", output); | |
| 201 AddField("client_token", | |
| 202 message.protocol_control().start_connection().client_token(), | |
| 203 output); | |
| 204 AddField( | |
| 205 "protocol_version", | |
| 206 message.protocol_control().start_connection().protocol_version(), | |
| 207 output); | |
| 208 break; | |
| 209 case ProtocolControlMessage::kCheckpointAck: | |
| 210 AddField("subtype", "CHECKPOINT_ACK", output); | |
| 211 AddField("checkpoint_id", | |
| 212 message.protocol_control().checkpoint_ack().checkpoint_id(), | |
| 213 output); | |
| 214 break; | |
| 215 default: | |
| 216 break; | |
| 217 } | |
| 218 } | |
| 219 }; | |
| 220 | |
| 221 // Logs fields from RENDER_WIDGET messages. | |
| 222 class RenderWidgetLogExtractor : public LogExtractor { | |
| 223 void ExtractFields(const BlimpMessage& message, | |
| 224 LogFields* output) const override { | |
| 225 switch (message.render_widget().type()) { | |
| 226 case RenderWidgetMessage::INITIALIZE: | |
| 227 AddField("subtype", "INITIALIZE", output); | |
| 228 break; | |
| 229 case RenderWidgetMessage::CREATED: | |
| 230 AddField("subtype", "CREATED", output); | |
| 231 break; | |
| 232 case RenderWidgetMessage::DELETED: | |
| 233 AddField("subtype", "DELETED", output); | |
| 234 break; | |
| 235 } | |
| 236 AddField("render_widget_id", message.render_widget().render_widget_id(), | |
| 237 output); | |
| 238 } | |
| 239 }; | |
| 240 | |
| 241 // Logs fields from SETTINGS messages. | |
| 242 class SettingsLogExtractor : public LogExtractor { | |
| 243 void ExtractFields(const BlimpMessage& message, | |
| 244 LogFields* output) const override { | |
| 245 if (message.settings().has_engine_settings()) { | |
| 246 const EngineSettingsMessage& engine_settings = | |
| 247 message.settings().engine_settings(); | |
| 248 AddField("subtype", "ENGINE_SETTINGS", output); | |
| 249 AddField("record_whole_document", engine_settings.record_whole_document(), | |
| 250 output); | |
| 251 AddField("client_os_info", engine_settings.client_os_info(), output); | |
| 252 } | |
| 253 } | |
| 254 }; | |
| 255 | 264 |
| 256 // Logs fields from TAB_CONTROL messages. | 265 // Logs fields from TAB_CONTROL messages. |
| 257 class TabControlLogExtractor : public LogExtractor { | 266 void ExtractTabControlMessageFields(const BlimpMessage& message, |
| 258 void ExtractFields(const BlimpMessage& message, | 267 LogFields* output) { |
| 259 LogFields* output) const override { | 268 switch (message.tab_control().tab_control_case()) { |
| 260 switch (message.tab_control().tab_control_case()) { | 269 case TabControlMessage::kCreateTab: |
| 261 case TabControlMessage::kCreateTab: | 270 AddField("subtype", "CREATE_TAB", output); |
| 262 AddField("subtype", "CREATE_TAB", output); | 271 break; |
| 263 break; | 272 case TabControlMessage::kCloseTab: |
| 264 case TabControlMessage::kCloseTab: | 273 AddField("subtype", "CLOSE_TAB", output); |
| 265 AddField("subtype", "CLOSE_TAB", output); | 274 break; |
| 266 break; | 275 case TabControlMessage::kSize: |
| 267 case TabControlMessage::kSize: | 276 AddField("subtype", "SIZE", output); |
| 268 AddField("subtype", "SIZE", output); | 277 AddField("size", message.tab_control().size(), output); |
| 269 AddField("size", message.tab_control().size(), output); | 278 break; |
| 270 break; | 279 case TabControlMessage::TAB_CONTROL_NOT_SET: |
| 271 default: // unknown | 280 break; |
| 272 break; | 281 } |
| 273 } | 282 } |
| 274 } | |
| 275 }; | |
| 276 | 283 |
| 277 // Logs fields from BLOB_CHANNEL messages. | 284 // Logs fields from BLOB_CHANNEL messages. |
| 278 class BlobChannelLogExtractor : public LogExtractor { | 285 void ExtractBlobChannelMessageFields(const BlimpMessage& message, |
| 279 void ExtractFields(const BlimpMessage& message, | 286 LogFields* output) { |
| 280 LogFields* output) const override { | 287 switch (message.blob_channel().type_case()) { |
| 281 switch (message.blob_channel().type_case()) { | 288 case BlobChannelMessage::TypeCase::kTransferBlob: |
| 282 case BlobChannelMessage::TypeCase::kTransferBlob: | 289 AddField("subtype", "TRANSFER_BLOB", output); |
| 283 AddField("subtype", "TRANSFER_BLOB", output); | 290 AddField("id", |
| 284 AddField("id", | 291 base::HexEncode( |
| 285 base::HexEncode( | 292 message.blob_channel().transfer_blob().blob_id().data(), |
| 286 message.blob_channel().transfer_blob().blob_id().data(), | 293 message.blob_channel().transfer_blob().blob_id().size()), |
| 287 message.blob_channel().transfer_blob().blob_id().size()), | 294 output); |
| 288 output); | 295 AddField("payload_size", |
| 289 AddField("payload_size", | 296 message.blob_channel().transfer_blob().payload().size(), output); |
| 290 message.blob_channel().transfer_blob().payload().size(), | 297 break; |
| 291 output); | 298 case BlobChannelMessage::TypeCase::TYPE_NOT_SET: // unknown |
| 292 break; | 299 break; |
| 293 case BlobChannelMessage::TypeCase::TYPE_NOT_SET: // unknown | 300 } |
| 294 break; | 301 } |
| 295 } | |
| 296 } | |
| 297 }; | |
| 298 | |
| 299 // No fields are extracted from |message|. | |
| 300 class NullLogExtractor : public LogExtractor { | |
| 301 void ExtractFields(const BlimpMessage& message, | |
| 302 LogFields* output) const override {} | |
| 303 }; | |
| 304 | 302 |
| 305 } // namespace | 303 } // namespace |
| 306 | 304 |
| 307 BlimpMessageLogger::BlimpMessageLogger() { | 305 std::ostream& operator<<(std::ostream& out, const BlimpMessage& message) { |
| 308 AddHandler("COMPOSITOR", BlimpMessage::kCompositor, | |
| 309 base::WrapUnique(new CompositorLogExtractor)); | |
| 310 AddHandler("IME", BlimpMessage::kIme, base::WrapUnique(new ImeLogExtractor)); | |
| 311 AddHandler("INPUT", BlimpMessage::kInput, | |
| 312 base::WrapUnique(new InputLogExtractor)); | |
| 313 AddHandler("NAVIGATION", BlimpMessage::kNavigation, | |
| 314 base::WrapUnique(new NavigationLogExtractor)); | |
| 315 AddHandler("PROTOCOL_CONTROL", BlimpMessage::kProtocolControl, | |
| 316 base::WrapUnique(new ProtocolControlLogExtractor)); | |
| 317 AddHandler("RENDER_WIDGET", BlimpMessage::kRenderWidget, | |
| 318 base::WrapUnique(new RenderWidgetLogExtractor)); | |
| 319 AddHandler("SETTINGS", BlimpMessage::kSettings, | |
| 320 base::WrapUnique(new SettingsLogExtractor)); | |
| 321 AddHandler("TAB_CONTROL", BlimpMessage::kTabControl, | |
| 322 base::WrapUnique(new TabControlLogExtractor)); | |
| 323 AddHandler("BLOB_CHANNEL", BlimpMessage::kBlobChannel, | |
| 324 base::WrapUnique(new BlobChannelLogExtractor)); | |
| 325 } | |
| 326 | |
| 327 BlimpMessageLogger::~BlimpMessageLogger() {} | |
| 328 | |
| 329 void BlimpMessageLogger::AddHandler(const std::string& feature_name, | |
| 330 BlimpMessage::FeatureCase feature_case, | |
| 331 std::unique_ptr<LogExtractor> extractor) { | |
| 332 DCHECK(extractors_.find(feature_case) == extractors_.end()); | |
| 333 DCHECK(!feature_name.empty()); | |
| 334 extractors_[feature_case] = make_pair(feature_name, std::move(extractor)); | |
| 335 } | |
| 336 | |
| 337 void BlimpMessageLogger::LogMessageToStream(const BlimpMessage& message, | |
| 338 std::ostream* out) const { | |
| 339 LogFields fields; | 306 LogFields fields; |
| 340 | 307 |
| 341 auto extractor = extractors_.find(message.feature_case()); | 308 switch (message.feature_case()) { |
| 342 if (extractor != extractors_.end()) { | 309 case BlimpMessage::kCompositor: |
| 343 // An extractor is registered for |message|. | 310 AddField("type", "COMPOSITOR", &fields); |
| 344 // Add the human-readable name of |message.type|. | 311 ExtractCompositorMessageFields(message, &fields); |
| 345 fields.push_back(make_pair("type", extractor->second.first)); | 312 break; |
| 346 extractor->second.second->ExtractFields(message, &fields); | 313 case BlimpMessage::kInput: |
| 347 } else { | 314 AddField("type", "INPUT", &fields); |
| 348 // Don't know the human-readable name of |message.type|. | 315 ExtractInputMessageFields(message, &fields); |
| 349 // Just represent it using its numeric form instead. | 316 break; |
| 350 AddField("type", message.feature_case(), &fields); | 317 case BlimpMessage::kNavigation: |
| 318 AddField("type", "NAVIGATION", &fields); |
| 319 ExtractNavigationMessageFields(message, &fields); |
| 320 break; |
| 321 case BlimpMessage::kProtocolControl: |
| 322 AddField("type", "PROTOCOL_CONTROL", &fields); |
| 323 ExtractProtocolControlMessageFields(message, &fields); |
| 324 break; |
| 325 case BlimpMessage::kRenderWidget: |
| 326 AddField("type", "RENDER_WIDGET", &fields); |
| 327 ExtractRenderWidgetMessageFields(message, &fields); |
| 328 break; |
| 329 case BlimpMessage::kSettings: |
| 330 AddField("type", "SETTINGS", &fields); |
| 331 ExtractSettingsMessageFields(message, &fields); |
| 332 break; |
| 333 case BlimpMessage::kTabControl: |
| 334 AddField("type", "TAB_CONTROL", &fields); |
| 335 ExtractTabControlMessageFields(message, &fields); |
| 336 break; |
| 337 case BlimpMessage::kBlobChannel: |
| 338 AddField("type", "BLOB_CHANNEL", &fields); |
| 339 ExtractBlobChannelMessageFields(message, &fields); |
| 340 break; |
| 341 case BlimpMessage::kIme: |
| 342 AddField("type", "IME", &fields); |
| 343 ExtractImeMessageFields(message, &fields); |
| 344 break; |
| 345 case BlimpMessage::FEATURE_NOT_SET: |
| 346 AddField("type", "<UNKNOWN>", &fields); |
| 347 break; |
| 351 } | 348 } |
| 352 | 349 |
| 353 // Append "target_tab_id" (if present) and "byte_size" to the field set. | 350 // Append "target_tab_id" (if present) and "byte_size" to the field set. |
| 354 if (message.has_target_tab_id()) { | 351 if (message.has_target_tab_id()) { |
| 355 AddField("target_tab_id", message.target_tab_id(), &fields); | 352 AddField("target_tab_id", message.target_tab_id(), &fields); |
| 356 } | 353 } |
| 357 AddField("byte_size", message.ByteSize(), &fields); | 354 AddField("byte_size", message.ByteSize(), &fields); |
| 358 | 355 |
| 359 // Format message using the syntax: | 356 // Format message using the syntax: |
| 360 // <BlimpMessage field1=value1 field2="value 2"> | 357 // <BlimpMessage field1=value1 field2="value 2"> |
| 361 *out << "<BlimpMessage "; | 358 out << "<BlimpMessage "; |
| 362 for (size_t i = 0; i < fields.size(); ++i) { | 359 for (size_t i = 0; i < fields.size(); ++i) { |
| 363 *out << fields[i].first << "=" << fields[i].second | 360 out << fields[i].first << "=" << fields[i].second |
| 364 << (i != fields.size() - 1 ? " " : ""); | 361 << (i != fields.size() - 1 ? " " : ""); |
| 365 } | 362 } |
| 366 *out << ">"; | 363 out << ">"; |
| 367 } | |
| 368 | 364 |
| 369 std::ostream& operator<<(std::ostream& out, const BlimpMessage& message) { | |
| 370 g_logger.Get().LogMessageToStream(message, &out); | |
| 371 return out; | 365 return out; |
| 372 } | 366 } |
| 373 | 367 |
| 374 } // namespace blimp | 368 } // namespace blimp |
| OLD | NEW |