<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vladyslav Lubenskyi</title>
    <description>The latest articles on DEV Community by Vladyslav Lubenskyi (@lubenskyi).</description>
    <link>https://dev.to/lubenskyi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F846877%2F65902cfb-9601-42d4-9c89-89d6f5cbe5c3.jpg</url>
      <title>DEV Community: Vladyslav Lubenskyi</title>
      <link>https://dev.to/lubenskyi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lubenskyi"/>
    <language>en</language>
    <item>
      <title>Chrome extensions in WebView2, CefSharp, and DotNetBrowser</title>
      <dc:creator>Vladyslav Lubenskyi</dc:creator>
      <pubDate>Tue, 18 Apr 2023 08:38:15 +0000</pubDate>
      <link>https://dev.to/dotnetbrowser/chrome-extensions-in-net-web-view-controls-11lm</link>
      <guid>https://dev.to/dotnetbrowser/chrome-extensions-in-net-web-view-controls-11lm</guid>
      <description>&lt;p&gt;It's 2023, and everything is in the browser. Web technologies are remarkably versatile, and we—desktop developers—envy that versatility. &lt;/p&gt;

&lt;p&gt;That's where web view controls come to help. And there are plenty of them in the .NET world: open-source and proprietary, free and commercial.&lt;/p&gt;

&lt;p&gt;With embeddable Gecko and Trident retired, all modern resorted to Chromium. It complies with the latest web standards, works fast, and has a million features. But there is one feature all web views struggle with. It's the Chrome extensions.&lt;/p&gt;

&lt;p&gt;In this article, I will examine how well web views support Chrome extensions and review their API.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;CefSharp's implementation is minimal, and most extensions don't work. It will change when they switch from the old Alloy to the new Chrome runtime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DotNetBrowser's implementation is functional, but not yet stable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WebView2 doesn't support the extensions thus far.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Today's contestants
&lt;/h2&gt;

&lt;p&gt;As you already noticed, I'm going to look at three libraries: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CefSharp&lt;/li&gt;
&lt;li&gt;WebView2&lt;/li&gt;
&lt;li&gt;DotNetBrowser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CefSharp uses Chromium Embedded Framework. This framework, usually abbreviated as CEF, is a fundamental piece of the ecosystem as every open-source web view is essentially a wrapper over it. The capabilities of CEF define what CefSharp and other similar libraries can do.&lt;/p&gt;

&lt;p&gt;WebView2 and DotNetBrowser are created and maintained by commercial companies and represent the proprietary end of the spectrum.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebView2
&lt;/h2&gt;

&lt;p&gt;WebView2 doesn't support Chrome extensions. But since it uses Microsoft Edge—whose extensions are fully compatible with Chrome's—it may start supporting them in the future.&lt;/p&gt;

