diff --git a/lib/protocol/audits.dart b/lib/protocol/audits.dart index fcd4165d..cd6881a9 100644 --- a/lib/protocol/audits.dart +++ b/lib/protocol/audits.dart @@ -9,6 +9,11 @@ class AuditsApi { AuditsApi(this._client); + Stream get onIssueAdded => _client.onEvent + .where((event) => event.name == 'Audits.issueAdded') + .map((event) => InspectorIssue.fromJson( + event.parameters['issue'] as Map)); + /// Returns the response body and size if it were re-encoded with the specified settings. Only /// applies to images. /// [requestId] Identifier of the network request to get content for. @@ -29,6 +34,17 @@ class AuditsApi { }); return GetEncodedResponseResult.fromJson(result); } + + /// Disables issues domain, prevents further issues from being reported to the client. + Future disable() async { + await _client.send('Audits.disable'); + } + + /// Enables issues domain, sends the issues collected so far to the client by means of the + /// `issueAdded` event. + Future enable() async { + await _client.send('Audits.enable'); + } } class GetEncodedResponseResult { @@ -52,3 +68,274 @@ class GetEncodedResponseResult { ); } } + +/// Information about a cookie that is affected by an inspector issue. +class AffectedCookie { + /// The following three properties uniquely identify a cookie + final String name; + + final String path; + + final String domain; + + /// Optionally identifies the site-for-cookies, which may be used by the + /// front-end as additional context. + final String siteForCookies; + + AffectedCookie( + {@required this.name, + @required this.path, + @required this.domain, + this.siteForCookies}); + + factory AffectedCookie.fromJson(Map json) { + return AffectedCookie( + name: json['name'] as String, + path: json['path'] as String, + domain: json['domain'] as String, + siteForCookies: json.containsKey('siteForCookies') + ? json['siteForCookies'] as String + : null, + ); + } + + Map toJson() { + return { + 'name': name, + 'path': path, + 'domain': domain, + if (siteForCookies != null) 'siteForCookies': siteForCookies, + }; + } +} + +class SameSiteCookieExclusionReason { + static const excludeSameSiteUnspecifiedTreatedAsLax = + SameSiteCookieExclusionReason._('ExcludeSameSiteUnspecifiedTreatedAsLax'); + static const excludeSameSiteNoneInsecure = + SameSiteCookieExclusionReason._('ExcludeSameSiteNoneInsecure'); + static const values = { + 'ExcludeSameSiteUnspecifiedTreatedAsLax': + excludeSameSiteUnspecifiedTreatedAsLax, + 'ExcludeSameSiteNoneInsecure': excludeSameSiteNoneInsecure, + }; + + final String value; + + const SameSiteCookieExclusionReason._(this.value); + + factory SameSiteCookieExclusionReason.fromJson(String value) => values[value]; + + String toJson() => value; + + @override + bool operator ==(other) => + (other is SameSiteCookieExclusionReason && other.value == value) || + value == other; + + @override + int get hashCode => value.hashCode; + + @override + String toString() => value.toString(); +} + +class SameSiteCookieWarningReason { + static const warnSameSiteUnspecifiedCrossSiteContext = + SameSiteCookieWarningReason._('WarnSameSiteUnspecifiedCrossSiteContext'); + static const warnSameSiteNoneInsecure = + SameSiteCookieWarningReason._('WarnSameSiteNoneInsecure'); + static const warnSameSiteUnspecifiedLaxAllowUnsafe = + SameSiteCookieWarningReason._('WarnSameSiteUnspecifiedLaxAllowUnsafe'); + static const warnSameSiteCrossSchemeSecureUrlMethodUnsafe = + SameSiteCookieWarningReason._( + 'WarnSameSiteCrossSchemeSecureUrlMethodUnsafe'); + static const warnSameSiteCrossSchemeSecureUrlLax = + SameSiteCookieWarningReason._('WarnSameSiteCrossSchemeSecureUrlLax'); + static const warnSameSiteCrossSchemeSecureUrlStrict = + SameSiteCookieWarningReason._('WarnSameSiteCrossSchemeSecureUrlStrict'); + static const warnSameSiteCrossSchemeInsecureUrlMethodUnsafe = + SameSiteCookieWarningReason._( + 'WarnSameSiteCrossSchemeInsecureUrlMethodUnsafe'); + static const warnSameSiteCrossSchemeInsecureUrlLax = + SameSiteCookieWarningReason._('WarnSameSiteCrossSchemeInsecureUrlLax'); + static const warnSameSiteCrossSchemeInsecureUrlStrict = + SameSiteCookieWarningReason._('WarnSameSiteCrossSchemeInsecureUrlStrict'); + static const values = { + 'WarnSameSiteUnspecifiedCrossSiteContext': + warnSameSiteUnspecifiedCrossSiteContext, + 'WarnSameSiteNoneInsecure': warnSameSiteNoneInsecure, + 'WarnSameSiteUnspecifiedLaxAllowUnsafe': + warnSameSiteUnspecifiedLaxAllowUnsafe, + 'WarnSameSiteCrossSchemeSecureUrlMethodUnsafe': + warnSameSiteCrossSchemeSecureUrlMethodUnsafe, + 'WarnSameSiteCrossSchemeSecureUrlLax': warnSameSiteCrossSchemeSecureUrlLax, + 'WarnSameSiteCrossSchemeSecureUrlStrict': + warnSameSiteCrossSchemeSecureUrlStrict, + 'WarnSameSiteCrossSchemeInsecureUrlMethodUnsafe': + warnSameSiteCrossSchemeInsecureUrlMethodUnsafe, + 'WarnSameSiteCrossSchemeInsecureUrlLax': + warnSameSiteCrossSchemeInsecureUrlLax, + 'WarnSameSiteCrossSchemeInsecureUrlStrict': + warnSameSiteCrossSchemeInsecureUrlStrict, + }; + + final String value; + + const SameSiteCookieWarningReason._(this.value); + + factory SameSiteCookieWarningReason.fromJson(String value) => values[value]; + + String toJson() => value; + + @override + bool operator ==(other) => + (other is SameSiteCookieWarningReason && other.value == value) || + value == other; + + @override + int get hashCode => value.hashCode; + + @override + String toString() => value.toString(); +} + +/// This information is currently necessary, as the front-end has a difficult +/// time finding a specific cookie. With this, we can convey specific error +/// information without the cookie. +class SameSiteCookieIssueDetails { + final List cookieWarningReasons; + + final List cookieExclusionReasons; + + SameSiteCookieIssueDetails( + {@required this.cookieWarningReasons, + @required this.cookieExclusionReasons}); + + factory SameSiteCookieIssueDetails.fromJson(Map json) { + return SameSiteCookieIssueDetails( + cookieWarningReasons: (json['cookieWarningReasons'] as List) + .map((e) => SameSiteCookieWarningReason.fromJson(e as String)) + .toList(), + cookieExclusionReasons: (json['cookieExclusionReasons'] as List) + .map((e) => SameSiteCookieExclusionReason.fromJson(e as String)) + .toList(), + ); + } + + Map toJson() { + return { + 'cookieWarningReasons': + cookieWarningReasons.map((e) => e.toJson()).toList(), + 'cookieExclusionReasons': + cookieExclusionReasons.map((e) => e.toJson()).toList(), + }; + } +} + +class AffectedResources { + final List cookies; + + AffectedResources({this.cookies}); + + factory AffectedResources.fromJson(Map json) { + return AffectedResources( + cookies: json.containsKey('cookies') + ? (json['cookies'] as List) + .map((e) => AffectedCookie.fromJson(e as Map)) + .toList() + : null, + ); + } + + Map toJson() { + return { + if (cookies != null) 'cookies': cookies.map((e) => e.toJson()).toList(), + }; + } +} + +/// A unique identifier for the type of issue. Each type may use one of the +/// optional fields in InspectorIssueDetails to convey more specific +/// information about the kind of issue, and AffectedResources to identify +/// resources that are affected by this issue. +class InspectorIssueCode { + static const sameSiteCookieIssue = + InspectorIssueCode._('SameSiteCookieIssue'); + static const values = { + 'SameSiteCookieIssue': sameSiteCookieIssue, + }; + + final String value; + + const InspectorIssueCode._(this.value); + + factory InspectorIssueCode.fromJson(String value) => values[value]; + + String toJson() => value; + + @override + bool operator ==(other) => + (other is InspectorIssueCode && other.value == value) || value == other; + + @override + int get hashCode => value.hashCode; + + @override + String toString() => value.toString(); +} + +/// This struct holds a list of optional fields with additional information +/// pertaining to the kind of issue. This is useful if there is a number of +/// very similar issues that only differ in details. +class InspectorIssueDetails { + final SameSiteCookieIssueDetails sameSiteCookieIssueDetails; + + InspectorIssueDetails({this.sameSiteCookieIssueDetails}); + + factory InspectorIssueDetails.fromJson(Map json) { + return InspectorIssueDetails( + sameSiteCookieIssueDetails: json.containsKey('sameSiteCookieIssueDetails') + ? SameSiteCookieIssueDetails.fromJson( + json['sameSiteCookieIssueDetails'] as Map) + : null, + ); + } + + Map toJson() { + return { + if (sameSiteCookieIssueDetails != null) + 'sameSiteCookieIssueDetails': sameSiteCookieIssueDetails.toJson(), + }; + } +} + +/// An inspector issue reported from the back-end. +class InspectorIssue { + final InspectorIssueCode code; + + final InspectorIssueDetails details; + + final AffectedResources resources; + + InspectorIssue( + {@required this.code, @required this.details, @required this.resources}); + + factory InspectorIssue.fromJson(Map json) { + return InspectorIssue( + code: InspectorIssueCode.fromJson(json['code'] as String), + details: InspectorIssueDetails.fromJson( + json['details'] as Map), + resources: + AffectedResources.fromJson(json['resources'] as Map), + ); + } + + Map toJson() { + return { + 'code': code.toJson(), + 'details': details.toJson(), + 'resources': resources.toJson(), + }; + } +} diff --git a/lib/protocol/browser.dart b/lib/protocol/browser.dart index 0e750da6..feadbc28 100644 --- a/lib/protocol/browser.dart +++ b/lib/protocol/browser.dart @@ -10,28 +10,29 @@ class BrowserApi { BrowserApi(this._client); /// Set permission settings for given origin. - /// [origin] Origin the permission applies to. + /// [origin] Origin the permission applies to, all origins if not specified. /// [permission] Descriptor of permission to override. /// [setting] Setting of the permission. /// [browserContextId] Context to override. When omitted, default browser context is used. Future setPermission( - String origin, PermissionDescriptor permission, PermissionSetting setting, - {BrowserContextID browserContextId}) async { + PermissionDescriptor permission, PermissionSetting setting, + {String origin, BrowserContextID browserContextId}) async { await _client.send('Browser.setPermission', { - 'origin': origin, 'permission': permission, 'setting': setting, + if (origin != null) 'origin': origin, if (browserContextId != null) 'browserContextId': browserContextId, }); } /// Grant specific permissions to the given origin and reject all others. + /// [origin] Origin the permission applies to, all origins if not specified. /// [browserContextId] BrowserContext to override permissions. When omitted, default browser context is used. - Future grantPermissions(String origin, List permissions, - {BrowserContextID browserContextId}) async { + Future grantPermissions(List permissions, + {String origin, BrowserContextID browserContextId}) async { await _client.send('Browser.grantPermissions', { - 'origin': origin, 'permissions': [...permissions], + if (origin != null) 'origin': origin, if (browserContextId != null) 'browserContextId': browserContextId, }); } @@ -44,6 +45,26 @@ class BrowserApi { }); } + /// Set the behavior when downloading a file. + /// [behavior] Whether to allow all or deny all download requests, or use default Chrome behavior if + /// available (otherwise deny). |allowAndName| allows download and names files according to + /// their dowmload guids. + /// [browserContextId] BrowserContext to set download behavior. When omitted, default browser context is used. + /// [downloadPath] The default path to save downloaded files to. This is requred if behavior is set to 'allow' + /// or 'allowAndName'. + Future setDownloadBehavior( + @Enum(['deny', 'allow', 'allowAndName', 'default']) String behavior, + {BrowserContextID browserContextId, + String downloadPath}) async { + assert( + const ['deny', 'allow', 'allowAndName', 'default'].contains(behavior)); + await _client.send('Browser.setDownloadBehavior', { + 'behavior': behavior, + if (browserContextId != null) 'browserContextId': browserContextId, + if (downloadPath != null) 'downloadPath': downloadPath, + }); + } + /// Close browser gracefully. Future close() async { await _client.send('Browser.close'); diff --git a/lib/protocol/debugger.dart b/lib/protocol/debugger.dart index 5378dee1..a4be9a8e 100644 --- a/lib/protocol/debugger.dart +++ b/lib/protocol/debugger.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:meta/meta.dart' show required; import '../src/connection.dart'; +import 'debugger.dart' as debugger; import 'runtime.dart' as runtime; /// Debugger domain exposes JavaScript debugging capabilities. It allows setting and removing @@ -182,8 +183,15 @@ class DebuggerApi { } /// Resumes JavaScript execution. - Future resume() async { - await _client.send('Debugger.resume'); + /// [terminateOnResume] Set to true to terminate execution upon resuming execution. In contrast + /// to Runtime.terminateExecution, this will allows to execute further + /// JavaScript (i.e. via evaluation) until execution of the paused code + /// is actually resumed, at which point termination is triggered. + /// If execution is currently not paused, this parameter has no effect. + Future resume({bool terminateOnResume}) async { + await _client.send('Debugger.resume', { + if (terminateOnResume != null) 'terminateOnResume': terminateOnResume, + }); } /// Searches for given string in script content. @@ -511,6 +519,12 @@ class ScriptFailedToParseEvent { /// JavaScript top stack frame of where the script parsed event was triggered if available. final runtime.StackTraceData stackTrace; + /// If the scriptLanguage is WebAssembly, the code section offset in the module. + final int codeOffset; + + /// The language of the script. + final debugger.ScriptLanguage scriptLanguage; + ScriptFailedToParseEvent( {@required this.scriptId, @required this.url, @@ -525,7 +539,9 @@ class ScriptFailedToParseEvent { this.hasSourceURL, this.isModule, this.length, - this.stackTrace}); + this.stackTrace, + this.codeOffset, + this.scriptLanguage}); factory ScriptFailedToParseEvent.fromJson(Map json) { return ScriptFailedToParseEvent( @@ -553,6 +569,11 @@ class ScriptFailedToParseEvent { ? runtime.StackTraceData.fromJson( json['stackTrace'] as Map) : null, + codeOffset: + json.containsKey('codeOffset') ? json['codeOffset'] as int : null, + scriptLanguage: json.containsKey('scriptLanguage') + ? debugger.ScriptLanguage.fromJson(json['scriptLanguage'] as String) + : null, ); } } @@ -603,6 +624,12 @@ class ScriptParsedEvent { /// JavaScript top stack frame of where the script parsed event was triggered if available. final runtime.StackTraceData stackTrace; + /// If the scriptLanguage is WebAssembly, the code section offset in the module. + final int codeOffset; + + /// The language of the script. + final debugger.ScriptLanguage scriptLanguage; + ScriptParsedEvent( {@required this.scriptId, @required this.url, @@ -618,7 +645,9 @@ class ScriptParsedEvent { this.hasSourceURL, this.isModule, this.length, - this.stackTrace}); + this.stackTrace, + this.codeOffset, + this.scriptLanguage}); factory ScriptParsedEvent.fromJson(Map json) { return ScriptParsedEvent( @@ -648,6 +677,11 @@ class ScriptParsedEvent { ? runtime.StackTraceData.fromJson( json['stackTrace'] as Map) : null, + codeOffset: + json.containsKey('codeOffset') ? json['codeOffset'] as int : null, + scriptLanguage: json.containsKey('scriptLanguage') + ? debugger.ScriptLanguage.fromJson(json['scriptLanguage'] as String) + : null, ); } } @@ -1041,6 +1075,7 @@ class ScopeType { static const script = ScopeType._('script'); static const eval = ScopeType._('eval'); static const module = ScopeType._('module'); + static const wasmExpressionStack = ScopeType._('wasm-expression-stack'); static const values = { 'global': global, 'local': local, @@ -1051,6 +1086,7 @@ class ScopeType { 'script': script, 'eval': eval, 'module': module, + 'wasm-expression-stack': wasmExpressionStack, }; final String value; @@ -1166,6 +1202,34 @@ class BreakLocationType { String toString() => value.toString(); } +/// Enum of possible script languages. +class ScriptLanguage { + static const javaScript = ScriptLanguage._('JavaScript'); + static const webAssembly = ScriptLanguage._('WebAssembly'); + static const values = { + 'JavaScript': javaScript, + 'WebAssembly': webAssembly, + }; + + final String value; + + const ScriptLanguage._(this.value); + + factory ScriptLanguage.fromJson(String value) => values[value]; + + String toJson() => value; + + @override + bool operator ==(other) => + (other is ScriptLanguage && other.value == value) || value == other; + + @override + int get hashCode => value.hashCode; + + @override + String toString() => value.toString(); +} + class PausedEventReason { static const ambiguous = PausedEventReason._('ambiguous'); static const assert$ = PausedEventReason._('assert'); diff --git a/lib/protocol/dom.dart b/lib/protocol/dom.dart index f0eec993..a287d11a 100644 --- a/lib/protocol/dom.dart +++ b/lib/protocol/dom.dart @@ -146,6 +146,27 @@ class DOMApi { return Node.fromJson(result['node'] as Map); } + /// Scrolls the specified rect of the given node into view if not already visible. + /// Note: exactly one between nodeId, backendNodeId and objectId should be passed + /// to identify the node. + /// [nodeId] Identifier of the node. + /// [backendNodeId] Identifier of the backend node. + /// [objectId] JavaScript object id of the node wrapper. + /// [rect] The rect to be scrolled into view, relative to the node's border box, in CSS pixels. + /// When omitted, center of the node will be used, similar to Element.scrollIntoView. + Future scrollIntoViewIfNeeded( + {NodeId nodeId, + BackendNodeId backendNodeId, + runtime.RemoteObjectId objectId, + Rect rect}) async { + await _client.send('DOM.scrollIntoViewIfNeeded', { + if (nodeId != null) 'nodeId': nodeId, + if (backendNodeId != null) 'backendNodeId': backendNodeId, + if (objectId != null) 'objectId': objectId, + if (rect != null) 'rect': rect, + }); + } + /// Disables DOM agent for the given page. Future disable() async { await _client.send('DOM.disable'); diff --git a/lib/protocol/emulation.dart b/lib/protocol/emulation.dart index 70e56004..d97aa767 100644 --- a/lib/protocol/emulation.dart +++ b/lib/protocol/emulation.dart @@ -143,6 +143,31 @@ class EmulationApi { }); } + /// Emulates the given vision deficiency. + /// [type] Vision deficiency to emulate. + Future setEmulatedVisionDeficiency( + @Enum([ + 'none', + 'achromatopsia', + 'blurredVision', + 'deuteranopia', + 'protanopia', + 'tritanopia' + ]) + String type) async { + assert(const [ + 'none', + 'achromatopsia', + 'blurredVision', + 'deuteranopia', + 'protanopia', + 'tritanopia' + ].contains(type)); + await _client.send('Emulation.setEmulatedVisionDeficiency', { + 'type': type, + }); + } + /// Overrides the Geolocation Position or Error. Omitting any of the parameters emulates position /// unavailable. /// [latitude] Mock latitude @@ -219,6 +244,15 @@ class EmulationApi { return result['virtualTimeTicksBase'] as num; } + /// Overrides default host system locale with the specified one. + /// [locale] ICU style C locale (e.g. "en_US"). If not specified or empty, disables the override and + /// restores default host system locale. + Future setLocaleOverride({String locale}) async { + await _client.send('Emulation.setLocaleOverride', { + if (locale != null) 'locale': locale, + }); + } + /// Overrides default host system timezone with the specified one. /// [timezoneId] The timezone identifier. If empty, disables the override and /// restores default host system timezone. diff --git a/lib/protocol/fetch.dart b/lib/protocol/fetch.dart index a44a2196..dce8c502 100644 --- a/lib/protocol/fetch.dart +++ b/lib/protocol/fetch.dart @@ -90,7 +90,7 @@ class FetchApi { /// [url] If set, the request url will be modified in a way that's not observable by page. /// [method] If set, the request method is overridden. /// [postData] If set, overrides the post data in the request. - /// [headers] If set, overrides the request headrts. + /// [headers] If set, overrides the request headers. Future continueRequest(RequestId requestId, {String url, String method, diff --git a/lib/protocol/network.dart b/lib/protocol/network.dart index 050ec29b..b2f8deff 100644 --- a/lib/protocol/network.dart +++ b/lib/protocol/network.dart @@ -1956,6 +1956,15 @@ class BlockedReason { static const subresourceFilter = BlockedReason._('subresource-filter'); static const contentType = BlockedReason._('content-type'); static const collapsedByClient = BlockedReason._('collapsed-by-client'); + static const coepFrameResourceNeedsCoepHeader = + BlockedReason._('coep-frame-resource-needs-coep-header'); + static const coopSandboxedIframeCannotNavigateToCoopPage = + BlockedReason._('coop-sandboxed-iframe-cannot-navigate-to-coop-page'); + static const corpNotSameOrigin = BlockedReason._('corp-not-same-origin'); + static const corpNotSameOriginAfterDefaultedToSameOriginByCoep = + BlockedReason._( + 'corp-not-same-origin-after-defaulted-to-same-origin-by-coep'); + static const corpNotSameSite = BlockedReason._('corp-not-same-site'); static const values = { 'other': other, 'csp': csp, @@ -1965,6 +1974,13 @@ class BlockedReason { 'subresource-filter': subresourceFilter, 'content-type': contentType, 'collapsed-by-client': collapsedByClient, + 'coep-frame-resource-needs-coep-header': coepFrameResourceNeedsCoepHeader, + 'coop-sandboxed-iframe-cannot-navigate-to-coop-page': + coopSandboxedIframeCannotNavigateToCoopPage, + 'corp-not-same-origin': corpNotSameOrigin, + 'corp-not-same-origin-after-defaulted-to-same-origin-by-coep': + corpNotSameOriginAfterDefaultedToSameOriginByCoep, + 'corp-not-same-site': corpNotSameSite, }; final String value; diff --git a/lib/protocol/page.dart b/lib/protocol/page.dart index c10af034..6f7cdbe1 100644 --- a/lib/protocol/page.dart +++ b/lib/protocol/page.dart @@ -78,6 +78,11 @@ class PageApi { .where((event) => event.name == 'Page.downloadWillBegin') .map((event) => DownloadWillBeginEvent.fromJson(event.parameters)); + /// Fired when download makes progress. Last call has |done| == true. + Stream get onDownloadProgress => _client.onEvent + .where((event) => event.name == 'Page.downloadProgress') + .map((event) => DownloadProgressEvent.fromJson(event.parameters)); + /// Fired when interstitial page was hidden Stream get onInterstitialHidden => _client.onEvent.where((event) => event.name == 'Page.interstitialHidden'); @@ -265,9 +270,11 @@ class PageApi { return GetAppManifestResult.fromJson(result); } - Future getInstallabilityErrors() async { + Future> getInstallabilityErrors() async { var result = await _client.send('Page.getInstallabilityErrors'); - return GetInstallabilityErrorsResult.fromJson(result); + return (result['installabilityErrors'] as List) + .map((e) => InstallabilityError.fromJson(e as Map)) + .toList(); } Future getManifestIcons() async { @@ -346,13 +353,18 @@ class PageApi { /// [referrer] Referrer URL. /// [transitionType] Intended transition type. /// [frameId] Frame id to navigate, if not specified navigates the top frame. + /// [referrerPolicy] Referrer-policy used for the navigation. Future navigate(String url, - {String referrer, TransitionType transitionType, FrameId frameId}) async { + {String referrer, + TransitionType transitionType, + FrameId frameId, + ReferrerPolicy referrerPolicy}) async { var result = await _client.send('Page.navigate', { 'url': url, if (referrer != null) 'referrer': referrer, if (transitionType != null) 'transitionType': transitionType, if (frameId != null) 'frameId': frameId, + if (referrerPolicy != null) 'referrerPolicy': referrerPolicy, }); return NavigateResult.fromJson(result); } @@ -596,6 +608,7 @@ class PageApi { /// [behavior] Whether to allow all or deny all download requests, or use default Chrome behavior if /// available (otherwise deny). /// [downloadPath] The default path to save downloaded files to. This is requred if behavior is set to 'allow' + @deprecated Future setDownloadBehavior( @Enum(['deny', 'allow', 'default']) String behavior, {String downloadPath}) async { @@ -849,19 +862,53 @@ class DownloadWillBeginEvent { /// Id of the frame that caused download to begin. final FrameId frameId; + /// Global unique identifier of the download. + final String guid; + /// URL of the resource being downloaded. final String url; - DownloadWillBeginEvent({@required this.frameId, @required this.url}); + DownloadWillBeginEvent( + {@required this.frameId, @required this.guid, @required this.url}); factory DownloadWillBeginEvent.fromJson(Map json) { return DownloadWillBeginEvent( frameId: FrameId.fromJson(json['frameId'] as String), + guid: json['guid'] as String, url: json['url'] as String, ); } } +class DownloadProgressEvent { + /// Global unique identifier of the download. + final String guid; + + /// Total expected bytes to download. + final num totalBytes; + + /// Total bytes received. + final num receivedBytes; + + /// Download status. + final DownloadProgressEventState state; + + DownloadProgressEvent( + {@required this.guid, + @required this.totalBytes, + @required this.receivedBytes, + @required this.state}); + + factory DownloadProgressEvent.fromJson(Map json) { + return DownloadProgressEvent( + guid: json['guid'] as String, + totalBytes: json['totalBytes'] as num, + receivedBytes: json['receivedBytes'] as num, + state: DownloadProgressEventState.fromJson(json['state'] as String), + ); + } +} + class JavascriptDialogClosedEvent { /// Whether dialog was confirmed. final bool result; @@ -1061,20 +1108,6 @@ class GetAppManifestResult { } } -class GetInstallabilityErrorsResult { - final List installabilityErrors; - - GetInstallabilityErrorsResult({@required this.installabilityErrors}); - - factory GetInstallabilityErrorsResult.fromJson(Map json) { - return GetInstallabilityErrorsResult( - installabilityErrors: (json['installabilityErrors'] as List) - .map((e) => InstallabilityError.fromJson(e as Map)) - .toList(), - ); - } -} - class GetLayoutMetricsResult { /// Metrics relating to the layout viewport. final LayoutViewport layoutViewport; @@ -2000,6 +2033,49 @@ class InstallabilityError { } } +/// The referring-policy used for the navigation. +class ReferrerPolicy { + static const noReferrer = ReferrerPolicy._('noReferrer'); + static const noReferrerWhenDowngrade = + ReferrerPolicy._('noReferrerWhenDowngrade'); + static const origin = ReferrerPolicy._('origin'); + static const originWhenCrossOrigin = + ReferrerPolicy._('originWhenCrossOrigin'); + static const sameOrigin = ReferrerPolicy._('sameOrigin'); + static const strictOrigin = ReferrerPolicy._('strictOrigin'); + static const strictOriginWhenCrossOrigin = + ReferrerPolicy._('strictOriginWhenCrossOrigin'); + static const unsafeUrl = ReferrerPolicy._('unsafeUrl'); + static const values = { + 'noReferrer': noReferrer, + 'noReferrerWhenDowngrade': noReferrerWhenDowngrade, + 'origin': origin, + 'originWhenCrossOrigin': originWhenCrossOrigin, + 'sameOrigin': sameOrigin, + 'strictOrigin': strictOrigin, + 'strictOriginWhenCrossOrigin': strictOriginWhenCrossOrigin, + 'unsafeUrl': unsafeUrl, + }; + + final String value; + + const ReferrerPolicy._(this.value); + + factory ReferrerPolicy.fromJson(String value) => values[value]; + + String toJson() => value; + + @override + bool operator ==(other) => + (other is ReferrerPolicy && other.value == value) || value == other; + + @override + int get hashCode => value.hashCode; + + @override + String toString() => value.toString(); +} + class FileChooserOpenedEventMode { static const selectSingle = FileChooserOpenedEventMode._('selectSingle'); static const selectMultiple = FileChooserOpenedEventMode._('selectMultiple'); @@ -2027,3 +2103,33 @@ class FileChooserOpenedEventMode { @override String toString() => value.toString(); } + +class DownloadProgressEventState { + static const inProgress = DownloadProgressEventState._('inProgress'); + static const completed = DownloadProgressEventState._('completed'); + static const canceled = DownloadProgressEventState._('canceled'); + static const values = { + 'inProgress': inProgress, + 'completed': completed, + 'canceled': canceled, + }; + + final String value; + + const DownloadProgressEventState._(this.value); + + factory DownloadProgressEventState.fromJson(String value) => values[value]; + + String toJson() => value; + + @override + bool operator ==(other) => + (other is DownloadProgressEventState && other.value == value) || + value == other; + + @override + int get hashCode => value.hashCode; + + @override + String toString() => value.toString(); +} diff --git a/lib/protocol/performance.dart b/lib/protocol/performance.dart index 08f26994..5c637010 100644 --- a/lib/protocol/performance.dart +++ b/lib/protocol/performance.dart @@ -18,14 +18,21 @@ class PerformanceApi { } /// Enable collecting and reporting metrics. - Future enable() async { - await _client.send('Performance.enable'); + /// [timeDomain] Time domain to use for collecting and reporting duration metrics. + Future enable( + {@Enum(['timeTicks', 'threadTicks']) String timeDomain}) async { + assert(timeDomain == null || + const ['timeTicks', 'threadTicks'].contains(timeDomain)); + await _client.send('Performance.enable', { + if (timeDomain != null) 'timeDomain': timeDomain, + }); } /// Sets time domain to use for collecting and reporting duration metrics. /// Note that this must be called before enabling metrics collection. Calling /// this method while metrics collection is enabled returns an error. /// [timeDomain] Time domain + @deprecated Future setTimeDomain( @Enum(['timeTicks', 'threadTicks']) String timeDomain) async { assert(const ['timeTicks', 'threadTicks'].contains(timeDomain)); diff --git a/lib/protocol/profiler.dart b/lib/protocol/profiler.dart index e2fa7fbc..98369444 100644 --- a/lib/protocol/profiler.dart +++ b/lib/protocol/profiler.dart @@ -65,11 +65,15 @@ class ProfilerApi { /// counters. /// [callCount] Collect accurate call counts beyond simple 'covered' or 'not covered'. /// [detailed] Collect block-based coverage. + /// [allowTriggeredUpdates] Allow the backend to send updates on its own initiative /// Returns: Monotonically increasing time (in seconds) when the coverage update was taken in the backend. - Future startPreciseCoverage({bool callCount, bool detailed}) async { + Future startPreciseCoverage( + {bool callCount, bool detailed, bool allowTriggeredUpdates}) async { var result = await _client.send('Profiler.startPreciseCoverage', { if (callCount != null) 'callCount': callCount, if (detailed != null) 'detailed': detailed, + if (allowTriggeredUpdates != null) + 'allowTriggeredUpdates': allowTriggeredUpdates, }); return result['timestamp'] as num; } diff --git a/lib/protocol/runtime.dart b/lib/protocol/runtime.dart index 64b556c4..de67dc71 100644 --- a/lib/protocol/runtime.dart +++ b/lib/protocol/runtime.dart @@ -164,7 +164,9 @@ class RuntimeApi { /// This implies `disableBreaks` below. /// [timeout] Terminate execution after timing out (number of milliseconds). /// [disableBreaks] Disable breakpoints during execution. - /// [replMode] Reserved flag for future REPL mode support. Setting this flag has currently no effect. + /// [replMode] Setting this flag to true enables `let` re-declaration and top-level `await`. + /// Note that `let` variables can only be re-declared if they originate from + /// `replMode` themselves. Future evaluate(String expression, {String objectGroup, bool includeCommandLineAPI, @@ -716,7 +718,7 @@ class RemoteObject { /// Object type. final RemoteObjectType type; - /// Object subtype hint. Specified for `object` type values only. + /// Object subtype hint. Specified for `object` or `wasm` type values only. final RemoteObjectSubtype subtype; /// Object class (constructor) name. Specified for `object` type values only. @@ -804,6 +806,7 @@ class RemoteObjectType { static const boolean = RemoteObjectType._('boolean'); static const symbol = RemoteObjectType._('symbol'); static const bigint = RemoteObjectType._('bigint'); + static const wasm = RemoteObjectType._('wasm'); static const values = { 'object': object, 'function': function, @@ -813,6 +816,7 @@ class RemoteObjectType { 'boolean': boolean, 'symbol': symbol, 'bigint': bigint, + 'wasm': wasm, }; final String value; @@ -852,6 +856,11 @@ class RemoteObjectSubtype { static const typedarray = RemoteObjectSubtype._('typedarray'); static const arraybuffer = RemoteObjectSubtype._('arraybuffer'); static const dataview = RemoteObjectSubtype._('dataview'); + static const i32 = RemoteObjectSubtype._('i32'); + static const i64 = RemoteObjectSubtype._('i64'); + static const f32 = RemoteObjectSubtype._('f32'); + static const f64 = RemoteObjectSubtype._('f64'); + static const v128 = RemoteObjectSubtype._('v128'); static const values = { 'array': array, 'null': null$, @@ -870,6 +879,11 @@ class RemoteObjectSubtype { 'typedarray': typedarray, 'arraybuffer': arraybuffer, 'dataview': dataview, + 'i32': i32, + 'i64': i64, + 'f32': f32, + 'f64': f64, + 'v128': v128, }; final String value; diff --git a/lib/protocol/target.dart b/lib/protocol/target.dart index b9d82774..1058d798 100644 --- a/lib/protocol/target.dart +++ b/lib/protocol/target.dart @@ -106,9 +106,13 @@ class TargetApi { /// Creates a new empty BrowserContext. Similar to an incognito profile but you can have more than /// one. + /// [disposeOnDetach] If specified, disposes this context when debugging session disconnects. /// Returns: The id of the context created. - Future createBrowserContext() async { - var result = await _client.send('Target.createBrowserContext'); + Future createBrowserContext( + {bool disposeOnDetach}) async { + var result = await _client.send('Target.createBrowserContext', { + if (disposeOnDetach != null) 'disposeOnDetach': disposeOnDetach, + }); return browser.BrowserContextID.fromJson( result['browserContextId'] as String); } @@ -212,14 +216,12 @@ class TargetApi { /// [flatten] Enables "flat" access to the session via specifying sessionId attribute in the commands. /// We plan to make this the default, deprecate non-flattened mode, /// and eventually retire it. See crbug.com/991325. - /// [windowOpen] Auto-attach to the targets created via window.open from current target. Future setAutoAttach(bool autoAttach, bool waitForDebuggerOnStart, - {bool flatten, bool windowOpen}) async { + {bool flatten}) async { await _client.send('Target.setAutoAttach', { 'autoAttach': autoAttach, 'waitForDebuggerOnStart': waitForDebuggerOnStart, if (flatten != null) 'flatten': flatten, - if (windowOpen != null) 'windowOpen': windowOpen, }); } diff --git a/lib/src/browser.dart b/lib/src/browser.dart index bd9e1f3d..a0a4292c 100644 --- a/lib/src/browser.dart +++ b/lib/src/browser.dart @@ -352,7 +352,7 @@ class BrowserContext { Future overridePermissions( String origin, List permissions) async { await browser.browser - .grantPermissions(origin, permissions, browserContextId: id); + .grantPermissions(permissions, origin: origin, browserContextId: id); } /// Clears all permission overrides for the browser context. diff --git a/lib/src/downloader.dart b/lib/src/downloader.dart index 3a05ea42..b296a6f7 100644 --- a/lib/src/downloader.dart +++ b/lib/src/downloader.dart @@ -16,7 +16,7 @@ class RevisionInfo { @required this.revision}); } -const int _lastRevision = 737027; +const int _lastRevision = 756035; Future downloadChrome({int revision, String cachePath}) async { revision ??= _lastRevision; diff --git a/tool/json/browser_protocol.json b/tool/json/browser_protocol.json index 309c2645..040d9a04 100644 --- a/tool/json/browser_protocol.json +++ b/tool/json/browser_protocol.json @@ -740,6 +740,9 @@ { "domain": "ApplicationCache", "experimental": true, + "dependencies": [ + "Page" + ], "types": [ { "id": "ApplicationCacheResource", @@ -954,6 +957,17 @@ } ] }, + { + "id": "AffectedFrame", + "description": "Information about the frame affected by an inspector issue.", + "type": "object", + "properties": [ + { + "name": "frameId", + "$ref": "Page.FrameId" + } + ] + }, { "id": "SameSiteCookieExclusionReason", "type": "string", @@ -969,12 +983,11 @@ "WarnSameSiteUnspecifiedCrossSiteContext", "WarnSameSiteNoneInsecure", "WarnSameSiteUnspecifiedLaxAllowUnsafe", - "WarnSameSiteCrossSchemeSecureUrlMethodUnsafe", - "WarnSameSiteCrossSchemeSecureUrlLax", - "WarnSameSiteCrossSchemeSecureUrlStrict", - "WarnSameSiteCrossSchemeInsecureUrlMethodUnsafe", - "WarnSameSiteCrossSchemeInsecureUrlLax", - "WarnSameSiteCrossSchemeInsecureUrlStrict" + "WarnSameSiteStrictLaxDowngradeStrict", + "WarnSameSiteStrictCrossDowngradeStrict", + "WarnSameSiteStrictCrossDowngradeLax", + "WarnSameSiteLaxCrossDowngradeStrict", + "WarnSameSiteLaxCrossDowngradeLax" ] }, { @@ -1030,12 +1043,93 @@ } ] }, + { + "id": "MixedContentResolutionStatus", + "type": "string", + "enum": [ + "MixedContentBlocked", + "MixedContentAutomaticallyUpgraded", + "MixedContentWarning" + ] + }, + { + "id": "MixedContentResourceType", + "type": "string", + "enum": [ + "Audio", + "Beacon", + "CSPReport", + "Download", + "EventSource", + "Favicon", + "Font", + "Form", + "Frame", + "Image", + "Import", + "Manifest", + "Ping", + "PluginData", + "PluginResource", + "Prefetch", + "Resource", + "Script", + "ServiceWorker", + "SharedWorker", + "Stylesheet", + "Track", + "Video", + "Worker", + "XMLHttpRequest", + "XSLT" + ] + }, + { + "id": "MixedContentIssueDetails", + "type": "object", + "properties": [ + { + "name": "resourceType", + "description": "The type of resource causing the mixed content issue (css, js, iframe,\nform,...). Marked as optional because it is mapped to from\nblink::mojom::RequestContextType, which will be replaced\nby network::mojom::RequestDestination", + "optional": true, + "$ref": "MixedContentResourceType" + }, + { + "name": "resolutionStatus", + "description": "The way the mixed content issue is being resolved.", + "$ref": "MixedContentResolutionStatus" + }, + { + "name": "insecureURL", + "description": "The unsafe http url causing the mixed content issue.", + "type": "string" + }, + { + "name": "mainResourceURL", + "description": "The url responsible for the call to an unsafe url.", + "type": "string" + }, + { + "name": "request", + "description": "The mixed content request.\nDoes not always exist (e.g. for unsafe form submission urls).", + "optional": true, + "$ref": "AffectedRequest" + }, + { + "name": "frame", + "description": "Optional because not every mixed content issue is necessarily linked to a frame.", + "optional": true, + "$ref": "AffectedFrame" + } + ] + }, { "id": "InspectorIssueCode", "description": "A unique identifier for the type of issue. Each type may use one of the\noptional fields in InspectorIssueDetails to convey more specific\ninformation about the kind of issue.", "type": "string", "enum": [ - "SameSiteCookieIssue" + "SameSiteCookieIssue", + "MixedContentIssue" ] }, { @@ -1047,6 +1141,11 @@ "name": "sameSiteCookieIssueDetails", "optional": true, "$ref": "SameSiteCookieIssueDetails" + }, + { + "name": "mixedContentIssueDetails", + "optional": true, + "$ref": "MixedContentIssueDetails" } ] }, @@ -1783,7 +1882,8 @@ "description": "This domain exposes CSS read/write operations. All CSS objects (stylesheets, rules, and styles)\nhave an associated `id` used in subsequent operations on the related object. Each object type has\na specific `id` structure, and those are not interchangeable between objects of different kinds.\nCSS objects can be loaded using the `get*ForNode()` calls (which accept a DOM node id). A client\ncan also keep track of stylesheets via the `styleSheetAdded`/`styleSheetRemoved` events and\nsubsequently load the required stylesheet contents using the `getStyleSheet[Text]()` methods.", "experimental": true, "dependencies": [ - "DOM" + "DOM", + "Page" ], "types": [ { @@ -6290,6 +6390,61 @@ "pause", "pauseIfNetworkFetchesPending" ] + }, + { + "id": "UserAgentBrandVersion", + "description": "Used to specify User Agent Cient Hints to emulate. See https://wicg.github.io/ua-client-hints", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "brand", + "type": "string" + }, + { + "name": "version", + "type": "string" + } + ] + }, + { + "id": "UserAgentMetadata", + "description": "Used to specify User Agent Cient Hints to emulate. See https://wicg.github.io/ua-client-hints", + "experimental": true, + "type": "object", + "properties": [ + { + "name": "brands", + "type": "array", + "items": { + "$ref": "UserAgentBrandVersion" + } + }, + { + "name": "fullVersion", + "type": "string" + }, + { + "name": "platform", + "type": "string" + }, + { + "name": "platformVersion", + "type": "string" + }, + { + "name": "architecture", + "type": "string" + }, + { + "name": "model", + "type": "string" + }, + { + "name": "mobile", + "type": "boolean" + } + ] } ], "commands": [ @@ -6700,6 +6855,13 @@ "description": "The platform navigator.platform should return.", "optional": true, "type": "string" + }, + { + "name": "userAgentMetadata", + "description": "To be sent in Sec-CH-UA-* headers and returned in navigator.userAgentData", + "experimental": true, + "optional": true, + "$ref": "UserAgentMetadata" } ] } @@ -10415,6 +10577,13 @@ "description": "The platform navigator.platform should return.", "optional": true, "type": "string" + }, + { + "name": "userAgentMetadata", + "description": "To be sent in Sec-CH-UA-* headers and returned in navigator.userAgentData", + "experimental": true, + "optional": true, + "$ref": "Emulation.UserAgentMetadata" } ] } @@ -10927,8 +11096,8 @@ "$ref": "RequestId" }, { - "name": "blockedCookies", - "description": "A list of cookies which will not be sent with this request along with corresponding reasons\nfor blocking.", + "name": "associatedCookies", + "description": "A list of cookies potentially associated to the requested URL. This includes both cookies sent with\nthe request and the ones not sent; the latter are distinguished by having blockedReason field set.", "type": "array", "items": { "$ref": "BlockedCookieWithReason" @@ -10984,6 +11153,67 @@ "Runtime" ], "types": [ + { + "id": "GridHighlightConfig", + "description": "Configuration data for the highlighting of Grid elements.", + "type": "object", + "properties": [ + { + "name": "showGridExtensionLines", + "description": "Whether the extension lines from grid cells to the rulers should be shown (default: false).", + "optional": true, + "type": "boolean" + }, + { + "name": "gridBorderColor", + "description": "The grid container border highlight color (default: transparent).", + "optional": true, + "$ref": "DOM.RGBA" + }, + { + "name": "cellBorderColor", + "description": "The cell border color (default: transparent).", + "optional": true, + "$ref": "DOM.RGBA" + }, + { + "name": "gridBorderDash", + "description": "Whether the grid border is dashed (default: false).", + "optional": true, + "type": "boolean" + }, + { + "name": "cellBorderDash", + "description": "Whether the cell border is dashed (default: false).", + "optional": true, + "type": "boolean" + }, + { + "name": "rowGapColor", + "description": "The row gap highlight fill color (default: transparent).", + "optional": true, + "$ref": "DOM.RGBA" + }, + { + "name": "rowHatchColor", + "description": "The row gap hatching fill color (default: transparent).", + "optional": true, + "$ref": "DOM.RGBA" + }, + { + "name": "columnGapColor", + "description": "The column gap highlight fill color (default: transparent).", + "optional": true, + "$ref": "DOM.RGBA" + }, + { + "name": "columnHatchColor", + "description": "The column gap hatching fill color (default: transparent).", + "optional": true, + "$ref": "DOM.RGBA" + } + ] + }, { "id": "HighlightConfig", "description": "Configuration data for the highlighting of page elements.", @@ -11060,6 +11290,51 @@ "description": "The grid layout color (default: transparent).", "optional": true, "$ref": "DOM.RGBA" + }, + { + "name": "colorFormat", + "description": "The color format used to format color styles (default: hex).", + "optional": true, + "$ref": "ColorFormat" + }, + { + "name": "gridHighlightConfig", + "description": "The grid layout highlight configuration (default: all transparent).", + "optional": true, + "$ref": "GridHighlightConfig" + } + ] + }, + { + "id": "ColorFormat", + "type": "string", + "enum": [ + "rgb", + "hsl", + "hex" + ] + }, + { + "id": "HingeConfig", + "description": "Configuration for dual screen hinge", + "type": "object", + "properties": [ + { + "name": "rect", + "description": "A rectangle represent hinge", + "$ref": "DOM.Rect" + }, + { + "name": "contentColor", + "description": "The content box highlight fill color (default: a dark color).", + "optional": true, + "$ref": "DOM.RGBA" + }, + { + "name": "outlineColor", + "description": "The content box highlight outline color (default: transparent).", + "optional": true, + "$ref": "DOM.RGBA" } ] }, @@ -11104,6 +11379,12 @@ "description": "Whether to include style info.", "optional": true, "type": "boolean" + }, + { + "name": "colorFormat", + "description": "The color format to get config with (default: hex)", + "optional": true, + "$ref": "ColorFormat" } ], "returns": [ @@ -11352,6 +11633,18 @@ "type": "boolean" } ] + }, + { + "name": "setShowHinge", + "description": "Add a dual screen device hinge", + "parameters": [ + { + "name": "hingeConfig", + "description": "hinge data, null means hideHinge", + "optional": true, + "$ref": "HingeConfig" + } + ] } ], "events": [ @@ -11909,6 +12202,17 @@ "anchorClick" ] }, + { + "id": "ClientNavigationDisposition", + "experimental": true, + "type": "string", + "enum": [ + "currentTab", + "newTab", + "newWindow", + "download" + ] + }, { "id": "InstallabilityErrorArgument", "experimental": true, @@ -13131,6 +13435,11 @@ "name": "url", "description": "The destination URL for the requested navigation.", "type": "string" + }, + { + "name": "disposition", + "description": "The disposition for the navigation.", + "$ref": "ClientNavigationDisposition" } ] }, @@ -13204,6 +13513,11 @@ "name": "url", "description": "URL of the resource being downloaded.", "type": "string" + }, + { + "name": "suggestedFilename", + "description": "Suggested file name of the resource (the actual name of the file saved on disk may differ).", + "type": "string" } ] }, @@ -13948,6 +14262,9 @@ { "domain": "ServiceWorker", "experimental": true, + "dependencies": [ + "Target" + ], "types": [ { "id": "RegistrationID", @@ -16704,9 +17021,31 @@ "id": "Timestamp", "type": "number" }, + { + "id": "PlayerMessage", + "description": "Have one type per entry in MediaLogRecord::Type\nCorresponds to kMessage", + "type": "object", + "properties": [ + { + "name": "level", + "description": "Keep in sync with MediaLogMessageLevel\nWe are currently keeping the message level 'error' separate from the\nPlayerError type because right now they represent different things,\nthis one being a DVLOG(ERROR) style log message that gets printed\nbased on what log level is selected in the UI, and the other is a\nrepresentation of a media::PipelineStatus object. Soon however we're\ngoing to be moving away from using PipelineStatus for errors and\nintroducing a new error type which should hopefully let us integrate\nthe error log level into the PlayerError type.", + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" + ] + }, + { + "name": "message", + "type": "string" + } + ] + }, { "id": "PlayerProperty", - "description": "Player Property type", + "description": "Corresponds to kMediaPropertyChange", "type": "object", "properties": [ { @@ -16715,40 +17054,41 @@ }, { "name": "value", - "optional": true, "type": "string" } ] }, - { - "id": "PlayerEventType", - "description": "Break out events into different types", - "type": "string", - "enum": [ - "errorEvent", - "triggeredEvent", - "messageEvent" - ] - }, { "id": "PlayerEvent", + "description": "Corresponds to kMediaEventTriggered", "type": "object", "properties": [ - { - "name": "type", - "$ref": "PlayerEventType" - }, { "name": "timestamp", - "description": "Events are timestamped relative to the start of the player creation\nnot relative to the start of playback.", "$ref": "Timestamp" }, { - "name": "name", + "name": "value", "type": "string" + } + ] + }, + { + "id": "PlayerError", + "description": "Corresponds to kMediaError", + "type": "object", + "properties": [ + { + "name": "type", + "type": "string", + "enum": [ + "pipeline_error", + "media_error" + ] }, { - "name": "value", + "name": "errorCode", + "description": "When this switches to using media::Status instead of PipelineStatus\nwe can remove \"errorCode\" and replace it with the fields from\na Status instance. This also seems like a duplicate of the error\nlevel enum - there is a todo bug to have that level removed and\nuse this instead. (crbug.com/1068454)", "type": "string" } ] @@ -16789,6 +17129,40 @@ } ] }, + { + "name": "playerMessagesLogged", + "description": "Send a list of any messages that need to be delivered.", + "parameters": [ + { + "name": "playerId", + "$ref": "PlayerId" + }, + { + "name": "messages", + "type": "array", + "items": { + "$ref": "PlayerMessage" + } + } + ] + }, + { + "name": "playerErrorsRaised", + "description": "Send a list of any errors that need to be delivered.", + "parameters": [ + { + "name": "playerId", + "$ref": "PlayerId" + }, + { + "name": "errors", + "type": "array", + "items": { + "$ref": "PlayerError" + } + } + ] + }, { "name": "playersCreated", "description": "Called whenever a player is created, or when a new agent joins and recieves\na list of active players. If an agent is restored, it will recieve the full\nlist of player ids and all events again.", diff --git a/tool/json/js_protocol.json b/tool/json/js_protocol.json index 77998410..75b07421 100644 --- a/tool/json/js_protocol.json +++ b/tool/json/js_protocol.json @@ -312,6 +312,30 @@ "JavaScript", "WebAssembly" ] + }, + { + "id": "DebugSymbols", + "description": "Debug symbols available for a wasm script.", + "type": "object", + "properties": [ + { + "name": "type", + "description": "Type of the debug symbols.", + "type": "string", + "enum": [ + "None", + "SourceMap", + "EmbeddedDWARF", + "ExternalDWARF" + ] + }, + { + "name": "externalURL", + "description": "URL of the external symbol source.", + "optional": true, + "type": "string" + } + ] } ], "commands": [ @@ -433,6 +457,43 @@ } ] }, + { + "name": "executeWasmEvaluator", + "description": "Execute a Wasm Evaluator module on a given call frame.", + "experimental": true, + "parameters": [ + { + "name": "callFrameId", + "description": "WebAssembly call frame identifier to evaluate on.", + "$ref": "CallFrameId" + }, + { + "name": "evaluator", + "description": "Code of the evaluator module.", + "type": "string" + }, + { + "name": "timeout", + "description": "Terminate execution after timing out (number of milliseconds).", + "experimental": true, + "optional": true, + "$ref": "Runtime.TimeDelta" + } + ], + "returns": [ + { + "name": "result", + "description": "Object wrapper for the evaluation result.", + "$ref": "Runtime.RemoteObject" + }, + { + "name": "exceptionDetails", + "description": "Exception details.", + "optional": true, + "$ref": "Runtime.ExceptionDetails" + } + ] + }, { "name": "getPossibleBreakpoints", "description": "Returns possible locations for breakpoint. scriptId in start and end range locations should be\nthe same.", @@ -1256,6 +1317,13 @@ "experimental": true, "optional": true, "$ref": "Debugger.ScriptLanguage" + }, + { + "name": "debugSymbols", + "description": "If the scriptLanguage is WebASsembly, the source of debug symbols for the module.", + "experimental": true, + "optional": true, + "$ref": "Debugger.DebugSymbols" } ] } @@ -2095,7 +2163,8 @@ "i64", "f32", "f64", - "v128" + "v128", + "anyref" ] }, { diff --git a/tool/json/protocol_from_chrome.json b/tool/json/protocol_from_chrome.json index 26aa16d8..96cc1f50 100644 --- a/tool/json/protocol_from_chrome.json +++ b/tool/json/protocol_from_chrome.json @@ -912,6 +912,131 @@ "dependencies": [ "Network" ], + "types": [ + { + "id": "AffectedCookie", + "description": "Information about a cookie that is affected by an inspector issue.", + "type": "object", + "properties": [ + { + "name": "name", + "description": "The following three properties uniquely identify a cookie", + "type": "string" + }, + { + "name": "path", + "type": "string" + }, + { + "name": "domain", + "type": "string" + }, + { + "name": "siteForCookies", + "description": "Optionally identifies the site-for-cookies, which may be used by the\nfront-end as additional context.", + "optional": true, + "type": "string" + } + ] + }, + { + "id": "SameSiteCookieExclusionReason", + "type": "string", + "enum": [ + "ExcludeSameSiteUnspecifiedTreatedAsLax", + "ExcludeSameSiteNoneInsecure" + ] + }, + { + "id": "SameSiteCookieWarningReason", + "type": "string", + "enum": [ + "WarnSameSiteUnspecifiedCrossSiteContext", + "WarnSameSiteNoneInsecure", + "WarnSameSiteUnspecifiedLaxAllowUnsafe", + "WarnSameSiteCrossSchemeSecureUrlMethodUnsafe", + "WarnSameSiteCrossSchemeSecureUrlLax", + "WarnSameSiteCrossSchemeSecureUrlStrict", + "WarnSameSiteCrossSchemeInsecureUrlMethodUnsafe", + "WarnSameSiteCrossSchemeInsecureUrlLax", + "WarnSameSiteCrossSchemeInsecureUrlStrict" + ] + }, + { + "id": "SameSiteCookieIssueDetails", + "description": "This information is currently necessary, as the front-end has a difficult\ntime finding a specific cookie. With this, we can convey specific error\ninformation without the cookie.", + "type": "object", + "properties": [ + { + "name": "cookieWarningReasons", + "type": "array", + "items": { + "$ref": "SameSiteCookieWarningReason" + } + }, + { + "name": "cookieExclusionReasons", + "type": "array", + "items": { + "$ref": "SameSiteCookieExclusionReason" + } + } + ] + }, + { + "id": "AffectedResources", + "type": "object", + "properties": [ + { + "name": "cookies", + "optional": true, + "type": "array", + "items": { + "$ref": "AffectedCookie" + } + } + ] + }, + { + "id": "InspectorIssueCode", + "description": "A unique identifier for the type of issue. Each type may use one of the\noptional fields in InspectorIssueDetails to convey more specific\ninformation about the kind of issue, and AffectedResources to identify\nresources that are affected by this issue.", + "type": "string", + "enum": [ + "SameSiteCookieIssue" + ] + }, + { + "id": "InspectorIssueDetails", + "description": "This struct holds a list of optional fields with additional information\npertaining to the kind of issue. This is useful if there is a number of\nvery similar issues that only differ in details.", + "type": "object", + "properties": [ + { + "name": "sameSiteCookieIssueDetails", + "optional": true, + "$ref": "SameSiteCookieIssueDetails" + } + ] + }, + { + "id": "InspectorIssue", + "description": "An inspector issue reported from the back-end.", + "type": "object", + "properties": [ + { + "name": "code", + "$ref": "InspectorIssueCode" + }, + { + "name": "details", + "$ref": "InspectorIssueDetails" + }, + { + "name": "resources", + "$ref": "AffectedResources" + } + ] + } + ], "commands": [ { "name": "getEncodedResponse", @@ -963,6 +1088,25 @@ "type": "integer" } ] + }, + { + "name": "disable", + "description": "Disables issues domain, prevents further issues from being reported to the client." + }, + { + "name": "enable", + "description": "Enables issues domain, sends the issues collected so far to the client by means of the\n`issueAdded` event." + } + ], + "events": [ + { + "name": "issueAdded", + "parameters": [ + { + "name": "issue", + "$ref": "InspectorIssue" + } + ] } ] }, @@ -1319,7 +1463,8 @@ "parameters": [ { "name": "origin", - "description": "Origin the permission applies to.", + "description": "Origin the permission applies to, all origins if not specified.", + "optional": true, "type": "string" }, { @@ -1347,6 +1492,8 @@ "parameters": [ { "name": "origin", + "description": "Origin the permission applies to, all origins if not specified.", + "optional": true, "type": "string" }, { @@ -1377,6 +1524,36 @@ } ] }, + { + "name": "setDownloadBehavior", + "description": "Set the behavior when downloading a file.", + "experimental": true, + "parameters": [ + { + "name": "behavior", + "description": "Whether to allow all or deny all download requests, or use default Chrome behavior if\navailable (otherwise deny). |allowAndName| allows download and names files according to\ntheir dowmload guids.", + "type": "string", + "enum": [ + "deny", + "allow", + "allowAndName", + "default" + ] + }, + { + "name": "browserContextId", + "description": "BrowserContext to set download behavior. When omitted, default browser context is used.", + "optional": true, + "$ref": "BrowserContextID" + }, + { + "name": "downloadPath", + "description": "The default path to save downloaded files to. This is requred if behavior is set to 'allow'\nor 'allowAndName'.", + "optional": true, + "type": "string" + } + ] + }, { "name": "close", "description": "Close browser gracefully." @@ -3588,6 +3765,37 @@ } ] }, + { + "name": "scrollIntoViewIfNeeded", + "description": "Scrolls the specified rect of the given node into view if not already visible.\nNote: exactly one between nodeId, backendNodeId and objectId should be passed\nto identify the node.", + "experimental": true, + "parameters": [ + { + "name": "nodeId", + "description": "Identifier of the node.", + "optional": true, + "$ref": "NodeId" + }, + { + "name": "backendNodeId", + "description": "Identifier of the backend node.", + "optional": true, + "$ref": "BackendNodeId" + }, + { + "name": "objectId", + "description": "JavaScript object id of the node wrapper.", + "optional": true, + "$ref": "Runtime.RemoteObjectId" + }, + { + "name": "rect", + "description": "The rect to be scrolled into view, relative to the node's border box, in CSS pixels.\nWhen omitted, center of the node will be used, similar to Element.scrollIntoView.", + "optional": true, + "$ref": "Rect" + } + ] + }, { "name": "disable", "description": "Disables DOM agent for the given page." @@ -6261,6 +6469,26 @@ } ] }, + { + "name": "setEmulatedVisionDeficiency", + "description": "Emulates the given vision deficiency.", + "experimental": true, + "parameters": [ + { + "name": "type", + "description": "Vision deficiency to emulate.", + "type": "string", + "enum": [ + "none", + "achromatopsia", + "blurredVision", + "deuteranopia", + "protanopia", + "tritanopia" + ] + } + ] + }, { "name": "setGeolocationOverride", "description": "Overrides the Geolocation Position or Error. Omitting any of the parameters emulates position\nunavailable.", @@ -6380,6 +6608,19 @@ } ] }, + { + "name": "setLocaleOverride", + "description": "Overrides default host system locale with the specified one.", + "experimental": true, + "parameters": [ + { + "name": "locale", + "description": "ICU style C locale (e.g. \"en_US\"). If not specified or empty, disables the override and\nrestores default host system locale.", + "optional": true, + "type": "string" + } + ] + }, { "name": "setTimezoneOverride", "description": "Overrides default host system timezone with the specified one.", @@ -8825,7 +9066,12 @@ "inspector", "subresource-filter", "content-type", - "collapsed-by-client" + "collapsed-by-client", + "coep-frame-resource-needs-coep-header", + "coop-sandboxed-iframe-cannot-navigate-to-coop-page", + "corp-not-same-origin", + "corp-not-same-origin-after-defaulted-to-same-origin-by-coep", + "corp-not-same-site" ] }, { @@ -11671,6 +11917,22 @@ } } ] + }, + { + "id": "ReferrerPolicy", + "description": "The referring-policy used for the navigation.", + "experimental": true, + "type": "string", + "enum": [ + "noReferrer", + "noReferrerWhenDowngrade", + "origin", + "originWhenCrossOrigin", + "sameOrigin", + "strictOrigin", + "strictOriginWhenCrossOrigin", + "unsafeUrl" + ] } ], "commands": [ @@ -11897,17 +12159,8 @@ "name": "getInstallabilityErrors", "experimental": true, "returns": [ - { - "name": "errors", - "deprecated": true, - "type": "array", - "items": { - "type": "string" - } - }, { "name": "installabilityErrors", - "experimental": true, "type": "array", "items": { "$ref": "InstallabilityError" @@ -12082,6 +12335,13 @@ "description": "Frame id to navigate, if not specified navigates the top frame.", "optional": true, "$ref": "FrameId" + }, + { + "name": "referrerPolicy", + "description": "Referrer-policy used for the navigation.", + "experimental": true, + "optional": true, + "$ref": "ReferrerPolicy" } ], "returns": [ @@ -12501,6 +12761,7 @@ "name": "setDownloadBehavior", "description": "Set the behavior when downloading a file.", "experimental": true, + "deprecated": true, "parameters": [ { "name": "behavior", @@ -12905,6 +13166,11 @@ "description": "Id of the frame that caused download to begin.", "$ref": "FrameId" }, + { + "name": "guid", + "description": "Global unique identifier of the download.", + "type": "string" + }, { "name": "url", "description": "URL of the resource being downloaded.", @@ -12912,6 +13178,38 @@ } ] }, + { + "name": "downloadProgress", + "description": "Fired when download makes progress. Last call has |done| == true.", + "experimental": true, + "parameters": [ + { + "name": "guid", + "description": "Global unique identifier of the download.", + "type": "string" + }, + { + "name": "totalBytes", + "description": "Total expected bytes to download.", + "type": "number" + }, + { + "name": "receivedBytes", + "description": "Total bytes received.", + "type": "number" + }, + { + "name": "state", + "description": "Download status.", + "type": "string", + "enum": [ + "inProgress", + "completed", + "canceled" + ] + } + ] + }, { "name": "interstitialHidden", "description": "Fired when interstitial page was hidden" @@ -13127,12 +13425,25 @@ }, { "name": "enable", - "description": "Enable collecting and reporting metrics." + "description": "Enable collecting and reporting metrics.", + "parameters": [ + { + "name": "timeDomain", + "description": "Time domain to use for collecting and reporting duration metrics.", + "optional": true, + "type": "string", + "enum": [ + "timeTicks", + "threadTicks" + ] + } + ] }, { "name": "setTimeDomain", "description": "Sets time domain to use for collecting and reporting duration metrics.\nNote that this must be called before enabling metrics collection. Calling\nthis method while metrics collection is enabled returns an error.", "experimental": true, + "deprecated": true, "parameters": [ { "name": "timeDomain", @@ -14601,6 +14912,14 @@ "name": "createBrowserContext", "description": "Creates a new empty BrowserContext. Similar to an incognito profile but you can have more than\none.", "experimental": true, + "parameters": [ + { + "name": "disposeOnDetach", + "description": "If specified, disposes this context when debugging session disconnects.", + "optional": true, + "type": "boolean" + } + ], "returns": [ { "name": "browserContextId", @@ -14785,13 +15104,6 @@ "description": "Enables \"flat\" access to the session via specifying sessionId attribute in the commands.\nWe plan to make this the default, deprecate non-flattened mode,\nand eventually retire it. See crbug.com/991325.", "optional": true, "type": "boolean" - }, - { - "name": "windowOpen", - "description": "Auto-attach to the targets created via window.open from current target.", - "experimental": true, - "optional": true, - "type": "boolean" } ] }, @@ -15502,7 +15814,7 @@ }, { "name": "headers", - "description": "If set, overrides the request headrts.", + "description": "If set, overrides the request headers.", "optional": true, "type": "array", "items": { @@ -16696,7 +17008,8 @@ "block", "script", "eval", - "module" + "module", + "wasm-expression-stack" ] }, { @@ -16771,6 +17084,15 @@ ] } ] + }, + { + "id": "ScriptLanguage", + "description": "Enum of possible script languages.", + "type": "string", + "enum": [ + "JavaScript", + "WebAssembly" + ] } ], "commands": [ @@ -17047,7 +17369,15 @@ }, { "name": "resume", - "description": "Resumes JavaScript execution." + "description": "Resumes JavaScript execution.", + "parameters": [ + { + "name": "terminateOnResume", + "description": "Set to true to terminate execution upon resuming execution. In contrast\nto Runtime.terminateExecution, this will allows to execute further\nJavaScript (i.e. via evaluation) until execution of the paused code\nis actually resumed, at which point termination is triggered.\nIf execution is currently not paused, this parameter has no effect.", + "optional": true, + "type": "boolean" + } + ] }, { "name": "searchInContent", @@ -17589,6 +17919,20 @@ "experimental": true, "optional": true, "$ref": "Runtime.StackTrace" + }, + { + "name": "codeOffset", + "description": "If the scriptLanguage is WebAssembly, the code section offset in the module.", + "experimental": true, + "optional": true, + "type": "integer" + }, + { + "name": "scriptLanguage", + "description": "The language of the script.", + "experimental": true, + "optional": true, + "$ref": "Debugger.ScriptLanguage" } ] }, @@ -17679,6 +18023,20 @@ "experimental": true, "optional": true, "$ref": "Runtime.StackTrace" + }, + { + "name": "codeOffset", + "description": "If the scriptLanguage is WebAssembly, the code section offset in the module.", + "experimental": true, + "optional": true, + "type": "integer" + }, + { + "name": "scriptLanguage", + "description": "The language of the script.", + "experimental": true, + "optional": true, + "$ref": "Debugger.ScriptLanguage" } ] } @@ -18278,6 +18636,12 @@ "description": "Collect block-based coverage.", "optional": true, "type": "boolean" + }, + { + "name": "allowTriggeredUpdates", + "description": "Allow the backend to send updates on its own initiative", + "optional": true, + "type": "boolean" } ], "returns": [ @@ -18481,12 +18845,13 @@ "number", "boolean", "symbol", - "bigint" + "bigint", + "wasm" ] }, { "name": "subtype", - "description": "Object subtype hint. Specified for `object` type values only.", + "description": "Object subtype hint. Specified for `object` or `wasm` type values only.", "optional": true, "type": "string", "enum": [ @@ -18506,7 +18871,12 @@ "promise", "typedarray", "arraybuffer", - "dataview" + "dataview", + "i32", + "i64", + "f32", + "f64", + "v128" ] }, { @@ -19302,7 +19672,7 @@ }, { "name": "replMode", - "description": "Reserved flag for future REPL mode support. Setting this flag has currently no effect.", + "description": "Setting this flag to true enables `let` re-declaration and top-level `await`.\nNote that `let` variables can only be re-declared if they originate from\n`replMode` themselves.", "experimental": true, "optional": true, "type": "boolean"