зеркало из 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/IntegerPrintfMacros.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/TelemetryComms.h"
|
||||
#include "private/pprio.h"
|
||||
#include "nsInputStreamPump.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
@ -1023,6 +1025,38 @@ nsJARChannel::OnStartRequest(nsIRequest* req) {
|
|||
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
|
||||
nsJARChannel::OnStopRequest(nsIRequest* req, nsresult status) {
|
||||
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 (mListener) {
|
||||
if (NS_SUCCEEDED(status) && !mOnDataCalled) {
|
||||
RecordEmptyFileEvent(mSpec);
|
||||
}
|
||||
|
||||
mListener->OnStopRequest(this, status);
|
||||
mListener = nullptr;
|
||||
}
|
||||
|
@ -1061,6 +1099,7 @@ nsJARChannel::OnDataAvailable(nsIRequest* req, nsIInputStream* stream,
|
|||
|
||||
nsresult rv;
|
||||
|
||||
mOnDataCalled = true;
|
||||
rv = mListener->OnDataAvailable(this, stream, offset, count);
|
||||
|
||||
// simply report progress here instead of hooking ourselves up as a
|
||||
|
|
|
@ -69,6 +69,7 @@ class nsJARChannel final : public nsIJARChannel,
|
|||
|
||||
bool mOpened;
|
||||
bool mCanceled;
|
||||
bool mOnDataCalled = false;
|
||||
|
||||
RefPtr<nsJARProtocolHandler> mJarHandler;
|
||||
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_umlaute.zip
|
||||
data/uncompressed.zip
|
||||
data/test_empty_file.zip
|
||||
|
||||
[test_jarchannel.js]
|
||||
skip-if = os == "mac"
|
||||
|
@ -44,3 +45,4 @@ skip-if = os == "mac"
|
|||
[test_bug1550815.js]
|
||||
# recovering from SIGBUS is temporarily disabled by bug 1583735
|
||||
skip-if = true
|
||||
[test_empty_jar_telemetry.js]
|
||||
|
|
|
@ -2085,6 +2085,27 @@ intl.ui.browserLanguage:
|
|||
record_in_processes: ["main"]
|
||||
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:
|
||||
evalUsage:
|
||||
objects: ["systemContext", "parentProcess"]
|
||||
|
|
Загрузка…
Ссылка в новой задаче