Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,9 @@ class NetworkRequestOverviewView extends StatelessWidget {

Widget _buildHttpTimeGraph() {
final data = this.data as DartIOHttpRequestData;
if (data.duration == null || data.instantEvents.isEmpty) {
if (data.duration == null ||
data.duration!.inMicroseconds == 0 ||
data.instantEvents.isEmpty) {
return Container(
key: httpTimingGraphKey,
height: 18.0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,27 @@ class DartIOHttpRequestData extends NetworkRequest {

@override
Duration? get duration {
if (inProgress || !isValid) return null;
// Timestamps are in microseconds
return _endTime!.difference(_request.startTime);
if (_hasError) {
final start = _request.startTime;
final end = _request.endTime;
return end != null ? end.difference(start) : null;
}

// Cancelled request
if (_request.isRequestComplete &&
!_request.isResponseComplete &&
_request.response == null) {
return Duration.zero;
}

final start = _request.startTime;
final end = _request.response?.endTime ?? _request.endTime;

if (end != null) {
return end.difference(start);
}

return null;
}

/// Whether the request is safe to display in the UI.
Expand Down Expand Up @@ -227,11 +245,19 @@ class DartIOHttpRequestData extends NetworkRequest {
return connectionInfo != null ? connectionInfo[_localPortKey] : null;
}

/// True if the HTTP request hasn't completed yet, determined by the lack of
/// an end time in the response data.
@override
bool get inProgress =>
_hasError ? !_request.isRequestComplete : !_request.isResponseComplete;
bool get inProgress {
// Detect cancelled requests (request finished but response never arrived)
if (_request.isRequestComplete &&
!_request.isResponseComplete &&
_request.response == null) {
return false;
}

return _hasError
? !_request.isRequestComplete
: !_request.isResponseComplete;
}

/// All instant events logged to the timeline for this HTTP request.
List<DartIOHttpInstantEvent> get instantEvents {
Expand Down Expand Up @@ -301,8 +327,17 @@ class DartIOHttpRequestData extends NetworkRequest {
DateTime get startTimestamp => _request.startTime;

@override
String? get status =>
_hasError ? 'Error' : _request.response?.statusCode.toString();
String? get status {
if (_hasError) return 'Error';

if (_request.isRequestComplete &&
!_request.isResponseComplete &&
_request.response == null) {
return 'Cancelled';
}

return _request.response?.statusCode.toString();
}

@override
String get uri => _request.uri.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ abstract class CustomPointerScrollView extends BoxScrollView {
super.physics,
super.shrinkWrap,
super.padding,
super.scrollCacheExtent,
super.cacheExtent,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CC @elliette ; from the PR description:

Update CustomPointerScrollView to use cacheExtent so the project compiles with the current Flutter SDK

super.semanticChildCount,
super.dragStartBehavior,
this.customPointerSignalHandler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -505,5 +505,16 @@ void main() {
expect(httpPatch.didFail, false);
expect(httpWsHandshake.didFail, false);
});

test('cancelled request should not remain pending', () {
final cancelledRequest = DartIOHttpRequestData(
HttpProfileRequest.parse(httpGetPendingJson)!,
requestFullDataFromVmService: false,
);

expect(cancelledRequest.inProgress, false);
expect(cancelledRequest.status, 'Cancelled');
expect(cancelledRequest.duration, Duration.zero);
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ void main() {
expect(column.getDisplayValue(getRequest), httpGet.status);

final pendingRequest = findRequestById('7');
expect(column.getDisplayValue(pendingRequest), '--');
expect(column.getDisplayValue(pendingRequest), 'Cancelled');
});

test('TypeColumn for http request', () {
Expand All @@ -94,16 +94,16 @@ void main() {
expect(column.getDisplayValue(getRequest), '811 ms');

final pendingRequest = findRequestById('7');
expect(column.getDisplayValue(pendingRequest), 'Pending');
expect(column.getDisplayValue(pendingRequest), '0 μs');
});

test('TimestampColumn', () {
final column = TimestampColumn();
final getRequest = findRequestById('1');

// The hours field may be unreliable since it depends on the timezone the
// test is running in.
expect(column.getDisplayValue(getRequest), contains(':45:26.279'));
// The hours and minutes field may be unreliable since it depends on the
// timezone the test is running in (e.g. UTC vs IST).
expect(column.getDisplayValue(getRequest), contains('26.279'));
});
});
}