Chrome extensions and the world of tomorrow (Chrome Dev Summit 2019)

Just another WordPress site

Chrome extensions and the world of tomorrow (Chrome Dev Summit 2019)

[MUSIC PLAYING] SIMEON VINCENT: As you probably guessed from the very creative title of this talk, I am going to be talking about Chrome extensions And there’s a lot I want to cover, and our time together is relatively limited So before we get into everything, I just want to make sure we’re on the same page We’re going to take a quick look at an itinerary of events So first, we’re gong to talk about how extensions are great, and how they’re amazing Then we’re going to talk about some of the anatomy of the existing ecosystem We’re going to talk about some of the challenges the extension ecosystem is facing We’ll start to talk about a fundamental shift in how the Chrome team is thinking about the Chrome Extensions platform We’ll go over some details of how to actually migrate an extension and adopt this new system And then I’ll try to tie it all together and say something cool, we’ll see So without further ado, let’s do it First off, extensions are great There are a lot of different ways that we could talk about extensions, like how many have been published, or how many the average user has installed, or user satisfaction ratings, or whatever But personally, when I think about extensions, the thing I keep coming back to is the fact that Chrome extensions are how users make Chrome theirs It’s not just another feature of the web browser This is the way that you customize the browser experience and make the web into something that you personally experience And users have consistently told us that they love using extensions, that extensions are a core part of how they browse the web And I think there’s a pretty simple reason why They make it your web browser You can use extensions to make all kinds of crazy things Like you can, I don’t know, get some motivation every time you open a new tab or automate parts of your workflow You can change your theme and make Chrome feel more like home You can remove ads on the sites you visit You can automatically donate to the content creators that you love Or you can take some inspiration from XKCD and replace a word here and there to spice up your day-to-day browsing experience But the point is, extensions put you front and center You customize your web browser to your tastes And if you can’t find an extension that does what you want, you could probably build your own Those of you comfortable with web development– I’m going to assume that’s a decent number of you here– are already most of the way to building your own Chrome extension See, the Chrome Extensions platform is itself an extension of the web platform Chrome extensions use the same standard technologies– JavaScript, HTML, CSS– that you, web developers use to make– I don’t know, I said you, web developers, that’s weird– web developers use to make websites and the experiences that we all enjoy every day This webby design is a core feature of our browser extension model And to show you what I mean, let’s take a quick look at an example extension to see how it works Here, I have a very real extension that definitely exists And it does two main things It allows me to block websites that I spend too much time on And it allows me to log my work so I can hold myself accountable So if we download this extension and open it up, we’ll see something like this Here, this is the CRX file that I’ve downloaded from the web store And as you can see, this command line utility I’m using shows that the extension is basically just a directory that contains standard webby files AUDIENCE: [INAUDIBLE] SIMEON VINCENT: Oh, my, I don’t know why I was going to give you that So it’s basically just a directory that contains a bunch of files that you’re typically used to working on the web And I want to quickly call out manifest.json here This file is important because it’s the primary entry point to enter your extension So if we pop this open, we can see that the manifest.json contains everything that the extension needs in order for Chrome to load it and run it And I specifically want to point out here that we’re looking at a Manifest version 2 extension The 2 means that we’re working with the second version of the platform Later, we’ll be talking more about some of the features specific to Chrome extensions from the Manifest version 3 platform So here we have the background property This is the– oh, no, what am I saying? The background pop property specifies what code will be running in the background Typically, your background is used to set up event listeners and coordinate between different parts of your extension content_scripts here are injected

