Google today launched Chrome 73 for Windows, Mac, Linux, Android, and iOS. The release includes support for hardware media keys, PWAs and dark mode on Mac, and the usual slew of developer features. You can update to the latest version now using Chrome’s built-in updater or download it directly from google.com/chrome.

With over 1 billion users, Chrome is both a browser and a major platform that web developers must consider. In fact, with Chrome’s regular additions and changes, developers often must stay on top of everything available — as well as what has been deprecated or removed — most notably, Chrome 73 removes drive-by downloads in sandboxed iframes.

New media features

If you have a keyboard or headset with media playback keys (play/pause, previous track, next track, and so on), Chrome now supports those. If you press the pause key, for example, the active media element playing in Chrome will be paused and receive a “paused” media event. If the play key is pressed, the previously paused media element will be resumed and receive a “play” media event. Best of all, this all works whether Chrome is in the foreground or the background. In Chrome OS, you can pause and resume audio across Chrome, Chrome Apps, and Android Apps.

Chrome 73 adds support for Auto Picture-in-Picture for installed Progressive Web Apps (PWAs) on the desktop. This can be handy for when, say, you’re on a conference call and are switching between apps or tabs. The video element has received a new autopictureinpicture attribute to make this possible. It works like this:

  • When document becomes hidden, the video element whose autopictureinpicture attribute was set most recently automatically enters Picture-in-Picture, if allowed.
  • When document becomes visible, the video element in Picture-in-Picture automatically leaves it.

Also for installed PWAs, Chrome now supports autoplay with sound on desktop, just like it does on mobile. Google is presumably making this change despite its war on autoplay with sound because users expect different experiences from apps than websites.

All of this brings us to the bigger PWA news.

PWAs and dark mode

Chrome 73 supports PWAs on macOS. These apps install and behave like native apps (they don’t show the address bar or tabs). Google killed off Chrome apps last year and has been focusing on PWAs ever since. Adding Mac support means Chrome now supports PWAs on all desktop and mobile platforms: Windows, Mac, Linux, Chrome OS, Android, and iOS.

But Google isn’t done. It plans to add new web platform capabilities that give developers access to the file system, wake lock, policy installation for enterprises, and even an ambient badge on the address bar to let users know a PWA can be installed.

Here’s Google’s pitch to developers:

A Progressive Web App is fast, and reliably so; always loading and performing at the same speed, regardless of network connection. They provide rich, engaging experiences via modern web features that take full advantage of the device capabilities.

Users can install your PWA from Chrome’s context menu, or you can directly promote the installation experience using the beforeinstallprompt event. Once installed, a PWA integrates with the OS to behave like a native application: users find and launch them from the same place as other apps, they run in their own window, they appear in the task switcher, their icons can show notification badging, and so on.

If you’re a developer, you should check out the standard PWA criteria that Chrome will check. If your PWA passes, Chrome will fire the beforeinstallprompt event, which you can add to with prompt().

Speaking of Macs, Chrome now also supports dark mode on Apple’s desktop operating system. Dark mode for Windows is on the way, the team promises.

Android and iOS

Chrome 73 for Android is rolling out slowly on Google Play. It includes stability and performance improvements, plus two additions:

  • Offline Content on the Dino Page: easily browse suggested articles while offline
  • Lite pages: get optimized pages that save data and load faster

Google unveiled Chrome Lite Pages earlier today.

Chrome 73 for iOS is available on Apple’s App Store with the following changelog:

  • If forms aren’t filled in automatically, you can now tap on the icons above the keyboard and easily access your saved passwords, addresses and credit card information.
  • Updated default search engines list. You can always choose your own favorite to be the default by performing a search on that website in Chrome, then visit Chrome settings to add the search engine.
  • If you’re a website developer, you can now view JavaScript console messages. Navigate to chrome://inspect to enable, then perform desired actions in another tab. Switch back to the same chrome://inspect tab to view any printed JavaScript console logs.

The last one will be particularly helpful for developers with iOS devices.

Security fixes and improvements

