Bug 1790375 - [bidi] Implement network.fetchError event r=webdriver-reviewers,whimboo

Implements https://w3c.github.io/webdriver-bidi/#event-network-fetchError

Differential Revision: https://phabricator.services.mozilla.com/D197586
This commit is contained in:
Julian Descottes 2024-01-11 15:49:30 +00:00
Родитель 80bf1f4d65
Коммит b06a1d4e19
3 изменённых файлов: 113 добавлений и 3 удалений

Просмотреть файл

@ -214,7 +214,11 @@ export class NetworkEventRecord {
},
};
this.#emitResponseCompleted();
if (responseInfo.blockedReason) {
this.#emitFetchError();
} else {
this.#emitResponseCompleted();
}
}
/**
@ -275,8 +279,8 @@ export class NetworkEventRecord {
authCallbacks,
contextId: this.#contextId,
isNavigationRequest: this.#isMainDocumentChannel,
requestChannel: this.#requestChannel,
redirectCount: this.#redirectCount,
requestChannel: this.#requestChannel,
requestData: this.#requestData,
responseChannel: this.#responseChannel,
responseData: this.#responseData,
@ -290,8 +294,23 @@ export class NetworkEventRecord {
this.#networkListener.emit("before-request-sent", {
contextId: this.#contextId,
isNavigationRequest: this.#isMainDocumentChannel,
requestChannel: this.#requestChannel,
redirectCount: this.#redirectCount,
requestChannel: this.#requestChannel,
requestData: this.#requestData,
timestamp: Date.now(),
});
}
#emitFetchError() {
this.#updateDataFromTimedChannel();
this.#networkListener.emit("fetch-error", {
contextId: this.#contextId,
// TODO: Update with a proper error text. Bug 1873037.
errorText: ChromeUtils.getXPCOMErrorName(this.#requestChannel.status),
isNavigationRequest: this.#isMainDocumentChannel,
redirectCount: this.#redirectCount,
requestChannel: this.#requestChannel,
requestData: this.#requestData,
timestamp: Date.now(),
});

Просмотреть файл

@ -78,6 +78,22 @@ add_task(async function test_beforeRequestSent_newTab() {
gBrowser.removeTab(tab);
});
add_task(async function test_fetchError() {
const listener = new NetworkListener();
const onFetchError = listener.once("fetch-error");
listener.startListening();
info("Check fetchError event when loading a new tab");
const tab = BrowserTestUtils.addTab(gBrowser, "https://not_a_valid_url/");
BrowserTestUtils.browserLoaded(tab.linkedBrowser);
const contextId = TabManager.getIdForBrowser(tab.linkedBrowser);
const event = await onFetchError;
assertNetworkEvent(event, contextId, "https://not_a_valid_url/");
is(event.errorText, "NS_ERROR_UNKNOWN_HOST");
gBrowser.removeTab(tab);
});
function assertNetworkEvent(event, expectedContextId, expectedUrl) {
is(event.contextId, expectedContextId, "Event has the expected context id");
is(event.requestData.url, expectedUrl, "Event has the expected url");

Просмотреть файл

@ -281,6 +281,7 @@ class NetworkModule extends Module {
this.#networkListener = new lazy.NetworkListener();
this.#networkListener.on("auth-required", this.#onAuthRequired);
this.#networkListener.on("before-request-sent", this.#onBeforeRequestSent);
this.#networkListener.on("fetch-error", this.#onFetchError);
this.#networkListener.on("response-completed", this.#onResponseEvent);
this.#networkListener.on("response-started", this.#onResponseEvent);
}
@ -288,6 +289,7 @@ class NetworkModule extends Module {
destroy() {
this.#networkListener.off("auth-required", this.#onAuthRequired);
this.#networkListener.off("before-request-sent", this.#onBeforeRequestSent);
this.#networkListener.off("fetch-error", this.#onFetchError);
this.#networkListener.off("response-completed", this.#onResponseEvent);
this.#networkListener.off("response-started", this.#onResponseEvent);
this.#networkListener.destroy();
@ -787,6 +789,78 @@ class NetworkModule extends Module {
}
};
#onFetchError = (name, data) => {
const {
contextId,
errorText,
isNavigationRequest,
redirectCount,
requestData,
timestamp,
} = data;
const browsingContext = lazy.TabManager.getBrowsingContextById(contextId);
if (!browsingContext) {
// Do not emit events if the context id does not match any existing
// browsing context.
return;
}
const internalEventName = "network._fetchError";
const protocolEventName = "network.fetchError";
// Process the navigation to create potentially missing navigation ids
// before the early return below.
const navigation = this.#getNavigationId(
protocolEventName,
isNavigationRequest,
browsingContext,
requestData.url
);
// Always emit internal events, they are used to support the browsingContext
// navigate command.
// Bug 1861922: Replace internal events with a Network listener helper
// directly using the NetworkObserver.
this.emitEvent(
internalEventName,
{
navigation,
url: requestData.url,
},
this.#getContextInfo(browsingContext)
);
const isListening = this.messageHandler.eventsDispatcher.hasListener(
protocolEventName,
{ contextId }
);
if (!isListening) {
// If there are no listeners subscribed to this event and this context,
// bail out.
return;
}
const baseParameters = this.#processNetworkEvent(protocolEventName, {
contextId,
navigation,
redirectCount,
requestData,
timestamp,
});
const fetchErrorEvent = this.#serializeNetworkEvent({
...baseParameters,
errorText,
});
this.emitEvent(
protocolEventName,
fetchErrorEvent,
this.#getContextInfo(browsingContext)
);
};
#onResponseEvent = (name, data) => {
const {
contextId,
@ -1051,6 +1125,7 @@ class NetworkModule extends Module {
return [
"network.authRequired",
"network.beforeRequestSent",
"network.fetchError",
"network.responseCompleted",
"network.responseStarted",
];