onto specific web pages that you want to load custom script on Here, I’m using a special pattern called all_urls, which, as you might guess, matches all URLs And finally, the permissions section currently defines two things– first, the URLs that I’m going to be interacting with, the hosts that I’m going to interact with, and the permissions that the extension requires My extension is pretty simple since it’s only basically blocking sites and saving data locally It doesn’t need many permissions Now, there’s a lot more that Manifest can do But these are the core pieces that we’ll be looking at later on So let’s take a look at some of the issues that we have with the current ecosystem While users love the platform, and good actors put them to wonderful use, we are also facing some very real challenges These are the issues that we’re facing We’re going to go over each in turn And while some of them are closely related, they’re distinct enough that we’re going to need to explain each So first, usability– simply put, when we first created the extensions platform, we made some assumptions about how users would interact with the installation flow, and how well they understood the install prompts, and how well they understood the trade-offs being requested And unfortunately, over time, I think, we’ve come to see that these don’t hold as well for the average user as we would have liked to On the flip side, powerful APIs are often a developer’s only option For example, if you want to block ads on a web today, you have to give the ad blocker broad access to your network request This means you’re also implicitly granting it the ability to see literally everything you do And understandably, this gives a good number of users a pause And speaking of powerful permissions, all_urls is kind of a special case that needs some of that extra attention See, it is extremely common in today’s ecosystem It’s almost impossible to install an extension that doesn’t say, this extension can read and modify all your site data And what that also means is that end users aren’t necessarily– they’re kind of desensitized They’re not giving enough credence to the danger that this poses This should be a relatively scary permission But it is kind of core to how the current extension ecosystem works It also makes it much harder for us to closely scrutinize the content of the extension in order to make sure that anomalous use or potentially dangerous use isn’t occurring And while we’re on the topic of frightening capabilities, in the current version of the extension ecosystem, it’s possible for an extension to load and execute code from a remote server or from an arbitrary string The term that we tend to use for this is remotely loaded code or remotely hosted code And essentially, we just mean any code that isn’t in the extension’s bundle And while this capability is used to good effect, it’s also a major attack vector After all, if an extension can change what it does at runtime without review, then essentially, all bets are off And to put it lightly, that’s not the situation we’re exactly excited about Another major challenge of the current extensions platform is that extensions can pretty easily tank performance, either for specific pages or for Chrome For specific pages, the user can just close the page and move on But when it starts to drag down Chrome, then everything suffers The web suffers, from the user’s point of view And due to the asynchronous architecture of the extensions platform, there’s no obvious signal to the end user when this is happening So if a page were to similarly slow down, you would start to see scroll junk, or there would be clear signals that there’s issues But basically, the computer just very slowly degrades And even if a user knew that an extension was at fault, there’s not a great way for them to take action, to reclaim those resources And finally, users simply don’t have enough control in today’s ecosystem They don’t have enough control over the experience of using an extension Historically, if an extension said that it needed broad host permissions, that it needed all_urls, they would just include that pattern in their permissions list And then the user is forced to either choose to grant them the set of capabilities that the extension’s requesting or to bail out entirely And needless to say, this isn’t good for users or developers It also assumes that the user actually understands these permissions So if a user didn’t understand “read and change all your site data,” they might say yes, even though they don’t

understand the consequences And there’s no remediation until you uninstall the extension entirely So that brings us to this paradigm shift As we think about how to improve the extensions platform and where we want it to go, we’re making some changes to the base assumptions about how extensions are built. And unfortunately, all of the issues we just went through present a fundamental conflict with the current extensions platform We can’t make those changes without some rather substantial breaking changes to the platform itself So we’re going to make some substantial changes and break the Manifest version, which is why we’re going from 2 to 3 That way, we have a new ecosystem to work in So if I had to give the current ecosystem kind of a tag line or a motto, it would be something like, “empower developers to create amazing end user experiences.” But as we look to the future of how we want to evolve the platform, we want to shift it to something more like, “empower users to customize Chrome with amazing extensions.” The privacy and security of the user should be the primary focus for both Chrome and for extension developers And of course, we’re still striving to provide developers with a powerful, capable platform that they can use to enable and delight users But that respect for the user should be a core principle for everyone With this user-centered philosophy in mind, we’re aiming to improve three main areas of the Chrome Extensions platform– privacy, security, and performance In order to improve the privacy of the extension ecosystem, we’re trying to give users more control over when an extension will run and what data it can access We’re also trying to encourage extension developers to give users more in-context permission requests and temporary permission grants In-context requests improve the end users comprehension of a permission being requested And temporary grants keep the user in control of their data For more about temporary grants, I’d encourage you to check out documentation on activeTab We’re also looking to improve the security guarantees of the extensions platform That is, we want to be able to say to the user with confidence that it is significantly harder or even impossible for an extension to gain control of this privileged execution environment And by extension, we want to increase– huh, by extension– we want to increase the end user trust in what they install, and that it won’t cause any long-term harm or won’t do anything without their direct involvement Oh, right, I have to press a button [LAUGHTER] We’re also aiming to make the extension platform more performant by default We want developers to fall into a pit of success, where even if they make a mistake or adopt an anti-pattern, things will, for the most part, just work out for them and, by extension, the end user So one of the goals here is to reduce the amount of resources that are being consumed over the extension’s lifetime I have too many things OK, let’s start to get into some of the details about how extension developers will migrate from the current extensions platform to the new version, Manifest V3 There are four main things that developers are going to need to adapt to in this transition First, we’re migrating from a background page to a background service worker We’re going to change how the extension gets and uses host permissions We’re introducing a new requirement for extensions to bundle all the source code that they’re going to execute into the extension itself And finally, we’re changing how network requests are modified at runtime Each of these has its own set of challenges and will require a different set of adaptations So we’re going to step through them and see how it goes First up, background context changes– the first and perhaps broadest set of changes is the transition from a background page to a background service worker There are two types of background pages today– persistent background pages and event pages Persistent background pages, as you may guess, are long-lived page environments that constantly run in the background Event pages, on the other hand, are temporary environments that are started in response to an event and terminated when they’re no longer needed We want to move from background pages

to service workers for three general reasons First, better overall performance– we want to reduce the number of concurrent processes running, the amount of memory consumed, and the total resource usage overall of extensions Second, extensions are built on top of the web Where possible, we much prefer to use the web’s primitives rather than custom extension’s specific solutions And finally, maintenance cost– upkeep has a very real cost If we have a bunch of redundant features that are both supported by the web platform and the extension platform, that means we have to do twice the work Like Chrome has to do twice the work in order to make any change because of knock-on effects One change here can cause consequences in other places you didn’t expect So as developers look to migrate to service workers, there are two categories of issues that we’re going to need to face First is this transition from a persistent page to an ephemeral environment And the other is moving from a headless page to a worker So first up, ephemerality– extension listeners need to be registered in the root context of an extension rather than in asynchronous registration and some kind of callback For example, you can imagine requesting some config from Aroma server and then, once you’ve received the response, registering the callback handler And this is a little bit off in the weeds, but I think it’s cool So I’m going to share it with you In order for Chrome to properly dispatch events, it needs the events to be registered as soon as possible, preferably, in the first turn of the event loop If they’re not, then it’s possible that you would perform your asynchronous network request You’d come back Before the response is received, Chrome would try to dispatch the event It wouldn’t be handled because there’s no handlers registered And then you receive the response, register your listener And now you’re like, wait, where did my event go? Like I dropped it on the floor because you weren’t there All right, second, you can’t rely on global state Since service workers are event-based, the global context with a service worker is tossed every time the service worker is torn down So you probably need to adapt by moving from global state to chrome.storage APIs or IndexedDB I should also call out here that extension service workers– well, I guess, all service workers– are asynchronous by design So you can’t rely on synchronous APIs like local storage So if you’re currently using local storage to store your state, you’ll need to work out a migration plan All right, the other major challenge with background pages is that they don’t have DOM– or I’m sorry, background service workers pages have DOM because they’re pages So no worker– web worker, or service worker, or animation worklet– none of them have access to DOM By design, workers are meant to be a stripped down environment But that also means you can’t do things that you’re used to using DOM for You can’t parse XML or HTML, or you can’t traverse a document tree because there’s no document You can’t dispatch events because there are no elements to dispatch events on You can’t play audio or video You can’t render to a canvas element because there’s no element So each of these is going to require its own specific ways to handle For parsing documents, traversing trees, dispatching events, a library like JSDOM or Undom can fill that use case For playing audio or video, you’ll probably want to reuse an existing DOM context or create a new one So open a new tab or window And for rendering to canvases, that’s what OffscreenCanvas is for explicitly, by design And while this isn’t our preferred pattern, in some cases, you may absolutely need a long-lived, persistent page environment In those cases, I’d recommend using a new tab or a new window And that may sound odd that we’re moving from a headless page to a worker, and the solution is to open a new page And the answer is, yes The rationale here is that this gives the user control If they are able to control whether or not a page is open, a tab is present, then they can decide whether or not they want your page to be around, or if they want to reclaim those resources For additional guidance on adopting service workers– there are other issues to be aware of here as well– check out the Migration Guide I’ll have a link at the end of the talk

