summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/client/ping.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter/client/ping.cpp')
-rw-r--r--toolkit/crashreporter/client/ping.cpp324
1 files changed, 0 insertions, 324 deletions
diff --git a/toolkit/crashreporter/client/ping.cpp b/toolkit/crashreporter/client/ping.cpp
deleted file mode 100644
index b49211c9c1..0000000000
--- a/toolkit/crashreporter/client/ping.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "crashreporter.h"
-
-#include <cstring>
-#include <ctime>
-#include <string>
-
-#if defined(XP_LINUX)
-# include <fcntl.h>
-# include <unistd.h>
-# include <sys/stat.h>
-#elif defined(XP_MACOSX)
-# include <CoreFoundation/CoreFoundation.h>
-#elif defined(XP_WIN)
-# include <objbase.h>
-#endif
-
-#include "json/json.h"
-
-#include "CrashAnnotations.h"
-
-using std::string;
-
-namespace CrashReporter {
-
-struct UUID {
- uint32_t m0;
- uint16_t m1;
- uint16_t m2;
- uint8_t m3[8];
-};
-
-// Generates an UUID; the code here is mostly copied from nsUUIDGenerator.cpp
-static string GenerateUUID() {
- UUID id = {};
-
-#if defined(XP_WIN) // Windows
- HRESULT hr = CoCreateGuid((GUID*)&id);
- if (FAILED(hr)) {
- return "";
- }
-#elif defined(XP_MACOSX) // MacOS X
- CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
- if (!uuid) {
- return "";
- }
-
- CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
- memcpy(&id, &bytes, sizeof(UUID));
-
- CFRelease(uuid);
-#elif defined(HAVE_ARC4RANDOM_BUF) // Android, BSD, ...
- arc4random_buf(&id, sizeof(UUID));
-#else // Linux
- int fd = open("/dev/urandom", O_RDONLY);
-
- if (fd == -1) {
- return "";
- }
-
- if (read(fd, &id, sizeof(UUID)) != sizeof(UUID)) {
- close(fd);
- return "";
- }
-
- close(fd);
-#endif
-
- /* Put in the version */
- id.m2 &= 0x0fff;
- id.m2 |= 0x4000;
-
- /* Put in the variant */
- id.m3[0] &= 0x3f;
- id.m3[0] |= 0x80;
-
- const char* kUUIDFormatString =
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
- const size_t kUUIDFormatStringLength = 36;
- char str[kUUIDFormatStringLength + 1] = {'\0'};
-
- int num = snprintf(str, kUUIDFormatStringLength + 1, kUUIDFormatString, id.m0,
- id.m1, id.m2, id.m3[0], id.m3[1], id.m3[2], id.m3[3],
- id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
-
- if (num != kUUIDFormatStringLength) {
- return "";
- }
-
- return str;
-}
-
-const char kISO8601Date[] = "%F";
-const char kISO8601DateHours[] = "%FT%H:00:00.000Z";
-
-// Return the current date as a string in the specified format, the following
-// constants are provided:
-// - kISO8601Date, the ISO 8601 date format, YYYY-MM-DD
-// - kISO8601DateHours, the ISO 8601 full date format, YYYY-MM-DDTHH:00:00.000Z
-static string CurrentDate(string format) {
- time_t now;
- time(&now);
- char buf[64]; // This should be plenty
- strftime(buf, sizeof buf, format.c_str(), gmtime(&now));
- return buf;
-}
-
-const char kTelemetryClientId[] = "TelemetryClientId";
-const char kTelemetryUrl[] = "TelemetryServerURL";
-const char kTelemetrySessionId[] = "TelemetrySessionId";
-const int kTelemetryVersion = 4;
-
-// Create the payload.metadata node of the crash ping using fields extracted
-// from the .extra file
-static Json::Value CreateMetadataNode(const Json::Value& aExtra) {
- Json::Value node;
-
- for (Json::ValueConstIterator iter = aExtra.begin(); iter != aExtra.end();
- ++iter) {
- Annotation annotation;
-
- if (AnnotationFromString(annotation, iter.memberName())) {
- if (IsAnnotationAllowedForPing(annotation)) {
- node[iter.memberName()] = *iter;
- }
- }
- }
-
- return node;
-}
-
-// Create the payload node of the crash ping
-static Json::Value CreatePayloadNode(const Json::Value& aExtra,
- const string& aHash,
- const string& aSessionId) {
- Json::Value payload;
-
- payload["sessionId"] = aSessionId;
- payload["version"] = 1;
- payload["crashDate"] = CurrentDate(kISO8601Date);
- payload["crashTime"] = CurrentDate(kISO8601DateHours);
- payload["hasCrashEnvironment"] = true;
- payload["crashId"] = CrashReporter::GetDumpLocalID();
- payload["minidumpSha256Hash"] = aHash;
- payload["processType"] = "main"; // This is always a main crash
- if (aExtra.isMember("StackTraces")) {
- payload["stackTraces"] = aExtra["StackTraces"];
- }
-
- // Assemble the payload metadata
- payload["metadata"] = CreateMetadataNode(aExtra);
-
- return payload;
-}
-
-// Create the application node of the crash ping
-static Json::Value CreateApplicationNode(
- const string& aVendor, const string& aName, const string& aVersion,
- const string& aDisplayVersion, const string& aPlatformVersion,
- const string& aChannel, const string& aBuildId, const string& aArchitecture,
- const string& aXpcomAbi) {
- Json::Value application;
-
- application["vendor"] = aVendor;
- application["name"] = aName;
- application["buildId"] = aBuildId;
- application["displayVersion"] = aDisplayVersion;
- application["platformVersion"] = aPlatformVersion;
- application["version"] = aVersion;
- application["channel"] = aChannel;
- if (!aArchitecture.empty()) {
- application["architecture"] = aArchitecture;
- }
- if (!aXpcomAbi.empty()) {
- application["xpcomAbi"] = aXpcomAbi;
- }
-
- return application;
-}
-
-// Create the root node of the crash ping
-static Json::Value CreateRootNode(
- const Json::Value& aExtra, const string& aUuid, const string& aHash,
- const string& aClientId, const string& aSessionId, const string& aName,
- const string& aVersion, const string& aChannel, const string& aBuildId) {
- Json::Value root;
- root["type"] = "crash"; // This is a crash ping
- root["id"] = aUuid;
- root["version"] = kTelemetryVersion;
- root["creationDate"] = CurrentDate(kISO8601DateHours);
- root["clientId"] = aClientId;
-
- // Parse the telemetry environment
- Json::Value environment;
- Json::Reader reader;
- string architecture;
- string xpcomAbi;
- string displayVersion;
- string platformVersion;
-
- if (reader.parse(aExtra["TelemetryEnvironment"].asString(), environment,
- /* collectComments */ false)) {
- if (environment.isMember("build") && environment["build"].isObject()) {
- Json::Value build = environment["build"];
- if (build.isMember("architecture") && build["architecture"].isString()) {
- architecture = build["architecture"].asString();
- }
- if (build.isMember("xpcomAbi") && build["xpcomAbi"].isString()) {
- xpcomAbi = build["xpcomAbi"].asString();
- }
- if (build.isMember("displayVersion") &&
- build["displayVersion"].isString()) {
- displayVersion = build["displayVersion"].asString();
- }
- if (build.isMember("platformVersion") &&
- build["platformVersion"].isString()) {
- platformVersion = build["platformVersion"].asString();
- }
- }
-
- root["environment"] = environment;
- }
-
- root["payload"] = CreatePayloadNode(aExtra, aHash, aSessionId);
- root["application"] = CreateApplicationNode(
- aExtra["Vendor"].asString(), aName, aVersion, displayVersion,
- platformVersion, aChannel, aBuildId, architecture, xpcomAbi);
-
- return root;
-}
-
-// Generates the URL used to submit the crash ping, see TelemetrySend.sys.mjs
-string GenerateSubmissionUrl(const string& aUrl, const string& aId,
- const string& aName, const string& aVersion,
- const string& aChannel, const string& aBuildId) {
- return aUrl + "/submit/telemetry/" + aId + "/crash/" + aName + "/" +
- aVersion + "/" + aChannel + "/" + aBuildId +
- "?v=" + std::to_string(kTelemetryVersion);
-}
-
-// Write out the ping into the specified file.
-//
-// Returns true if the ping was written out successfully, false otherwise.
-static bool WritePing(const string& aPath, const string& aPing) {
- std::ofstream* f = UIOpenWrite(aPath, std::ios::trunc);
- bool success = false;
-
- if (f->is_open()) {
- *f << aPing;
- f->close();
- success = f->good();
- }
-
- delete f;
- return success;
-}
-
-// Assembles the crash ping using the JSON data extracted from the .extra file
-// and sends it using the crash sender. All the telemetry specific data but the
-// environment will be stripped from the annotations so that it won't be sent
-// together with the crash report.
-//
-// Note that the crash ping sender is invoked in a fire-and-forget way so this
-// won't block waiting for the ping to be delivered.
-//
-// Returns true if the ping was assembled and handed over to the pingsender
-// correctly, also populates the aPingUuid parameter with the ping UUID. Returns
-// false otherwise and leaves the aPingUuid parameter unmodified.
-bool SendCrashPing(Json::Value& aExtra, const string& aHash, string& aPingUuid,
- const string& pingDir) {
- // Remove the telemetry-related data from the crash annotations
- Json::Value value;
- aExtra.removeMember(kTelemetryClientId, &value);
- string clientId = value.asString();
- aExtra.removeMember(kTelemetryUrl, &value);
- string serverUrl = value.asString();
- aExtra.removeMember(kTelemetrySessionId, &value);
- string sessionId = value.asString();
-
- if (clientId.empty() || serverUrl.empty() || sessionId.empty()) {
- return false;
- }
-
- string buildId = aExtra["BuildID"].asString();
- string channel = aExtra["ReleaseChannel"].asString();
- string name = aExtra["ProductName"].asString();
- string version = aExtra["Version"].asString();
- string uuid = GenerateUUID();
- string url =
- GenerateSubmissionUrl(serverUrl, uuid, name, version, channel, buildId);
-
- if (serverUrl.empty() || uuid.empty()) {
- return false;
- }
-
- Json::Value root = CreateRootNode(aExtra, uuid, aHash, clientId, sessionId,
- name, version, channel, buildId);
-
- // Write out the result to the pending pings directory
- Json::StreamWriterBuilder builder;
- builder["indentation"] = "";
- string ping = Json::writeString(builder, root);
- string pingPath = pingDir + UI_DIR_SEPARATOR + uuid + ".json";
-
- if (!WritePing(pingPath, ping)) {
- return false;
- }
-
- // Hand over the ping to the sender
- std::vector<string> args = {url, pingPath};
- if (UIRunProgram(CrashReporter::GetProgramPath(UI_PING_SENDER_FILENAME),
- args)) {
- aPingUuid = uuid;
- return true;
- } else {
- return false;
- }
-}
-
-} // namespace CrashReporter