diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs
index 169be2d8..c800efdb 100644
--- a/Core/FormBrowser.cs
+++ b/Core/FormBrowser.cs
@@ -12,6 +12,7 @@
 using TweetDuck.Core.Other.Analytics;
 using TweetDuck.Core.Utils;
 using TweetDuck.Plugins;
+using TweetDuck.Plugins.Enums;
 using TweetDuck.Plugins.Events;
 using TweetDuck.Updates;
 
@@ -38,6 +39,7 @@ public bool IsWaiting{
 
         public string UpdateInstallerPath { get; private set; }
 
+        public PluginManager PluginManager => plugins;
         public AnalyticsFile AnalyticsFile => analytics?.File ?? AnalyticsFile.Dummy;
 
         private readonly TweetDeckBrowser browser;
@@ -57,17 +59,19 @@ public FormBrowser(UpdaterSettings updaterSettings){
             InitializeComponent();
 
             Text = Program.BrandName;
-            
-            this.browser = new TweetDeckBrowser(this, new TweetDeckBridge.Browser(this, notification));
-            this.contextMenu = ContextMenuBrowser.CreateMenu(this);
 
-            this.plugins = new PluginManager(browser, Program.PluginPath, Program.PluginConfigFilePath);
+            this.plugins = new PluginManager(Program.PluginPath, Program.PluginConfigFilePath);
             this.plugins.Reloaded += plugins_Reloaded;
             this.plugins.Executed += plugins_Executed;
             this.plugins.Reload();
 
             this.notification = new FormNotificationTweet(this, plugins);
             this.notification.Show();
+            
+            this.browser = new TweetDeckBrowser(this, new TweetDeckBridge.Browser(this, notification));
+            this.contextMenu = ContextMenuBrowser.CreateMenu(this);
+
+            this.plugins.Register(browser, PluginEnvironment.Browser, true);
 
             Controls.Add(new MenuStrip{ Visible = false }); // fixes Alt freezing the program in Win 10 Anniversary Update
 
diff --git a/Core/Notification/FormNotificationMain.cs b/Core/Notification/FormNotificationMain.cs
index e2eac9b1..b6dc98d2 100644
--- a/Core/Notification/FormNotificationMain.cs
+++ b/Core/Notification/FormNotificationMain.cs
@@ -12,7 +12,7 @@
 using TweetDuck.Resources;
 
 namespace TweetDuck.Core.Notification{
-    abstract partial class FormNotificationMain : FormNotificationBase{
+    abstract partial class FormNotificationMain : FormNotificationBase, ITweetDeckBrowser{
         private const string NotificationScriptFile = "notification.js";
 
         private static readonly string NotificationScriptIdentifier = ScriptLoader.GetRootIdentifier(NotificationScriptFile);
@@ -81,17 +81,35 @@ protected FormNotificationMain(FormBrowser owner, PluginManager pluginManager, b
             this.timerBarHeight = BrowserUtils.Scale(4, DpiScale);
             
             browser.KeyboardHandler = new KeyboardHandlerNotification(this);
-            
             browser.RegisterAsyncJsObject("$TD", new TweetDeckBridge.Notification(owner, this));
-            browser.RegisterAsyncJsObject("$TDP", plugins.Bridge);
 
             browser.LoadingStateChanged += Browser_LoadingStateChanged;
             browser.FrameLoadEnd += Browser_FrameLoadEnd;
 
+            plugins.Register(this, PluginEnvironment.Notification);
+
             mouseHookDelegate = MouseHookProc;
             Disposed += (sender, args) => StopMouseHook(true);
         }
 
+        void ITweetDeckBrowser.RegisterBridge(string name, object obj){
+            browser.RegisterAsyncJsObject(name, obj);
+        }
+
+        void ITweetDeckBrowser.OnFrameLoaded(Action<IFrame> callback){
+            browser.FrameLoadEnd += (sender, args) => {
+                IFrame frame = args.Frame;
+
+                if (frame.IsMain && NotificationJS != null && browser.Address != "about:blank"){
+                    callback(frame);
+                }
+            };
+        }
+
+        void ITweetDeckBrowser.ExecuteFunction(string name, params object[] args){
+            browser.ExecuteScriptAsync(name, args);
+        }
+
         // mouse wheel hook
 
         private void StartMouseHook(){
@@ -166,7 +184,6 @@ private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
             if (e.Frame.IsMain && NotificationJS != null && browser.Address != "about:blank"){
                 e.Frame.ExecuteJavaScriptAsync(PropertyBridge.GenerateScript(PropertyBridge.Environment.Notification));
                 ScriptLoader.ExecuteScript(e.Frame, NotificationJS, NotificationScriptIdentifier);
-                plugins.ExecutePlugins(e.Frame, PluginEnvironment.Notification);
             }
         }
 
@@ -232,7 +249,7 @@ public override void ResumeNotification(){
         protected override string GetTweetHTML(TweetNotification tweet){
             string html = base.GetTweetHTML(tweet);
 
-            foreach(InjectedHTML injection in plugins.Bridge.NotificationInjections){
+            foreach(InjectedHTML injection in plugins.NotificationInjections){
                 html = injection.Inject(html);
             }
 
diff --git a/Core/Notification/Screenshot/FormNotificationScreenshotable.cs b/Core/Notification/Screenshot/FormNotificationScreenshotable.cs
index 5b2cabc5..df508819 100644
--- a/Core/Notification/Screenshot/FormNotificationScreenshotable.cs
+++ b/Core/Notification/Screenshot/FormNotificationScreenshotable.cs
@@ -33,7 +33,7 @@ public FormNotificationScreenshotable(Action callback, FormBrowser owner, Plugin
         protected override string GetTweetHTML(TweetNotification tweet){
             string html = tweet.GenerateHtml("td-screenshot", false);
 
-            foreach(InjectedHTML injection in plugins.Bridge.NotificationInjections){
+            foreach(InjectedHTML injection in plugins.NotificationInjections){
                 html = injection.Inject(html);
             }
 
diff --git a/Plugins/PluginManager.cs b/Plugins/PluginManager.cs
index 5ea1609e..3ed0917c 100644
--- a/Plugins/PluginManager.cs
+++ b/Plugins/PluginManager.cs
@@ -5,6 +5,7 @@
 using System.IO;
 using System.Linq;
 using TweetDuck.Core;
+using TweetDuck.Data;
 using TweetDuck.Plugins.Enums;
 using TweetDuck.Plugins.Events;
 using TweetDuck.Resources;
@@ -21,42 +22,46 @@ sealed class PluginManager{
         public string PathCustomPlugins => Path.Combine(rootPath, "user");
 
         public IEnumerable<Plugin> Plugins => plugins;
+        public IEnumerable<InjectedHTML> NotificationInjections => bridge.NotificationInjections;
+
         public PluginConfig Config { get; }
-        public PluginBridge Bridge { get; }
         
         public event EventHandler<PluginErrorEventArgs> Reloaded;
         public event EventHandler<PluginErrorEventArgs> Executed;
 
-        private readonly ITweetDeckBrowser browser;
         private readonly string rootPath;
         private readonly string configPath;
+        private readonly PluginBridge bridge;
 
         private readonly HashSet<Plugin> plugins = new HashSet<Plugin>();
         private readonly Dictionary<int, Plugin> tokens = new Dictionary<int, Plugin>();
         private readonly Random rand = new Random();
 
-        public PluginManager(ITweetDeckBrowser browser, string rootPath, string configPath){
-            this.browser = browser;
+        private ITweetDeckBrowser mainBrowser;
+
+        public PluginManager(string rootPath, string configPath){
             this.rootPath = rootPath;
             this.configPath = configPath;
 
             this.Config = new PluginConfig();
-            this.Bridge = new PluginBridge(this);
-
-            this.browser.OnFrameLoaded(OnFrameLoaded);
-            this.browser.RegisterBridge("$TDP", Bridge);
+            this.bridge = new PluginBridge(this);
 
             Config.Load(configPath);
             Config.PluginChangedState += Config_PluginChangedState;
         }
 
-        private void Config_PluginChangedState(object sender, PluginChangedStateEventArgs e){
-            browser.ExecuteFunction("TDPF_setPluginState", e.Plugin, e.IsEnabled);
-            Config.Save(configPath);
+        public void Register(ITweetDeckBrowser browser, PluginEnvironment environment, bool asMainBrowser = false){
+            browser.OnFrameLoaded(frame => ExecutePlugins(frame, environment));
+            browser.RegisterBridge("$TDP", bridge);
+
+            if (asMainBrowser){
+                mainBrowser = browser;
+            }
         }
 
-        private void OnFrameLoaded(IFrame frame){
-            ExecutePlugins(frame, PluginEnvironment.Browser);
+        private void Config_PluginChangedState(object sender, PluginChangedStateEventArgs e){
+            mainBrowser?.ExecuteFunction("TDPF_setPluginState", e.Plugin, e.IsEnabled);
+            Config.Save(configPath);
         }
 
         public bool IsPluginInstalled(string identifier){
@@ -68,12 +73,12 @@ public bool HasAnyPlugin(PluginEnvironment environment){
         }
 
         public bool IsPluginConfigurable(Plugin plugin){
-            return plugin.HasConfig || Bridge.WithConfigureFunction.Contains(plugin);
+            return plugin.HasConfig || bridge.WithConfigureFunction.Contains(plugin);
         }
 
         public void ConfigurePlugin(Plugin plugin){
-            if (Bridge.WithConfigureFunction.Contains(plugin)){
-                browser.ExecuteFunction("TDPF_configurePlugin", plugin);
+            if (bridge.WithConfigureFunction.Contains(plugin)){
+                mainBrowser?.ExecuteFunction("TDPF_configurePlugin", plugin);
             }
             else if (plugin.HasConfig){
                 if (File.Exists(plugin.ConfigPath)){
@@ -143,7 +148,7 @@ IEnumerable<Plugin> LoadPluginsFrom(string path, PluginGroup group){
             Reloaded?.Invoke(this, new PluginErrorEventArgs(loadErrors));
         }
 
-        public void ExecutePlugins(IFrame frame, PluginEnvironment environment){
+        private void ExecutePlugins(IFrame frame, PluginEnvironment environment){
             if (!HasAnyPlugin(environment)){
                 return;
             }