All right, too many words Code– assuming that you already have your background script in a state that can be transitioned directly to a service worker– and for reference, a decent number of event pages already fit this bill– you can simply change the background scripts here into a service worker That’s it It’s a one-line change in your manifest But that makes a decent number of assumptions All right, host permissions– one of the fundamental changes in how the new version of the extensions platform is rethinking the way extensions work is this shift towards a more user-centric interaction model In the past, if an extension wanted to access data on every website, as I mentioned before, they just add all_urls to their permissions list And then if the user didn’t understand or just agreed to it, the extension would have that capability until it was uninstalled Given the risks associated with this persistent permission, the extensions team wanted to change how capability grants like this work in order to give users more control over their data With the release of Chrome 70 in October of last year, end users gained a lot more control with the introduction of this feature Here, if you right-click an extension in the toolbar, you can go to the “This can change and read site data” option, where you can restrict the extension’s access to either a specific site or even to only run on click Looking to the future, we’re exploring additional changes to the installation flow, so that “When you click the extension” option in here is the new default Users can still opt into granting broader persistent permissions if they wish to do so But that should be the user’s choice, not the developer’s Rather extension should provide a complete compelling experience out-of-the-box without having to ask the user to give away the sun, the moon, and the stars The intent here is more direct user control over when and where extensions will access their data Today, many of extensions are designed around this pervasive data access pattern And there are a whole host of ways that good actors put this to positive effect But it also comes at a cost that a lot of developers and users may not have considered And that cost is compromising user security and privacy To that end, I’d strongly encourage developers to look into ways to embrace this new paradigm, this new mindset And try to design your basic interactions for your extension around temporary host permissions rather than persistent host permissions Where possible, treat in-page interaction and host permissions as a progressive enhancement If the user likes what you’re delivering, then they can choose to grant your extension additional capabilities Before we move off permissions, I would want to make a quick note about API changes Earlier I mentioned that Manifest version 2 specify hosts in the permissions field In Manifest version 3, we’re changing this to have a dedicated field host.permissions, where you define your host permissions While this is a small change, the intent is to better reflect how the Chrome platform is thinking about and using host permissions These aren’t capabilities that will be required of the user These are things that may enhance your extension All right, remotely hosted code restrictions– a few moments ago, I talked about some of the challenges related to remotely loading code And in order to address these issues, in the future, extensions will only be able to execute code that is in the extension’s bundle And by code, I specifically mean JavaScript, CSS, and WebAssembly Now, CSS may seem like a bit of an outlier here But unfortunately, through clever use of CSS, it’s possible to leak data about the page that the CSS is injected into So unfortunately, we have to guard against that I should also call out that remote data is fine You’ll still be able to load JSON You’ll still be able to request media assets You can still make remote procedure calls or API calls You can still do that webby stuff The intent, though, is, in this privileged execution environment, we need to be able to see the code that will be run We plan to accomplish this through a combination