&lt;p&gt;Follow these GitHub issues to get updates on WebView2 progress:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/MicrosoftEdge/WebView2Feedback/issues/98"&gt;Add Ons or Extensions with WebView2 (WebView2Feedback#98)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MicrosoftEdge/WebView2Feedback/issues/191"&gt;Ability to install extensions (WebView2Feedback#191)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MicrosoftEdge/WebView2Feedback/issues/3258"&gt;Support for UI-less extensions (WebView2Feedback#3258)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  DotNetBrowser
&lt;/h2&gt;

&lt;p&gt;DotNetBrowser released a &lt;a href="https://teamdev.com/dotnetbrowser/blog/chrome-extensions-in-dotnetbrowser/?utm_campaign=extensions-preview&amp;amp;utm_medium=article&amp;amp;utm_source=devto"&gt;public preview of the extension support&lt;/a&gt;. We have yet to finalize the exact list of available browser APIs, but ultimately, we expect most of the extensions to work.&lt;/p&gt;

&lt;p&gt;Here are the extensions that work in DotNetBrowser: uBlock and AdBlock, Windows Accounts, Web Vitals, and React Developer Tools. We tested these, but you can expect similar extensions to work too.&lt;/p&gt;

&lt;p&gt;If you want to know if a specific extension works, mention it in a &lt;a href="https://github.com/TeamDev-IP/DotNetBrowser-Examples/discussions/141"&gt;GitHub discussion&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  API review
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Installing and uninstalling extensions
&lt;/h4&gt;

&lt;p&gt;In DotNetBrowser, you install extensions permanently. An installed extension is persisted in the profile and remains available until you explicitly uninstall it.&lt;/p&gt;

&lt;p&gt;Before installation, grant the permissions first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Profiles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Extensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ValidatePermissionsHandler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ValidatePermissionsParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ValidatePermissionsResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
        &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ValidatePermissionsResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Grant&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, install the extension with a Chrome Web Store link or a CRX file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;extension&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Install&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://chrome.google.com/webstore/detail/…"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// or&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;extension&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Install&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"C:\\extension.crx"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To uninstall the extension, execute the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Uninstall&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Executing the extension action
&lt;/h4&gt;

&lt;p&gt;Every extension has an icon in the Chrome toolbar. When it's clicked, the extension may execute &lt;a href="https://developer.chrome.com/docs/extensions/reference/action/"&gt;the action&lt;/a&gt;. For example, it can show a pop-up, change the page, or do anything else. &lt;/p&gt;

&lt;p&gt;Here's how you trigger this action from the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The action will interact with this `browser`.&lt;/span&gt;
&lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the action opens a pop-up, the library will show it in a new window. Alternatively, you can leave the pop-up off the screen and manipulate it from the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenExtensionActionPopupHandler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OpenExtensionActionPopupParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OpenExtensionActionPopupResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PopupBrowser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Navigation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FrameLoadFinished&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Frame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"switch"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;OpenExtensionActionPopupResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Handling extension events
&lt;/h4&gt;

&lt;p&gt;Show or suppress pop-up windows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenExtensionPopupHandler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OpenExtensionPopupParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OpenExtensionPopupResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;OpenExtensionPopupResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Suppress&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Handle downloads started by an extension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartDownloadHandler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;StartDownloadParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StartDownloadResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;StartDownloadResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DownloadTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"C:\\Downloads"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Monitor changes in the extension action badge, tooltip, and icon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Updated&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;badge&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtensionAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;icon&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtensionAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tooltip&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtensionAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tooltip&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  CefSharp
&lt;/h2&gt;

&lt;p&gt;CefSharp supports the extensions, but most of them will not work. This is because extensions need &lt;a href="https://developer.chrome.com/docs/extensions/reference/"&gt;special browser APIs&lt;/a&gt;, of which there are over 70. And CEF has only 4—a small set required for a built-in PDF viewer.&lt;/p&gt;

&lt;p&gt;At this moment, &lt;a href="https://github.com/chromiumembedded/cef/issues/1947#issuecomment-1465003373"&gt;further work is discontinued&lt;/a&gt;. After introducing the new integration layer (called Chrome runtime), they decided not to proceed with extensions in the old integration layer (named Alloy). We expect most extensions to work in the new integration layer as the library starts to rely on Chromium's code much more.&lt;/p&gt;

&lt;p&gt;So, do extensions work or not? Not yet. The Chrome runtime is incompatible with CefSharp and CefGlue kind of libraries—it's a work in progress. Track these issues to check on the progress:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/cefsharp/CefSharp/discussions/4123"&gt;Chrome Runtime discussion&lt;/a&gt; in CefSharp repository.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/chromiumembedded/cef/issues/2969"&gt;Support chrome windows with CEF callbacks (cef#2969)&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  API review
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Loading and unloading extensions
&lt;/h4&gt;

&lt;p&gt;Unlike Chromium, CEF doesn't persist extensions: you load them each time the application starts. To load the extension, have it unzipped in the directory and execute the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBrowserHost&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;RequestContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoadExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"C:\\dir"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ExtensionHandler&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To unload the extension, find it in RequestContext and unload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gibkoahgjfhphbmeiphbcnhehbfdlcgo"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Unload&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Handling extension events
&lt;/h4&gt;

&lt;p&gt;Extensions emit events: when loaded or unloaded, wants to create a new browser or access the active browser. These are all handled in &lt;a href="https://cefsharp.github.io/api/75.1.x/html/T_CefSharp_IExtensionHandler.htm"&gt;&lt;code&gt;IExtensionHandler&lt;/code&gt;&lt;/a&gt;, which you associate with the extension on loading. &lt;/p&gt;

&lt;p&gt;Though, until CefSharp adopts the Chrome runtime, most event handlers may be never called.&lt;/p&gt;

&lt;p&gt;Here's a short example to get the gist of the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExtensionHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IExtensionHandler&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="c1"&gt;// Don't allow extensions to create background browsers.&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IExtensionHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OnBeforeBackgroundBrowser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IExtension&lt;/span&gt; &lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IBrowserSettings&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Let the extension know which browser is active now.&lt;/span&gt;
    &lt;span class="n"&gt;IBrowser&lt;/span&gt; &lt;span class="n"&gt;IExtensionHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetActiveBrowser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IExtension&lt;/span&gt; &lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IBrowser&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;includeIncognito&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mainBrowser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Don't allow extensions to access browsers that have a private page&lt;/span&gt;
    &lt;span class="c1"&gt;// loaded.&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IExtensionHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CanAccessBrowser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IExtension&lt;/span&gt; &lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IBrowser&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;includeIncognito&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IBrowser&lt;/span&gt; &lt;span class="n"&gt;targetBrowser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;targetBrowser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my-private-page"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Useful reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/chromiumembedded/cef/issues/2969"&gt;Support Chrome windows with CEF callbacks&lt;/a&gt;. The original issue behind the Chrome runtime in CEF.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/chromiumembedded/cef/issues/1947"&gt;Add support for Chrome extensions&lt;/a&gt;. The original issue for extensions support in CEF.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>cefsharp</category>
      <category>webview</category>
      <category>dotnetbrowser</category>
    </item>
  </channel>
</rss>