Chrome 73 also implements 60 security fixes. The following were found by external researchers:

  • [$TBD][913964] High CVE-2019-5787: Use after free in Canvas. Reported by Zhe Jin(金哲),Luyao Liu(刘路遥) from Chengdu Security Response Center of Qihoo 360 Technology Co. Ltd on 2018-12-11
  • [$N/A][925864] High CVE-2019-5788: Use after free in FileAPI. Reported by Mark Brand of Google Project Zero on 2019-01-28
  • [$N/A][921581] High CVE-2019-5789: Use after free in WebMIDI. Reported by Mark Brand of Google Project Zero on 2019-01-14
  • [$7500][914736] High CVE-2019-5790: Heap buffer overflow in V8. Reported by Dimitri Fourny (Blue Frost Security) on 2018-12-13
  • [$1000][926651] High CVE-2019-5791: Type confusion in V8. Reported by Choongwoo Han of Naver Corporation on 2019-01-30
  • [$500][914983] High CVE-2019-5792: Integer overflow in PDFium. Reported by pdknsk on 2018-12-13
  • [$TBD][937487] Medium CVE-2019-5793: Excessive permissions for private API in Extensions. Reported by Jun Kokatsu, Microsoft Browser Vulnerability Research on 2019-03-01
  • [$TBD][935175] Medium CVE-2019-5794: Security UI spoofing. Reported by Juno Im of Theori on 2019-02-24
  • [$N/A][919643] Medium CVE-2019-5795: Integer overflow in PDFium. Reported by pdknsk on 2019-01-07
  • [$N/A][918861] Medium CVE-2019-5796: Race condition in Extensions. Reported by Mark Brand of Google Project Zero on 2019-01-03
  • [$N/A][916523] Medium CVE-2019-5797: Race condition in DOMStorage. Reported by Mark Brand of Google Project Zero on 2018-12-19
  • [$N/A][883596] Medium CVE-2019-5798: Out of bounds read in Skia. Reported by Tran Tien Hung (@hungtt28) of Viettel Cyber Security on 2018-09-13
  • [$1000][905301] Medium CVE-2019-5799: CSP bypass with blob URL. Reported by sohalt on 2018-11-14
  • [$1000][894228] Medium CVE-2019-5800: CSP bypass with blob URL. Reported by Jun Kokatsu (@shhnjk) on 2018-10-10
  • [$500][921390] Medium CVE-2019-5801: Incorrect Omnibox display on iOS. Reported by Khalil Zhani on 2019-01-13
  • [$500][632514] Medium CVE-2019-5802: Security UI spoofing. Reported by Ronni Skansing on 2016-07-28
  • [$1000][909865] Low CVE-2019-5803: CSP bypass with Javascript URLs’. Reported by Andrew Comminos of Facebook on 2018-11-28
  • [$500][933004] Low CVE-2019-5804: Command line command injection on Windows. Reported by Joshua Graham of TSS on 2019-02-17
  • [940992] Various fixes from internal audits, fuzzing and other initiatives

Google thus spent at least $13,500 in bug bounties for this release. That’s significantly less than usual, but as you can see many of the security fixes don’t yet have awards attached. As always, the security fixes alone should be enough incentive for you to upgrade.

Developer features

Chrome 73 includes constructable stylesheets, which means there’s now a programmatic way to add stylesheets. Although it has been previously possible to dynamically create a stylesheet by attaching it directly to a style element’s sheet property, this sometimes resulted in a flash of unstyled content and the bloat of duplicate CSS rules. Constructable stylesheets let you define and apply shared CSS styles to multiple shadow roots or to the document object. Referred to as adopting, updates to a shared style sheet are applied everywhere it’s been adopted. Instead of a new API, stylesheets are constructed imperatively with the replace() and replaceSync() methods.

Next, Chrome 73 adds String.prototype.matchAll(), a new regular expression matching method. It provides a more complete set of matches than String.prototype.match() does.

Chrome 73 includes passive mousewheel listeners. In Chrome 56, Google changed touchstart and touchmove that are registered on root targets to be passive by default, letting the browser safely perform scrolling and zooming without being blocked on listeners. Chrome 73 ensures the wheel and mousewheel event listeners behave the same way.

Chrome 73 updates the V8 JavaScript engine to version 7.3. It includes the –async-stack-traces and –harmony-await-optimization flags, faster Wasm startup, and new JavaScript language features. Check out the full changelog for more information.

Other developer features in this release include:

  • Cross-Origin resource policy: Cross-Origin-Resource-Policy response header allows http servers to ask the browser to prevent cross-origin or cross-site embedding of the returned resource. This is complementary to the Cross-Origin Read Blocking feature and is especially valuable for resources not covered by CORB (which only protects HTML, XML and JSON). Cross-Origin-Resource-Policy is currently the only way to protect images against Spectre attacks or against compromised renderers.
  • document.visibilityState set to “hidden” when WebContents is occluded: Thanks to the WebContents Occlusion feature in Chromium, the Page Visibility API will now accurately reflect the visibility state of web pages, especially when they are occluded. In other words, the document.visibilityState value will be “hidden” when the browser tab or window is covered by one or more window.
  • DOMMatrixReadOnly.scaleNonUniform(): The scaleNonUniform() function post-multiplies a non-uniform scale transformation on the current matrix and returns the resulting matrix. It is being re-added to support legacy compatibility with SVGMatrix. Non-uniform scaling is a transformation in which at least one of the scaling factors is different from the others. For example, non-uniform scaling might turn a rectangle into a square or a parallelogram.
  • EME extension: HDCP policy check: Applications now have the ability to query whether a certain HDCP policy can be enforced so that playback can be started at the optimum resolution for the best user experience. A sample is available for developers who want to try it.
  • GamePad API: GamepadButton touched attribute: The GamePad API now provides the touched state of a gamepad button, which indicates whether a finger is on a button independent of whether it’s being pressed.
  • imagesrcset and imagesizes attributes on link rel=preload: The <link> element now supports imagesrcset and imagesizes properties to correspond to srcset and sizes attributes of HTMLImageElement. To use them, the <link> element must include the preload and image keywords.
  • Implicit root scroller: Implicit root scroller allows viewport-filling scrollers (iframes, divs) to perform document-level scrolling, i.e. show/hide URL bar, overscroll glow, rotation anchoring, etc.. This feature doesn’t have an API so it’s not on a standards track. Chrome will try to determine if a page is mainly contained in a non-document scroller and attempt to delegate its document-scrolling-UX to that scroller. This is an implicit version of the previously proposed rootScrollers API.
  • ::part pseudo element on shadow hosts: Chrome now supports the ::part() pseudo-element on shadow hosts, allowing shadow hosts to selectively expose chosen elements from their shadow tree to the outside page for styling purposes.
  • PerformanceObserver.supportedEntryTypes: PerformanceObserver.supportedEntryTypes provides a way to feature-detect the PerformanceEntry types that are implemented in a web browser.
  • Use the response URL as the base URL for CSS and XSLT stylesheets: If a page contains <link rel="stylesheet" href="/styles.css">, and /styles.css redirects to /foo/styles.css, URLs in the stylesheet will be relative to /foo/styles.css. In this case the request URL is different to the response URL, and it’s the response URL that’s used as the base URL. With a service worker in the middle, Chrome didn’t handle this correctly. It would use the request URL as the base URL for CSS. This is fixed in Chrome 73. Chrome will correctly use the response URL.
  • XHR: Use the response URL for responseURL and documents: XHR’s responseURL property should provide the URL of the response. In many cases, the request and response URLs are the same, but service workers can choose to return a response from elsewhere. Redirects also cause the request and response URLs to be different. If the XHR request was intercepted by a service worker, Chrome would incorrectly set responseURL to the request URL. This is fixed in Chrome 73. Chrome will correctly set responseURL to the response URL.
  • RTCConfiguration.offerExtmapAllowMixed: A boolean property has been added to RTCConfiguration.offerExtmapAllowMixed() to enable the extmap-allow-mixed attribute in a session description protocol (SDP) offer.
  • RTCRtpReceiver.getParameters(): The new RTCRtpReceiver.getParameters() method returns the RTCRtpReceiver object’s track decoding parameters, which includes the codec and RTP header lists negotiated for the call, the RTCP information, and the layer count.
  • RTCRtpReceiver.getSynchronizationSources(): The new RTCRtpReceiver.getSynchronizationSources() method returns the latest playout timestamps of RTP packets for audio and video receivers. This is useful for determining in real time which streams are active, such as for the use case of audio meters or prioritizing displaying active participant streams in the UI.
  • Turn RTCRtpContributingSource from an interface into a dictionary: The specification requires RTCRtpContributingSource to be a dictionary, but it was previously shipped as an interface. With this change RTCRtpContributingSource will no longer have a prototype and getContributingSources() will create a new set of objects with each call.
  • Rename Atomics.wake() to Atomics.notify(): The Atomics.wake() method is being renamed Atomics.notify(). This is a low-level function to wake a Worker that has been suspended via Atomics.wait(). This conforms to a specification change made to alleviate confusion created by the similarity of the names wait and wake.
  • Transform list interpolation: Chrome has improved how CSS transforms are handled to reduce cases where a matrix interpolation fallback is used. An interpolation is an intermediate transformation. Sometimes interpretation of the CSS rule requires falling back to a matrix to accomplish the interpolation, and this can produce visual results other than what the web developer intends. To mitigate this, the specification was changed to reduce the number of situations when this can occur.
  • Spec-compliant shadow blur-radius: Gaussian blur sigma is now computed as one-half the blur-radius, as mandated by the specification. Blink’s shadow implementation now matches FireFox and Safari.
  • Remove isomorphic decoding of URL fragment identifier: When Chrome opens a URL with a fragment id, it decodes %xx and applies isomorphic-decode to it, then tries to find an element with the decoding result as an ID in some cases. No other browsers do this, and it’s not defined by the standard. Starting in version 73, Chrome no longer does this either.

For a full rundown of what’s new, check out the Chrome 73 milestone hotlist.

Google releases a new version of its browser every six weeks or so. Chrome 74 will arrive by end of April.