of platform and policy changes For example, if you attempt to change the default content security policy on an extension, in order to grant unsafe eval, as in the case here, or grant a remote domain, you simply will fail to load the extension at install time I tend to be a big fan of “error loudly and clearly, as soon as possible.” And this is definitely that In order to adapt to this change, I’d strongly recommend developers move towards a config-driven architecture Bundle all the code that your extension may execute at runtime And then use remotely loaded configuration– for example, JSON– in order to choose which files you actually inject and which code parts you execute I’d also encourage extension developers to consider adding feature switches to their extensions and possibly some messaging support in order to minimize unexpected behaviors and to communicate those unexpected behaviors and disabling of certain features to end users One major area changing in Manifest V3 is how we handle modifying network requests Currently, extensions use the blocking version of the Web Request API in order to, well, block web requests This API effectively places the extension between the browser and the network Here’s a simplified version of the web request flow First, the extension registers event listeners with Chrome in order to get callbacks when a net request lifecycle event is fired Next, when the event is triggered, Chrome passes a request object to the extension And finally, the extension chooses whether to allow the request, to modify it, or to cancel it entirely While this API is very capable, it has a couple of major issues that we want to address in this attempt to move to a more privacy-preserving and secure extension platform First, it requires host permissions for the extension to work As we just talked about, we’re trying to go away from them or discourage their persistent use, which means that in the current world, an extension wouldn’t be able to observe or modify the request In other words, at install time, the extension wouldn’t work out-of-the-box That’s a pretty bad experience for the end user So it’s something that we want to address Second, this exposes too much data to the extension passively The request object that I mentioned in step 2 here contains detailed information, such as the URL, the cookies used, the request body, et cetera And this pervasive passive data access is exactly the type of thing that we’re trying to adjust in Manifest version 3 And third, and finally, this API was designed for a world with persistent background pages To put it another way, it’s not a great fit for moving to service workers Service workers have a startup cost And all requests are blocked until that startup cost is paid Without getting too deep into the internals of Chrome, the web requests model involves a decent amount of extra work for Chrome For every lifecycle event that is fired for every request, every extension that’s interested in it needs data to be serialized and passed across multiple different process hops The extension use of the service worker is also a bit different than on the open web, where service workers cash offline content and enable better offline experiences In our case, though, the service worker would be a blocking– network request would block on the extension service worker until the extension service worker to start it up And that has a very real cost to end users So in order to continue to serve the Web Request use case and the wonderful things that it does, we’re trying to take a think on redesigning some of the basics of this model To show you what I mean, let’s take a look at how a new API that we’re introducing is going to work Oh, I lied I have to say that in order to continue to serve the basic use cases– oh, no, I said all that Not that it matters We’re introducing a new API called Declarative Net Request that takes a completely different approach So rather than the extension sitting between the browser and the network, the extension at install time says, hey, Chrome, here’s a list of rules that I want you to enforce And then Chrome is responsible for enforcing them This declarative model drastically

limits how much data is exposed to the extension, while still enabling extensions to modify requests and block ads and stuff So let’s see some code to actually compare the two First, in Manifest version 2, I have a set of permissions that I request I have to request both webRequest and webRequestBlocking because that’s a separate thing I also have to request all the hosts that I want to intercept And then I match requests that are sent to the main_frame on Twitter, and I cancel them So all of this is happening running in a JavaScript environment Instead in Manifest version 3, my permissions list now is only declarativeNetRequest No host permissions required I have a new property called declarative_net_request, where I define a set of static rules And each of these rules will match the main_frame and the URL and then block that request I should also call out that in response of developer feedback, we’ve also added a– what’s it called– Runtime API in order to add dynamic rules But this still allows Chrome to remain in control of what requests are allowed and limit the amount of data exposed to the extension If you’re interested in learning more, please check out our documentation Again, link at the end of the talk But we are very interested in trying to work with the development community in order to find a good solution for this All right, wrap it up We talked about a lot of stuff, moving from background pages to service workers, host permissions, remotely hosted code, restrictions, net request modification And all of that was too fast to even hear what I just said But before our time together is over, I want to touch on another important thing, what we’re keeping the same Extensions are an amazing feature of Chrome Time and time again, we’ve heard that extension cited as a key feature of how users browse the web Extensions give users a way to customize Chrome and truly make it their own As we refine the platform to give users more control over their browsing experience, we’re also striving to maintain the eclectic, feature-rich, vibrant ecosystem of extensions that we have today We want to get to a world where we can satisfy all of these use cases that empower users and make Chrome their web browser, while also feeling safe, and in charge, and secure That’s the reason that we’re pursuing Manifest version 3 And we’re committed to continuing to work with the development community throughout this transition Before I go, though, I’d like to encourage you all to start experimenting with the new version of the Chrome Extensions platform We have a developer preview in Chrome Canary today Well, actually, we released it on Halloween But it’s out there You can start experimenting and trying these out Try migrating extensions and also give us feedback on what you can and can’t do And please let us know if you run into any issues on the Chromium Extensions Google group Again, thank you very much I appreciate it Have a good one [APPLAUSE] [MUSIC PLAYING]