зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1675205 - Report telemetry when load an empty file via a JAR archive r=zbraniecki
This will report when a telemetry even whenever we load an empty file via a JAR channel. It will not catch situations where onStopRequest is called with an error code, or when the listener of the channel does not consume the stream. Differential Revision: https://phabricator.services.mozilla.com/D96412
This commit is contained in:
Родитель
bd132e112d
Коммит
5f2e68c256
|
@ -19,6 +19,8 @@
|
||||||
#include "mozilla/BasePrincipal.h"
|
#include "mozilla/BasePrincipal.h"
|
||||||
#include "mozilla/IntegerPrintfMacros.h"
|
#include "mozilla/IntegerPrintfMacros.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
|
#include "mozilla/Telemetry.h"
|
||||||
|
#include "mozilla/TelemetryComms.h"
|
||||||
#include "private/pprio.h"
|
#include "private/pprio.h"
|
||||||
#include "nsInputStreamPump.h"
|
#include "nsInputStreamPump.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
@ -1023,6 +1025,38 @@ nsJARChannel::OnStartRequest(nsIRequest* req) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void RecordEmptyFileEvent(const nsCString& aFileName) {
|
||||||
|
// Send Telemetry
|
||||||
|
|
||||||
|
// The event can only hold 80 characters.
|
||||||
|
// We only save the file name and path inside the jar.
|
||||||
|
auto findFilenameStart = [](const nsCString& aFileName) -> uint32_t {
|
||||||
|
int32_t pos = aFileName.Find("!/");
|
||||||
|
if (pos == kNotFound) {
|
||||||
|
MOZ_ASSERT(false, "This should not happen");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int32_t from = aFileName.RFindChar('/', pos);
|
||||||
|
if (from == kNotFound) {
|
||||||
|
MOZ_ASSERT(false, "This should not happen");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Skip over the slash
|
||||||
|
from++;
|
||||||
|
return from;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If for some reason we are unable to extract the filename we report the
|
||||||
|
// entire string, or 80 characters of it, to make sure we don't miss any
|
||||||
|
// events.
|
||||||
|
uint32_t from = findFilenameStart(aFileName);
|
||||||
|
|
||||||
|
Telemetry::EventID eventType =
|
||||||
|
Telemetry::EventID::NetworkJarChannel_Nodata_Onstop;
|
||||||
|
Telemetry::RecordEvent(eventType, mozilla::Some(Substring(aFileName, from)),
|
||||||
|
Nothing{});
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsJARChannel::OnStopRequest(nsIRequest* req, nsresult status) {
|
nsJARChannel::OnStopRequest(nsIRequest* req, nsresult status) {
|
||||||
LOG(("nsJARChannel::OnStopRequest [this=%p %s status=%" PRIx32 "]\n", this,
|
LOG(("nsJARChannel::OnStopRequest [this=%p %s status=%" PRIx32 "]\n", this,
|
||||||
|
@ -1031,6 +1065,10 @@ nsJARChannel::OnStopRequest(nsIRequest* req, nsresult status) {
|
||||||
if (NS_SUCCEEDED(mStatus)) mStatus = status;
|
if (NS_SUCCEEDED(mStatus)) mStatus = status;
|
||||||
|
|
||||||
if (mListener) {
|
if (mListener) {
|
||||||
|
if (NS_SUCCEEDED(status) && !mOnDataCalled) {
|
||||||
|
RecordEmptyFileEvent(mSpec);
|
||||||
|
}
|
||||||
|
|
||||||
mListener->OnStopRequest(this, status);
|
mListener->OnStopRequest(this, status);
|
||||||
mListener = nullptr;
|
mListener = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1061,6 +1099,7 @@ nsJARChannel::OnDataAvailable(nsIRequest* req, nsIInputStream* stream,
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
|
mOnDataCalled = true;
|
||||||
rv = mListener->OnDataAvailable(this, stream, offset, count);
|
rv = mListener->OnDataAvailable(this, stream, offset, count);
|
||||||
|
|
||||||
// simply report progress here instead of hooking ourselves up as a
|
// simply report progress here instead of hooking ourselves up as a
|
||||||
|
|
|
@ -69,6 +69,7 @@ class nsJARChannel final : public nsIJARChannel,
|
||||||
|
|
||||||
bool mOpened;
|
bool mOpened;
|
||||||
bool mCanceled;
|
bool mCanceled;
|
||||||
|
bool mOnDataCalled = false;
|
||||||
|
|
||||||
RefPtr<nsJARProtocolHandler> mJarHandler;
|
RefPtr<nsJARProtocolHandler> mJarHandler;
|
||||||
nsCOMPtr<nsIJARURI> mJarURI;
|
nsCOMPtr<nsIJARURI> mJarURI;
|
||||||
|
|
Двоичный файл не отображается.
|
@ -0,0 +1,102 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
|
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
||||||
|
|
||||||
|
const { TelemetryTestUtils } = ChromeUtils.import(
|
||||||
|
"resource://testing-common/TelemetryTestUtils.jsm"
|
||||||
|
);
|
||||||
|
|
||||||
|
const { TelemetryController } = ChromeUtils.import(
|
||||||
|
"resource://gre/modules/TelemetryController.jsm"
|
||||||
|
);
|
||||||
|
|
||||||
|
const nsIBinaryInputStream = Components.Constructor(
|
||||||
|
"@mozilla.org/binaryinputstream;1",
|
||||||
|
"nsIBinaryInputStream",
|
||||||
|
"setInputStream"
|
||||||
|
);
|
||||||
|
|
||||||
|
const fileBase = "test_empty_file.zip";
|
||||||
|
const file = do_get_file("data/" + fileBase);
|
||||||
|
const jarBase = "jar:" + Services.io.newFileURI(file).spec + "!";
|
||||||
|
const tmpDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
|
||||||
|
|
||||||
|
function Listener(callback) {
|
||||||
|
this._callback = callback;
|
||||||
|
}
|
||||||
|
Listener.prototype = {
|
||||||
|
gotStartRequest: false,
|
||||||
|
available: -1,
|
||||||
|
gotStopRequest: false,
|
||||||
|
QueryInterface: ChromeUtils.generateQI(["nsIRequestObserver"]),
|
||||||
|
onDataAvailable(request, stream, offset, count) {
|
||||||
|
try {
|
||||||
|
this.available = stream.available();
|
||||||
|
Assert.equal(this.available, count);
|
||||||
|
// Need to consume stream to avoid assertion
|
||||||
|
new nsIBinaryInputStream(stream).readBytes(count);
|
||||||
|
} catch (ex) {
|
||||||
|
do_throw(ex);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onStartRequest(request) {
|
||||||
|
this.gotStartRequest = true;
|
||||||
|
},
|
||||||
|
onStopRequest(request, status) {
|
||||||
|
this.gotStopRequest = true;
|
||||||
|
Assert.equal(status, 0);
|
||||||
|
if (this._callback) {
|
||||||
|
this._callback.call(null, this);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const TELEMETRY_EVENTS_FILTERS = {
|
||||||
|
category: "network.jar.channel",
|
||||||
|
method: "noData",
|
||||||
|
};
|
||||||
|
|
||||||
|
add_task(async function test_empty_jar_file() {
|
||||||
|
var copy = tmpDir.clone();
|
||||||
|
copy.append("zzdxphd909dbc6r2bxtqss2m000017");
|
||||||
|
copy.append("zzdxphd909dbc6r2bxtqss2m000017");
|
||||||
|
copy.append(fileBase);
|
||||||
|
file.copyTo(copy.parent, copy.leafName);
|
||||||
|
|
||||||
|
var uri = "jar:" + Services.io.newFileURI(copy).spec + "!/test.txt";
|
||||||
|
var chan = NetUtil.newChannel({ uri, loadUsingSystemPrincipal: true });
|
||||||
|
|
||||||
|
Services.telemetry.setEventRecordingEnabled("network.jar.channel", true);
|
||||||
|
Services.telemetry.clearEvents();
|
||||||
|
|
||||||
|
await new Promise(resolve => {
|
||||||
|
chan.asyncOpen(
|
||||||
|
new Listener(function(l) {
|
||||||
|
Assert.ok(chan.contentLength == 0);
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
copy.remove(false);
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
TelemetryTestUtils.assertEvents(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
category: "network.jar.channel",
|
||||||
|
method: "noData",
|
||||||
|
object: "onStop",
|
||||||
|
value: `${fileBase}!/test.txt`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TELEMETRY_EVENTS_FILTERS
|
||||||
|
);
|
||||||
|
});
|
|
@ -17,6 +17,7 @@ support-files =
|
||||||
data/test_crx_dummy.crx
|
data/test_crx_dummy.crx
|
||||||
data/test_umlaute.zip
|
data/test_umlaute.zip
|
||||||
data/uncompressed.zip
|
data/uncompressed.zip
|
||||||
|
data/test_empty_file.zip
|
||||||
|
|
||||||
[test_jarchannel.js]
|
[test_jarchannel.js]
|
||||||
skip-if = os == "mac"
|
skip-if = os == "mac"
|
||||||
|
@ -44,3 +45,4 @@ skip-if = os == "mac"
|
||||||
[test_bug1550815.js]
|
[test_bug1550815.js]
|
||||||
# recovering from SIGBUS is temporarily disabled by bug 1583735
|
# recovering from SIGBUS is temporarily disabled by bug 1583735
|
||||||
skip-if = true
|
skip-if = true
|
||||||
|
[test_empty_jar_telemetry.js]
|
||||||
|
|
|
@ -2085,6 +2085,27 @@ intl.ui.browserLanguage:
|
||||||
record_in_processes: ["main"]
|
record_in_processes: ["main"]
|
||||||
bug_numbers: [1486507, 1553311, 1607501, 1672571]
|
bug_numbers: [1486507, 1553311, 1607501, 1672571]
|
||||||
|
|
||||||
|
network.jar.channel:
|
||||||
|
noData:
|
||||||
|
objects: ["onStop"]
|
||||||
|
bug_numbers:
|
||||||
|
- 1675205
|
||||||
|
description: >
|
||||||
|
This event gets recorded whenever onStopRequest gets called with a
|
||||||
|
success code, but no onDataAvailable calls have been made. This indicates
|
||||||
|
an empty file in the JAR archive.
|
||||||
|
notification_emails:
|
||||||
|
- vgosu@mozilla.com
|
||||||
|
- zbraniecki@mozilla.com
|
||||||
|
release_channel_collection: opt-out
|
||||||
|
products:
|
||||||
|
- firefox
|
||||||
|
expiry_version: "93"
|
||||||
|
record_in_processes:
|
||||||
|
- main
|
||||||
|
extra_keys:
|
||||||
|
spec: The path of the file being loaded.
|
||||||
|
|
||||||
security:
|
security:
|
||||||
evalUsage:
|
evalUsage:
|
||||||
objects: ["systemContext", "parentProcess"]
|
objects: ["systemContext", "parentProcess"]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче