chromoting_event.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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
  3. // found in the LICENSE file.
  4. #include "remoting/base/chromoting_event.h"
  5. #include "base/strings/string_util.h"
  6. #include "base/strings/stringize_macros.h"
  7. #include "base/system/sys_info.h"
  8. #include "build/build_config.h"
  9. #include "build/chromeos_buildflags.h"
  10. #include "remoting/base/name_value_map.h"
  11. namespace remoting {
  12. namespace {
  13. const NameMapElement<ChromotingEvent::AuthMethod> kAuthMethodNames[]{
  14. {ChromotingEvent::AuthMethod::PIN, "pin"},
  15. {ChromotingEvent::AuthMethod::ACCESS_CODE, "access-code"},
  16. {ChromotingEvent::AuthMethod::PINLESS, "pinless"},
  17. {ChromotingEvent::AuthMethod::THIRD_PARTY, "third-party"},
  18. };
  19. const NameMapElement<ChromotingEvent::ConnectionError> kConnectionErrorNames[]{
  20. {ChromotingEvent::ConnectionError::NONE, "none"},
  21. {ChromotingEvent::ConnectionError::HOST_OFFLINE, "host-offline"},
  22. {ChromotingEvent::ConnectionError::SESSION_REJECTED, "session-rejected"},
  23. {ChromotingEvent::ConnectionError::INCOMPATIBLE_PROTOCOL,
  24. "incompatible-protocol"},
  25. {ChromotingEvent::ConnectionError::NETWORK_FAILURE, "network-failure"},
  26. {ChromotingEvent::ConnectionError::UNKNOWN_ERROR, "unknown-error"},
  27. {ChromotingEvent::ConnectionError::INVALID_ACCESS_CODE,
  28. "invalid-access-code"},
  29. {ChromotingEvent::ConnectionError::MISSING_PLUGIN, "missing-plugin"},
  30. {ChromotingEvent::ConnectionError::AUTHENTICATION_FAILED,
  31. "authentication-failed"},
  32. {ChromotingEvent::ConnectionError::BAD_VERSION, "bad-version"},
  33. {ChromotingEvent::ConnectionError::HOST_OVERLOAD, "host-overload"},
  34. {ChromotingEvent::ConnectionError::P2P_FAILURE, "p2p-failure"},
  35. {ChromotingEvent::ConnectionError::UNEXPECTED, "unexpected"},
  36. {ChromotingEvent::ConnectionError::CLIENT_SUSPENDED, "client-suspended"},
  37. {ChromotingEvent::ConnectionError::NACL_DISABLED, "nacl-disabled"},
  38. {ChromotingEvent::ConnectionError::MAX_SESSION_LENGTH,
  39. "max-session-length"},
  40. {ChromotingEvent::ConnectionError::HOST_CONFIGURATION_ERROR,
  41. "host-configuration-error"},
  42. {ChromotingEvent::ConnectionError::NACL_PLUGIN_CRASHED,
  43. "nacl-plugin-crashed"},
  44. {ChromotingEvent::ConnectionError::INVALID_ACCOUNT, "invalid-account"},
  45. };
  46. const NameMapElement<ChromotingEvent::ConnectionType> kConnectionTypeNames[]{
  47. {ChromotingEvent::ConnectionType::DIRECT, "direct"},
  48. {ChromotingEvent::ConnectionType::STUN, "stun"},
  49. {ChromotingEvent::ConnectionType::RELAY, "relay"},
  50. };
  51. const NameMapElement<ChromotingEvent::Mode> kModeNames[]{
  52. {ChromotingEvent::Mode::IT2ME, "it2me"},
  53. {ChromotingEvent::Mode::ME2ME, "me2me"},
  54. };
  55. const NameMapElement<ChromotingEvent::Os> kOsNames[] = {
  56. {ChromotingEvent::Os::CHROMOTING_LINUX, "linux"},
  57. {ChromotingEvent::Os::CHROMOTING_CHROMEOS, "chromeos"},
  58. {ChromotingEvent::Os::CHROMOTING_MAC, "mac"},
  59. {ChromotingEvent::Os::CHROMOTING_WINDOWS, "windows"},
  60. {ChromotingEvent::Os::OTHER, "other"},
  61. {ChromotingEvent::Os::CHROMOTING_ANDROID, "android"},
  62. {ChromotingEvent::Os::CHROMOTING_IOS, "ios"},
  63. };
  64. const NameMapElement<ChromotingEvent::SessionState> kSessionStateNames[]{
  65. {ChromotingEvent::SessionState::UNKNOWN, "unknown"},
  66. {ChromotingEvent::SessionState::CREATED, "created"},
  67. {ChromotingEvent::SessionState::BAD_PLUGIN_VERSION, "bad-plugin-version"},
  68. {ChromotingEvent::SessionState::UNKNOWN_PLUGIN_ERROR,
  69. "unknown-plugin-error"},
  70. {ChromotingEvent::SessionState::CONNECTING, "connecting"},
  71. {ChromotingEvent::SessionState::INITIALIZING, "initializing"},
  72. {ChromotingEvent::SessionState::CONNECTED, "connected"},
  73. {ChromotingEvent::SessionState::CLOSED, "closed"},
  74. {ChromotingEvent::SessionState::CONNECTION_FAILED, "connection-failed"},
  75. {ChromotingEvent::SessionState::UNDEFINED, "undefined"},
  76. {ChromotingEvent::SessionState::PLUGIN_DISABLED, "plugin-disabled"},
  77. {ChromotingEvent::SessionState::CONNECTION_DROPPED, "connection-dropped"},
  78. {ChromotingEvent::SessionState::CONNECTION_CANCELED, "connection-canceled"},
  79. {ChromotingEvent::SessionState::AUTHENTICATED, "authenticated"},
  80. {ChromotingEvent::SessionState::STARTED, "started"},
  81. {ChromotingEvent::SessionState::SIGNALING, "signaling"},
  82. {ChromotingEvent::SessionState::CREATING_PLUGIN, "creating-plugin"},
  83. };
  84. } // namespace
  85. const char ChromotingEvent::kAuthMethodKey[] = "auth_method";
  86. const char ChromotingEvent::kCaptureLatencyKey[] = "capture_latency";
  87. const char ChromotingEvent::kConnectionErrorKey[] = "connection_error";
  88. const char ChromotingEvent::kConnectionTypeKey[] = "connection_type";
  89. const char ChromotingEvent::kCpuKey[] = "cpu";
  90. const char ChromotingEvent::kDecodeLatencyKey[] = "decode_latency";
  91. const char ChromotingEvent::kEncodeLatencyKey[] = "encode_latency";
  92. const char ChromotingEvent::kHostOsKey[] = "host_os";
  93. const char ChromotingEvent::kHostOsVersionKey[] = "host_os_version";
  94. const char ChromotingEvent::kHostVersionKey[] = "host_version";
  95. const char ChromotingEvent::kMaxCaptureLatencyKey[] = "max_capture_latency";
  96. const char ChromotingEvent::kMaxDecodeLatencyKey[] = "max_decode_latency";
  97. const char ChromotingEvent::kMaxEncodeLatencyKey[] = "max_encode_latency";
  98. const char ChromotingEvent::kMaxRenderLatencyKey[] = "max_render_latency";
  99. const char ChromotingEvent::kMaxRoundtripLatencyKey[] = "max_roundtrip_latency";
  100. const char ChromotingEvent::kModeKey[] = "mode";
  101. const char ChromotingEvent::kOsKey[] = "os";
  102. const char ChromotingEvent::kOsVersionKey[] = "os_version";
  103. const char ChromotingEvent::kPreviousSessionStateKey[] =
  104. "previous_session_state";
  105. const char ChromotingEvent::kRenderLatencyKey[] = "render_latency";
  106. const char ChromotingEvent::kRoleKey[] = "role";
  107. const char ChromotingEvent::kRoundtripLatencyKey[] = "roundtrip_latency";
  108. const char ChromotingEvent::kSessionDurationKey[] = "session_duration";
  109. const char ChromotingEvent::kSessionEntryPointKey[] = "session_entry_point";
  110. const char ChromotingEvent::kSessionIdKey[] = "session_id";
  111. const char ChromotingEvent::kSessionStateKey[] = "session_state";
  112. const char ChromotingEvent::kSignalStrategyTypeKey[] = "signal_strategy_type";
  113. const char ChromotingEvent::kTypeKey[] = "type";
  114. const char ChromotingEvent::kVideoBandwidthKey[] = "video_bandwidth";
  115. const char ChromotingEvent::kWebAppVersionKey[] = "webapp_version";
  116. ChromotingEvent::ChromotingEvent() : values_map_(new base::DictionaryValue()) {}
  117. ChromotingEvent::ChromotingEvent(Type type) : ChromotingEvent() {
  118. SetEnum(kTypeKey, type);
  119. }
  120. ChromotingEvent::ChromotingEvent(const ChromotingEvent& other) {
  121. send_attempts_ = other.send_attempts_;
  122. values_map_ = other.values_map_->CreateDeepCopy();
  123. }
  124. ChromotingEvent::ChromotingEvent(ChromotingEvent&& other) {
  125. send_attempts_ = other.send_attempts_;
  126. values_map_ = std::move(other.values_map_);
  127. }
  128. ChromotingEvent::~ChromotingEvent() = default;
  129. ChromotingEvent& ChromotingEvent::operator=(const ChromotingEvent& other) {
  130. if (this != &other) {
  131. send_attempts_ = other.send_attempts_;
  132. values_map_ = other.values_map_->CreateDeepCopy();
  133. }
  134. return *this;
  135. }
  136. ChromotingEvent& ChromotingEvent::operator=(ChromotingEvent&& other) {
  137. send_attempts_ = other.send_attempts_;
  138. values_map_ = std::move(other.values_map_);
  139. return *this;
  140. }
  141. void ChromotingEvent::SetString(const std::string& key,
  142. const std::string& value) {
  143. values_map_->SetStringKey(key, value);
  144. }
  145. void ChromotingEvent::SetInteger(const std::string& key, int value) {
  146. values_map_->SetIntKey(key, value);
  147. }
  148. void ChromotingEvent::SetBoolean(const std::string& key, bool value) {
  149. values_map_->SetBoolKey(key, value);
  150. }
  151. void ChromotingEvent::SetDouble(const std::string& key, double value) {
  152. values_map_->SetDoubleKey(key, value);
  153. }
  154. bool ChromotingEvent::IsDataValid() {
  155. const base::Value* auth_method = values_map_->FindKey(kAuthMethodKey);
  156. if (auth_method &&
  157. auth_method->GetInt() == static_cast<int>(AuthMethod::NOT_SET)) {
  158. return false;
  159. }
  160. // TODO(yuweih): We may add other checks.
  161. return true;
  162. }
  163. void ChromotingEvent::AddSystemInfo() {
  164. SetString(kCpuKey, base::SysInfo::OperatingSystemArchitecture());
  165. SetString(kOsVersionKey, base::SysInfo::OperatingSystemVersion());
  166. SetString(kWebAppVersionKey, STRINGIZE(VERSION));
  167. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  168. Os os = Os::CHROMOTING_LINUX;
  169. #elif BUILDFLAG(IS_CHROMEOS_ASH)
  170. Os os = Os::CHROMOTING_CHROMEOS;
  171. #elif BUILDFLAG(IS_IOS)
  172. Os os = Os::CHROMOTING_IOS;
  173. #elif BUILDFLAG(IS_MAC)
  174. Os os = Os::CHROMOTING_MAC;
  175. #elif BUILDFLAG(IS_WIN)
  176. Os os = Os::CHROMOTING_WINDOWS;
  177. #elif BUILDFLAG(IS_ANDROID)
  178. Os os = Os::CHROMOTING_ANDROID;
  179. #else
  180. Os os = Os::OTHER;
  181. #endif
  182. SetEnum(kOsKey, os);
  183. }
  184. void ChromotingEvent::IncrementSendAttempts() {
  185. send_attempts_++;
  186. }
  187. const base::Value* ChromotingEvent::GetValue(const std::string& key) const {
  188. return values_map_->FindKey(key);
  189. }
  190. std::unique_ptr<base::DictionaryValue> ChromotingEvent::CopyDictionaryValue()
  191. const {
  192. return values_map_->CreateDeepCopy();
  193. }
  194. // TODO(rkjnsn): Ideally we'd use the protobuf directly instead of storing
  195. // everything in a DictionaryValue that needs to be converted.
  196. apis::v1::ChromotingEvent ChromotingEvent::CreateProto() const {
  197. apis::v1::ChromotingEvent event_proto;
  198. if (values_map_->FindKey(kAuthMethodKey)) {
  199. event_proto.set_auth_method(
  200. static_cast<apis::v1::ChromotingEvent_AuthMethod>(
  201. values_map_->FindKey(kAuthMethodKey)->GetInt()));
  202. }
  203. if (values_map_->FindKey(kCaptureLatencyKey)) {
  204. event_proto.set_capture_latency(
  205. values_map_->FindKey(kCaptureLatencyKey)->GetDouble());
  206. }
  207. if (values_map_->FindKey(kConnectionErrorKey)) {
  208. event_proto.set_connection_error(
  209. static_cast<apis::v1::ChromotingEvent_ConnectionError>(
  210. values_map_->FindKey(kConnectionErrorKey)->GetInt()));
  211. }
  212. if (values_map_->FindKey(kConnectionTypeKey)) {
  213. event_proto.set_connection_type(
  214. static_cast<apis::v1::ChromotingEvent_ConnectionType>(
  215. values_map_->FindKey(kConnectionTypeKey)->GetInt()));
  216. }
  217. if (values_map_->FindKey(kCpuKey)) {
  218. event_proto.set_cpu(values_map_->FindKey(kCpuKey)->GetString());
  219. }
  220. if (values_map_->FindKey(kDecodeLatencyKey)) {
  221. event_proto.set_decode_latency(
  222. values_map_->FindKey(kDecodeLatencyKey)->GetDouble());
  223. }
  224. if (values_map_->FindKey(kEncodeLatencyKey)) {
  225. event_proto.set_encode_latency(
  226. values_map_->FindKey(kEncodeLatencyKey)->GetDouble());
  227. }
  228. if (values_map_->FindKey(kHostOsKey)) {
  229. event_proto.set_host_os(static_cast<apis::v1::ChromotingEvent_Os>(
  230. values_map_->FindKey(kHostOsKey)->GetInt()));
  231. }
  232. if (values_map_->FindKey(kHostOsVersionKey)) {
  233. event_proto.set_host_os_version(
  234. values_map_->FindKey(kHostOsVersionKey)->GetString());
  235. }
  236. if (values_map_->FindKey(kHostVersionKey)) {
  237. event_proto.set_host_version(
  238. values_map_->FindKey(kHostVersionKey)->GetString());
  239. }
  240. if (values_map_->FindKey(kMaxCaptureLatencyKey)) {
  241. event_proto.set_max_capture_latency(
  242. values_map_->FindKey(kMaxCaptureLatencyKey)->GetDouble());
  243. }
  244. if (values_map_->FindKey(kMaxDecodeLatencyKey)) {
  245. event_proto.set_max_decode_latency(
  246. values_map_->FindKey(kMaxDecodeLatencyKey)->GetDouble());
  247. }
  248. if (values_map_->FindKey(kMaxEncodeLatencyKey)) {
  249. event_proto.set_max_encode_latency(
  250. values_map_->FindKey(kMaxEncodeLatencyKey)->GetDouble());
  251. }
  252. if (values_map_->FindKey(kMaxRenderLatencyKey)) {
  253. event_proto.set_max_render_latency(
  254. values_map_->FindKey(kMaxRenderLatencyKey)->GetDouble());
  255. }
  256. if (values_map_->FindKey(kMaxRoundtripLatencyKey)) {
  257. event_proto.set_max_roundtrip_latency(
  258. values_map_->FindKey(kMaxRoundtripLatencyKey)->GetDouble());
  259. }
  260. if (values_map_->FindKey(kModeKey)) {
  261. event_proto.set_mode(static_cast<apis::v1::ChromotingEvent_Mode>(
  262. values_map_->FindKey(kModeKey)->GetInt()));
  263. }
  264. if (values_map_->FindKey(kOsKey)) {
  265. event_proto.set_os(static_cast<apis::v1::ChromotingEvent_Os>(
  266. values_map_->FindKey(kOsKey)->GetInt()));
  267. }
  268. if (values_map_->FindKey(kOsVersionKey)) {
  269. event_proto.set_os_version(
  270. values_map_->FindKey(kOsVersionKey)->GetString());
  271. }
  272. if (values_map_->FindKey(kPreviousSessionStateKey)) {
  273. event_proto.set_previous_session_state(
  274. static_cast<apis::v1::ChromotingEvent_SessionState>(
  275. values_map_->FindKey(kPreviousSessionStateKey)->GetInt()));
  276. }
  277. if (values_map_->FindKey(kRenderLatencyKey)) {
  278. event_proto.set_render_latency(
  279. values_map_->FindKey(kRenderLatencyKey)->GetDouble());
  280. }
  281. if (values_map_->FindKey(kRoleKey)) {
  282. event_proto.set_role(static_cast<apis::v1::ChromotingEvent_Role>(
  283. values_map_->FindKey(kRoleKey)->GetInt()));
  284. }
  285. if (values_map_->FindKey(kRoundtripLatencyKey)) {
  286. event_proto.set_roundtrip_latency(
  287. values_map_->FindKey(kRoundtripLatencyKey)->GetDouble());
  288. }
  289. if (values_map_->FindKey(kSessionDurationKey)) {
  290. event_proto.set_session_duration(
  291. values_map_->FindKey(kSessionDurationKey)->GetDouble());
  292. }
  293. if (values_map_->FindKey(kSessionEntryPointKey)) {
  294. event_proto.set_session_entry_point(
  295. static_cast<apis::v1::ChromotingEvent_SessionEntryPoint>(
  296. values_map_->FindKey(kSessionEntryPointKey)->GetInt()));
  297. }
  298. if (values_map_->FindKey(kSessionIdKey)) {
  299. event_proto.set_session_id(
  300. values_map_->FindKey(kSessionIdKey)->GetString());
  301. }
  302. if (values_map_->FindKey(kSessionStateKey)) {
  303. event_proto.set_session_state(
  304. static_cast<apis::v1::ChromotingEvent_SessionState>(
  305. values_map_->FindKey(kSessionStateKey)->GetInt()));
  306. }
  307. if (values_map_->FindKey(kSignalStrategyTypeKey)) {
  308. event_proto.set_signal_strategy_type(
  309. static_cast<apis::v1::ChromotingEvent_SignalStrategyType>(
  310. values_map_->FindKey(kSignalStrategyTypeKey)->GetInt()));
  311. }
  312. if (values_map_->FindKey(kTypeKey)) {
  313. event_proto.set_type(static_cast<apis::v1::ChromotingEvent_Type>(
  314. values_map_->FindKey(kTypeKey)->GetInt()));
  315. }
  316. if (values_map_->FindKey(kVideoBandwidthKey)) {
  317. event_proto.set_video_bandwidth(
  318. values_map_->FindKey(kVideoBandwidthKey)->GetDouble());
  319. }
  320. if (values_map_->FindKey(kWebAppVersionKey)) {
  321. event_proto.set_webapp_version(
  322. values_map_->FindKey(kWebAppVersionKey)->GetString());
  323. }
  324. return event_proto;
  325. }
  326. // static
  327. bool ChromotingEvent::IsEndOfSession(SessionState state) {
  328. return state == SessionState::CLOSED ||
  329. state == SessionState::CONNECTION_DROPPED ||
  330. state == SessionState::CONNECTION_FAILED ||
  331. state == SessionState::CONNECTION_CANCELED;
  332. }
  333. // static
  334. ChromotingEvent::Os ChromotingEvent::ParseOsFromString(const std::string& os) {
  335. ChromotingEvent::Os result;
  336. if (!NameToValue(kOsNames, base::ToLowerASCII(os), &result)) {
  337. return Os::OTHER;
  338. }
  339. return result;
  340. }
  341. // static
  342. template <>
  343. const char* ChromotingEvent::EnumToString(AuthMethod value) {
  344. return ValueToName(kAuthMethodNames, value);
  345. }
  346. // static
  347. template <>
  348. const char* ChromotingEvent::EnumToString(ConnectionError value) {
  349. return ValueToName(kConnectionErrorNames, value);
  350. }
  351. // static
  352. template <>
  353. const char* ChromotingEvent::EnumToString(ConnectionType value) {
  354. return ValueToName(kConnectionTypeNames, value);
  355. }
  356. // static
  357. template <>
  358. const char* ChromotingEvent::EnumToString(Mode value) {
  359. return ValueToName(kModeNames, value);
  360. }
  361. // static
  362. template <>
  363. const char* ChromotingEvent::EnumToString(Os value) {
  364. return ValueToName(kOsNames, value);
  365. }
  366. // static
  367. template <>
  368. const char* ChromotingEvent::EnumToString(SessionState value) {
  369. return ValueToName(kSessionStateNames, value);
  370. }
  371. } // namespace remoting