blob: 3b3506c29acf166f9a6b62a1169bdefafcbacbce [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/reporting/reporting.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/deprecation_report_body.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/report.h"
#include "third_party/blink/renderer/core/frame/reporting_context.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
namespace blink {
namespace {
const char kChromeLoadTimesNavigationTiming[] =
"chrome.loadTimes() is deprecated, instead use standardized API: "
"Navigation Timing 2. "
"https://www.chromestatus.com/features/5637885046816768.";
const char kChromeLoadTimesNextHopProtocol[] =
"chrome.loadTimes() is deprecated, instead use standardized API: "
"nextHopProtocol in Navigation Timing 2. "
"https://www.chromestatus.com/features/5637885046816768.";
const char kChromeLoadTimesPaintTiming[] =
"chrome.loadTimes() is deprecated, instead use standardized API: "
"Paint Timing. "
"https://www.chromestatus.com/features/5637885046816768.";
enum Milestone {
kUnknown,
kM61 = 61,
kM62 = 62,
kM64 = 64,
kM65 = 65,
kM70 = 70,
kM71 = 71,
kM72 = 72,
kM75 = 75,
kM76 = 76,
kM77 = 77,
kM78 = 78,
kM79 = 79,
kM80 = 80,
kM81 = 81,
kM82 = 82,
kM83 = 83,
kM84 = 84,
kM85 = 85,
kM86 = 86,
kM87 = 87,
kM88 = 88,
kM89 = 89,
kM90 = 90,
kM91 = 91,
kM92 = 92,
kM93 = 93,
kM94 = 94,
kM95 = 95,
kM96 = 96,
};
// Returns estimated milestone dates as milliseconds since January 1, 1970.
base::Time::Exploded MilestoneDate(Milestone milestone) {
// These are the Estimated Stable Dates:
// https://www.chromium.org/developers/calendar
// All dates except for kUnknown are at 04:00:00 GMT.
switch (milestone) {
case kUnknown:
break;
case kM61:
return {2017, 9, 0, 5, 4};
case kM62:
return {2017, 10, 0, 17, 4};
case kM64:
return {2018, 1, 0, 23, 4};
case kM65:
return {2018, 3, 0, 6, 4};
case kM70:
return {2018, 10, 0, 16, 4};
case kM71:
return {2018, 12, 0, 4, 4};
case kM72:
return {2019, 1, 0, 29, 4};
case kM75:
return {2019, 6, 0, 4, 4};
case kM76:
return {2019, 7, 0, 30, 4};
case kM77:
return {2019, 9, 0, 10, 4};
case kM78:
return {2019, 10, 0, 22, 4};
case kM79:
return {2019, 12, 0, 10, 4};
case kM80:
return {2020, 2, 0, 4, 4};
case kM81:
return {2020, 4, 0, 7, 4};
case kM82:
// This release was cancelled, so this is the (new) M83 date.
// https://groups.google.com/a/chromium.org/d/msg/chromium-dev/N1NxbSVOZas/ySlEKDKkBgAJ
return {2020, 5, 0, 18, 4};
case kM83:
return {2020, 5, 0, 18, 4};
case kM84:
return {2020, 7, 0, 14, 4};
case kM85:
return {2020, 8, 0, 25, 4};
case kM86:
return {2020, 10, 0, 6, 4};
case kM87:
return {2020, 11, 0, 17, 4};
case kM88:
return {2021, 1, 0, 19, 4};
case kM89:
return {2021, 3, 0, 2, 4};
case kM90:
return {2021, 4, 0, 13, 4};
case kM91:
return {2021, 5, 0, 25, 4};
case kM92:
return {2021, 7, 0, 20, 4};
case kM93:
return {2021, 8, 0, 31, 4};
case kM94:
return {2021, 10, 0, 12, 4};
case kM95:
return {2021, 11, 0, 30, 4};
case kM96:
return {2022, 1, 0, 25, 4};
}
NOTREACHED();
return {1970, 1, 0, 1, 0};
}
// Returns estimated milestone dates as human-readable strings.
String MilestoneString(Milestone milestone) {
if (milestone == kUnknown)
return "";
base::Time::Exploded date = MilestoneDate(milestone);
return String::Format("M%d, around %s %d", milestone,
WTF::kMonthFullName[date.month - 1], date.year);
}
struct DeprecationInfo {
String id;
Milestone anticipated_removal;
String message;
};
String ReplacedBy(const char* feature, const char* replacement) {
return String::Format("%s is deprecated. Please use %s instead.", feature,
replacement);
}
String WillBeRemoved(const char* feature,
Milestone milestone,
const char* details) {
return String::Format(
"%s is deprecated and will be removed in %s. See "
"https://www.chromestatus.com/features/%s for more details.",
feature, MilestoneString(milestone).Ascii().c_str(), details);
}
String ReplacedWillBeRemoved(const char* feature,
const char* replacement,
Milestone milestone,
const char* details) {
return String::Format(
"%s is deprecated and will be removed in %s. Please use %s instead. See "
"https://www.chromestatus.com/features/%s for more details.",
feature, MilestoneString(milestone).Ascii().c_str(), replacement,
details);
}
DeprecationInfo GetDeprecationInfo(WebFeature feature) {
switch (feature) {
// Quota
case WebFeature::kPrefixedStorageInfo:
return {"PrefixedStorageInfo", kUnknown,
ReplacedBy("'window.webkitStorageInfo'",
"'navigator.webkitTemporaryStorage' or "
"'navigator.webkitPersistentStorage'")};
case WebFeature::kPrefixedVideoSupportsFullscreen:
return {"PrefixedVideoSupportsFullscreen", kUnknown,
ReplacedBy("'HTMLVideoElement.webkitSupportsFullscreen'",
"'Document.fullscreenEnabled'")};
case WebFeature::kPrefixedVideoDisplayingFullscreen:
return {"PrefixedVideoDisplayingFullscreen", kUnknown,
ReplacedBy("'HTMLVideoElement.webkitDisplayingFullscreen'",
"'Document.fullscreenElement'")};
case WebFeature::kPrefixedVideoEnterFullscreen:
return {"PrefixedVideoEnterFullscreen", kUnknown,
ReplacedBy("'HTMLVideoElement.webkitEnterFullscreen()'",
"'Element.requestFullscreen()'")};
case WebFeature::kPrefixedVideoExitFullscreen:
return {"PrefixedVideoExitFullscreen", kUnknown,
ReplacedBy("'HTMLVideoElement.webkitExitFullscreen()'",
"'Document.exitFullscreen()'")};
case WebFeature::kPrefixedVideoEnterFullScreen:
return {"PrefixedVideoEnterFullScreen", kUnknown,
ReplacedBy("'HTMLVideoElement.webkitEnterFullScreen()'",
"'Element.requestFullscreen()'")};
case WebFeature::kPrefixedVideoExitFullScreen:
return {"PrefixedVideoExitFullScreen", kUnknown,
ReplacedBy("'HTMLVideoElement.webkitExitFullScreen()'",
"'Document.exitFullscreen()'")};
case WebFeature::kPrefixedRequestAnimationFrame:
return {"PrefixedRequestAnimationFrame", kUnknown,
"'webkitRequestAnimationFrame' is vendor-specific. Please use "
"the standard 'requestAnimationFrame' instead."};
case WebFeature::kPrefixedCancelAnimationFrame:
return {"PrefixedCancelAnimationFrame", kUnknown,
"'webkitCancelAnimationFrame' is vendor-specific. Please use the "
"standard 'cancelAnimationFrame' instead."};
case WebFeature::kPictureSourceSrc:
return {"PictureSourceSrc", kUnknown,
"<source src> with a <picture> parent is invalid and therefore "
"ignored. Please use <source srcset> instead."};
case WebFeature::kXMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload:
return {"XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload",
kUnknown,
"Synchronous XMLHttpRequest on the main thread is deprecated "
"because of its detrimental effects to the end user's "
"experience. For more help, check https://xhr.spec.whatwg.org/."};
case WebFeature::kPrefixedWindowURL:
return {"PrefixedWindowURL", kUnknown,
ReplacedBy("'webkitURL'", "'URL'")};
case WebFeature::kRangeExpand:
return {"RangeExpand", kUnknown,
ReplacedBy("'Range.expand()'", "'Selection.modify()'")};
// Blocked subresource requests:
case WebFeature::kLegacyProtocolEmbeddedAsSubresource:
return {"LegacyProtocolEmbeddedAsSubresource", kUnknown,
"Subresource requests using legacy protocols (like `ftp:`) "
"are blocked. Please deliver web-accessible resources over "
"modern protocols like HTTPS. See "
"https://www.chromestatus.com/feature/5709390967472128 for "
"details."};
case WebFeature::kRequestedSubresourceWithEmbeddedCredentials:
return {"RequestedSubresourceWithEmbeddedCredentials", kUnknown,
"Subresource requests whose URLs contain embedded credentials "
"(e.g. `https://user:pass@host/`) are blocked. See "
"https://www.chromestatus.com/feature/5669008342777856 for more "
"details."};
// Powerful features on insecure origins (https://goo.gl/rStTGz)
case WebFeature::kGeolocationInsecureOrigin:
case WebFeature::kGeolocationInsecureOriginIframe:
return {"GeolocationInsecureOrigin", kUnknown,
"getCurrentPosition() and watchPosition() no longer work on "
"insecure origins. To use this feature, you should consider "
"switching your application to a secure origin, such as HTTPS. "
"See https://goo.gl/rStTGz for more details."};
case WebFeature::kGeolocationInsecureOriginDeprecatedNotRemoved:
case WebFeature::kGeolocationInsecureOriginIframeDeprecatedNotRemoved:
return {"GeolocationInsecureOriginDeprecatedNotRemoved", kUnknown,
"getCurrentPosition() and watchPosition() are deprecated on "
"insecure origins. To use this feature, you should consider "
"switching your application to a secure origin, such as HTTPS. "
"See https://goo.gl/rStTGz for more details."};
case WebFeature::kGetUserMediaInsecureOrigin:
case WebFeature::kGetUserMediaInsecureOriginIframe:
return {
"GetUserMediaInsecureOrigin", kUnknown,
"getUserMedia() no longer works on insecure origins. To use this "
"feature, you should consider switching your application to a "
"secure origin, such as HTTPS. See https://goo.gl/rStTGz for more "
"details."};
case WebFeature::kMediaSourceAbortRemove:
return {
"MediaSourceAbortRemove", kUnknown,
"Using SourceBuffer.abort() to abort remove()'s asynchronous "
"range removal is deprecated due to specification change. Support "
"will be removed in the future. You should instead await "
"'updateend'. abort() is intended to only abort an asynchronous "
"media append or reset parser state. See "
"https://www.chromestatus.com/features/6107495151960064 for more "
"details."};
case WebFeature::kMediaSourceDurationTruncatingBuffered:
return {
"MediaSourceDurationTruncatingBuffered", kUnknown,
"Setting MediaSource.duration below the highest presentation "
"timestamp of any buffered coded frames is deprecated due to "
"specification change. Support for implicit removal of truncated "
"buffered media will be removed in the future. You should instead "
"perform explicit remove(newDuration, oldDuration) on all "
"sourceBuffers, where newDuration < oldDuration. See "
"https://www.chromestatus.com/features/6107495151960064 for more "
"details."};
case WebFeature::kApplicationCacheAPIInsecureOrigin:
case WebFeature::kApplicationCacheManifestSelectInsecureOrigin:
return {"ApplicationCacheAPIInsecureOrigin", kM70,
"Application Cache was previously restricted to secure origins "
"only from M70 on but now secure origin use is deprecated and "
"will be removed in M82. Please shift your use case over to "
"Service Workers."};
case WebFeature::kApplicationCacheAPISecureOrigin:
return {
"ApplicationCacheAPISecureOrigin", kM85,
WillBeRemoved("Application Cache API use", kM85, "6192449487634432")};
case WebFeature::kApplicationCacheManifestSelectSecureOrigin:
return {"ApplicationCacheAPISecureOrigin", kM85,
WillBeRemoved("Application Cache API manifest selection", kM85,
"6192449487634432")};
case WebFeature::kNotificationInsecureOrigin:
case WebFeature::kNotificationAPIInsecureOriginIframe:
case WebFeature::kNotificationPermissionRequestedInsecureOrigin:
return {"NotificationInsecureOrigin", kUnknown,
"The Notification API may no longer be used from insecure "
"origins. "
"You should consider switching your application to a secure "
"origin, "
"such as HTTPS. See https://goo.gl/rStTGz for more details."};
case WebFeature::kNotificationPermissionRequestedIframe:
return {"NotificationPermissionRequestedIframe", kUnknown,
"Permission for the Notification API may no longer be requested "
"from "
"a cross-origin iframe. You should consider requesting "
"permission "
"from a top-level frame or opening a new window instead. See "
"https://www.chromestatus.com/feature/6451284559265792 for more "
"details."};
case WebFeature::kCSSSelectorInternalMediaControlsOverlayCastButton:
return {"CSSSelectorInternalMediaControlsOverlayCastButton", kUnknown,
"The disableRemotePlayback attribute should be used in order to "
"disable the default Cast integration instead of using "
"-internal-media-controls-overlay-cast-button selector. See "
"https://www.chromestatus.com/feature/5714245488476160 for more "
"details."};
case WebFeature::kSelectionAddRangeIntersect:
return {
"SelectionAddRangeIntersect", kUnknown,
"The behavior that Selection.addRange() merges existing Range and "
"the specified Range was removed. See "
"https://www.chromestatus.com/features/6680566019653632 for more "
"details."};
case WebFeature::kRtcpMuxPolicyNegotiate:
return {"RtcpMuxPolicyNegotiate", kM62,
String::Format("The rtcpMuxPolicy option is being considered for "
"removal and may be removed no earlier than %s. "
"If you depend on it, "
"please see "
"https://www.chromestatus.com/features/"
"5654810086866944 "
"for more details.",
MilestoneString(kM62).Ascii().c_str())};
case WebFeature::kCanRequestURLHTTPContainingNewline:
return {
"CanRequestURLHTTPContainingNewline", kUnknown,
"Resource requests whose URLs contained both removed whitespace "
"(`\\n`, `\\r`, `\\t`) characters and less-than characters (`<`) "
"are blocked. Please remove newlines and encode less-than "
"characters from places like element attribute values in order to "
"load these resources. See "
"https://www.chromestatus.com/feature/5735596811091968 for more "
"details."};
case WebFeature::kHTMLImports:
return {"HTMLImports", kUnknown,
"The HTML Imports feature has been removed. See "
"https://www.chromestatus.com/feature/5144752345317376 for more "
"details."};
case WebFeature::kLocalCSSFileExtensionRejected:
return {"LocalCSSFileExtensionRejected", kM64,
String("CSS cannot be loaded from `file:` URLs unless they end "
"in a `.css` file extension.")};
case WebFeature::kChromeLoadTimesRequestTime:
case WebFeature::kChromeLoadTimesStartLoadTime:
case WebFeature::kChromeLoadTimesCommitLoadTime:
case WebFeature::kChromeLoadTimesFinishDocumentLoadTime:
case WebFeature::kChromeLoadTimesFinishLoadTime:
case WebFeature::kChromeLoadTimesNavigationType:
case WebFeature::kChromeLoadTimesConnectionInfo:
return {"ChromeLoadTimesConnectionInfo", kUnknown,
kChromeLoadTimesNavigationTiming};
case WebFeature::kChromeLoadTimesFirstPaintTime:
case WebFeature::kChromeLoadTimesFirstPaintAfterLoadTime:
return {"ChromeLoadTimesFirstPaintAfterLoadTime", kUnknown,
kChromeLoadTimesPaintTiming};
case WebFeature::kChromeLoadTimesWasFetchedViaSpdy:
case WebFeature::kChromeLoadTimesWasNpnNegotiated:
case WebFeature::kChromeLoadTimesNpnNegotiatedProtocol:
case WebFeature::kChromeLoadTimesWasAlternateProtocolAvailable:
return {"ChromeLoadTimesWasAlternateProtocolAvailable", kUnknown,
kChromeLoadTimesNextHopProtocol};
case WebFeature::kMediaElementSourceOnOfflineContext:
return {"MediaElementAudioSourceNode", kM71,
WillBeRemoved("Creating a MediaElementAudioSourceNode on an "
"OfflineAudioContext",
kM71, "5258622686724096")};
case WebFeature::kMediaStreamDestinationOnOfflineContext:
return {"MediaStreamAudioDestinationNode", kM71,
WillBeRemoved("Creating a MediaStreamAudioDestinationNode on an "
"OfflineAudioContext",
kM71, "5258622686724096")};
case WebFeature::kMediaStreamSourceOnOfflineContext:
return {
"MediaStreamAudioSourceNode", kM71,
WillBeRemoved(
"Creating a MediaStreamAudioSourceNode on an OfflineAudioContext",
kM71, "5258622686724096")};
case WebFeature::kTextToSpeech_SpeakDisallowedByAutoplay:
return {
"TextToSpeech_DisallowedByAutoplay", kM71,
String::Format("speechSynthesis.speak() without user activation is "
"no longer allowed since %s. See "
"https://www.chromestatus.com/feature/"
"5687444770914304 for more details",
MilestoneString(kM71).Ascii().c_str())};
case WebFeature::kRTCPeerConnectionComplexPlanBSdpUsingDefaultSdpSemantics:
return {"RTCPeerConnectionComplexPlanBSdpUsingDefaultSdpSemantics", kM72,
String::Format(
"\"Complex\" Plan B SDP detected! Chrome will switch the "
"default sdpSemantics in %s from 'plan-b' to the "
"standardized 'unified-plan' format and this peer connection "
"is relying on the default sdpSemantics. This SDP is not "
"compatible with Unified Plan and will be rejected by "
"clients expecting Unified Plan. For more information about "
"how to prepare for the switch, see "
"https://webrtc.org/web-apis/chrome/unified-plan/.",
MilestoneString(kM72).Ascii().c_str())};
case WebFeature::kNoSysexWebMIDIWithoutPermission:
return {"NoSysexWebMIDIWithoutPermission", kM82,
String::Format(
"Web MIDI will ask a permission to use even if the sysex is "
"not specified in the MIDIOptions since around %s. See "
"https://www.chromestatus.com/feature/5138066234671104 for "
"more details.",
MilestoneString(kM82).Ascii().c_str())};
case WebFeature::kCustomCursorIntersectsViewport:
return {
"CustomCursorIntersectsViewport", kM75,
WillBeRemoved(
"Custom cursors with size greater than 32x32 DIP intersecting "
"native UI",
kM75, "5825971391299584")};
case WebFeature::kXRSupportsSession:
return {"XRSupportsSession", kM80,
ReplacedBy(
"supportsSession()",
"isSessionSupported() and check the resolved boolean value")};
case WebFeature::kObsoleteWebrtcTlsVersion:
return {"ObsoleteWebRtcCipherSuite", kM81,
String::Format(
"Your partner is negotiating an obsolete (D)TLS version. "
"Support for this will be removed in %s. "
"Please check with your partner to have this fixed.",
MilestoneString(kM81).Ascii().c_str())};
case WebFeature::kCssStyleSheetReplaceWithImport:
return {
"CssStyleSheetReplaceWithImport", kM84,
String::Format(
"Support for calls to CSSStyleSheet.replace() with stylesheet "
"text that includes @import has been deprecated, and will be "
"removed in %s. See "
"https://chromestatus.com/feature/4735925877735424 for more "
"details.",
MilestoneString(kM84).Ascii().c_str())};
case WebFeature::kV8SharedArrayBufferConstructedWithoutIsolation:
return {
"SharedArrayBufferConstructedWithoutIsolation", kM91,
String::Format(
"SharedArrayBuffer will require cross-origin isolation as of "
"%s. See "
"https://developer.chrome.com/blog/enabling-shared-array-buffer/"
" for more details.",
MilestoneString(kM91).Ascii().c_str())};
case WebFeature::kV8RTCRtpSender_CreateEncodedAudioStreams_Method:
return {"V8RTCRtpSender_CreateEncodedAudioStreams_Method", kM88,
ReplacedWillBeRemoved("RTCRtpSender.createEncodedAudioStreams",
"RTCRtpSender.createEncodedStreams", kM88,
"6321945865879552")};
case WebFeature::kV8RTCRtpSender_CreateEncodedVideoStreams_Method:
return {"V8RTCRtpSender_CreateEncodedVideoStreams_Method", kM88,
ReplacedWillBeRemoved("RTCRtpSender.createEncodedVideoStreams",
"RTCRtpSender.createEncodedStreams", kM88,
"6321945865879552")};
case WebFeature::kV8RTCRtpReceiver_CreateEncodedAudioStreams_Method:
return {"V8RTCRtpReceiver_CreateEncodedAudioStreams_Method", kM88,
ReplacedWillBeRemoved("RTCRtpReceiver.createEncodedAudioStreams",
"RTCRtpReceiver.createEncodedStreams", kM88,
"6321945865879552")};
case WebFeature::kV8RTCRtpReceiver_CreateEncodedVideoStreams_Method:
return {"V8RTCRtpReceiver_CreateEncodedVideoStreams_Method", kM88,
ReplacedWillBeRemoved("RTCRtpReceiver.createEncodedVideoStreams",
"RTCRtpReceiver.createEncodedStreams", kM88,
"6321945865879552")};
case WebFeature::kForceEncodedAudioInsertableStreams:
return {"ForceEncodedAudioInsertableStreams", kM88,
ReplacedWillBeRemoved(
"RTCConfiguration.forceEncodedAudioInsertableStreams",
"RTCConfiguration.encodedInsertableStreams", kM88,
"6321945865879552")};
case WebFeature::kForceEncodedVideoInsertableStreams:
return {"ForceEncodedVideoInsertableStreams", kM88,
ReplacedWillBeRemoved(
"RTCConfiguration.forceEncodedVideoInsertableStreams",
"RTCConfiguration.encodedInsertableStreams", kM88,
"6321945865879552")};
case WebFeature::kRTCConstraintEnableRtpDataChannelsFalse:
case WebFeature::kRTCConstraintEnableRtpDataChannelsTrue:
return {
"RTP data channel", kM88,
"RTP data channels are no longer supported. "
"The \"RtpDataChannels\" constraint is currently ignored, and may "
"cause an error at a later date."};
case WebFeature::kCSSSelectorWebkitDetailsMarker:
if (!RuntimeEnabledFeatures::SummaryListItemEnabled())
return {"NotDeprecated", kUnknown, ""};
return {"CSSSeelctorWebKitDetailsMarker", kM89,
ReplacedBy("::-webkit-details-marker pseudo element selector",
"::marker") +
" See https://chromestatus.com/feature/6730096436051968 for "
"more details."};
case WebFeature::kV8SpeechRecognitionEvent_Interpretation_AttributeGetter:
return {"V8SpeechRecognitionEvent_Interpretation_AttributeGetter", kM91,
WillBeRemoved("SpeechRecognitionEvent's interpretation attribute",
kM91, "5769608873115648")};
case WebFeature::kV8SpeechRecognitionEvent_Emma_AttributeGetter:
return {"V8SpeechRecognitionEvent_Emma_AttributeGetter", kM91,
WillBeRemoved("SpeechRecognitionEvent's emma attribute", kM91,
"5769608873115648")};
case WebFeature::kRTCPeerConnectionSdpSemanticsPlanB:
return {"RTCPeerConnectionSdpSemanticsPlanB", kM93,
"Plan B SDP semantics, which is used when constructing an "
"RTCPeerConnection with {sdpSemantics:\"plan-b\"}, is a legacy "
"version of the Session Description Protocol that has severe "
"compatibility issues on modern browsers. The standardized SDP "
"format, \"unified-plan\", has been used by default since M72 "
"(January, 2019). Dropping support for Plan B is targeted for "
"M93 (Canary: July 15, 2021; Stable: August 24, 2021)."};
case WebFeature::kRTCPeerConnectionSdpSemanticsPlanBWithReverseOriginTrial:
return {"RTCPeerConnectionSdpSemanticsPlanBWithReverseOriginTrial", kM96,
"Plan B SDP semantics, which is used when constructing an "
"RTCPeerConnection with {sdpSemantics:\"plan-b\"}, is a legacy "
"version of the Session Description Protocol that has severe "
"compatibility issues on modern browsers. The standardized SDP "
"format, \"unified-plan\", has been used by default since M72 "
"(January, 2019). Dropping support for Plan B is targeted for "
"M93 (Canary: July 15, 2021; Stable: August 24, 2021), but "
"because you have opted in to the Reverse Origin Trial, you have "
"until M96 (Canary: November, 2021; Stable: January, 2022)."};
case WebFeature::kAddressSpaceUnknownNonSecureContextEmbeddedPrivate:
case WebFeature::kAddressSpaceUnknownNonSecureContextEmbeddedLocal:
case WebFeature::kAddressSpacePublicNonSecureContextEmbeddedPrivate:
case WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLocal:
case WebFeature::kAddressSpacePrivateNonSecureContextEmbeddedLocal:
return {"InsecurePrivateNetworkSubresourceRequest", kM92,
"The website requested a subresource from a "
"network that it could only access because of its users' "
"privileged network position. These requests expose non-public "
"devices and servers to the internet, increasing the risk of a "
"cross-site request forgery (CSRF) attack, and/or information "
"leakage. To mitigate these risks, Chrome deprecates requests to "
"non-public subresources when initiated from non-secure "
"contexts, and will start blocking them in Chrome 92 (July "
"2021). See https://chromestatus.com/feature/5436853517811712 "
"for more details."};
// Features that aren't deprecated don't have a deprecation message.
default:
return {"NotDeprecated", kUnknown, ""};
}
}
Report* CreateReportInternal(const KURL& context_url,
const DeprecationInfo& info) {
base::Optional<base::Time> optional_removal_date;
if (info.anticipated_removal != kUnknown) {
base::Time removal_date;
bool result = base::Time::FromUTCExploded(
MilestoneDate(info.anticipated_removal), &removal_date);
DCHECK(result);
optional_removal_date = removal_date;
}
DeprecationReportBody* body = MakeGarbageCollected<DeprecationReportBody>(
info.id, optional_removal_date, info.message);
return MakeGarbageCollected<Report>(ReportType::kDeprecation, context_url,
body);
}
} // anonymous namespace
Deprecation::Deprecation() : mute_count_(0) {}
void Deprecation::ClearSuppression() {
css_property_deprecation_bits_.reset();
features_deprecation_bits_.reset();
}
void Deprecation::MuteForInspector() {
mute_count_++;
}
void Deprecation::UnmuteForInspector() {
mute_count_--;
}
void Deprecation::Suppress(CSSPropertyID unresolved_property) {
DCHECK(IsCSSPropertyIDWithName(unresolved_property));
css_property_deprecation_bits_.set(static_cast<size_t>(unresolved_property));
}
bool Deprecation::IsSuppressed(CSSPropertyID unresolved_property) {
DCHECK(IsCSSPropertyIDWithName(unresolved_property));
return css_property_deprecation_bits_[static_cast<size_t>(
unresolved_property)];
}
void Deprecation::SetReported(WebFeature feature) {
features_deprecation_bits_.set(static_cast<size_t>(feature));
}
bool Deprecation::GetReported(WebFeature feature) const {
return features_deprecation_bits_[static_cast<size_t>(feature)];
}
void Deprecation::WarnOnDeprecatedProperties(
const LocalFrame* frame,
CSSPropertyID unresolved_property) {
Page* page = frame ? frame->GetPage() : nullptr;
if (!page || page->GetDeprecation().mute_count_ ||
page->GetDeprecation().IsSuppressed(unresolved_property))
return;
String message = DeprecationMessage(unresolved_property);
if (!message.IsEmpty()) {
page->GetDeprecation().Suppress(unresolved_property);
auto* console_message = MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kDeprecation,
mojom::ConsoleMessageLevel::kWarning, message);
frame->Console().AddMessage(console_message);
}
}
String Deprecation::DeprecationMessage(CSSPropertyID unresolved_property) {
// TODO: Add a switch here when there are properties that we intend to
// deprecate.
// Returning an empty string for now.
return g_empty_string;
}
void Deprecation::CountDeprecationCrossOriginIframe(LocalDOMWindow* window,
WebFeature feature) {
DCHECK(window);
if (!window->GetFrame())
return;
// Check to see if the frame can script into the top level context.
Frame& top = window->GetFrame()->Tree().Top();
if (!window->GetSecurityOrigin()->CanAccess(
top.GetSecurityContext()->GetSecurityOrigin())) {
CountDeprecation(window, feature);
}
}
void Deprecation::CountDeprecation(ExecutionContext* context,
WebFeature feature) {
if (!context)
return;
Deprecation* deprecation = nullptr;
if (auto* window = DynamicTo<LocalDOMWindow>(context)) {
if (window->GetFrame())
deprecation = &window->GetFrame()->GetPage()->GetDeprecation();
} else if (auto* scope = DynamicTo<WorkerOrWorkletGlobalScope>(context)) {
// TODO(crbug.com/1146824): Remove this once PlzDedicatedWorker and
// PlzServiceWorker ship.
if (!scope->IsInitialized()) {
return;
}
deprecation = &scope->GetDeprecation();
}
if (!deprecation || deprecation->mute_count_ ||
deprecation->GetReported(feature)) {
return;
}
deprecation->SetReported(feature);
// Don't count usage of WebComponentsV0 for chrome:// URLs, but still report
// the deprecation messages.
// Note that this only applies to HTML Imports, as Shadow DOM v0 and Custom
// Elements v0 have both now been removed.
bool count_usage = true;
if (context->Url().ProtocolIs("chrome") &&
feature == WebFeature::kHTMLImports) {
count_usage = false;
}
if (count_usage)
context->CountUse(feature);
const DeprecationInfo info = GetDeprecationInfo(feature);
// Send the deprecation message to the console as a warning.
DCHECK(!info.message.IsEmpty());
auto* console_message = MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kDeprecation,
mojom::ConsoleMessageLevel::kWarning, info.message);
context->AddConsoleMessage(console_message);
Report* report = CreateReportInternal(context->Url(), info);
// Send the deprecation report to the Reporting API and any
// ReportingObservers.
ReportingContext::From(context)->QueueReport(report);
}
// static
String Deprecation::DeprecationMessage(WebFeature feature) {
return GetDeprecationInfo(feature).message;
}
} // namespace blink