├── SpawnDev.BlazorJS.BrowserExtension ├── _Imports.razor ├── Images │ └── icon-128.png ├── buildcontent │ └── patch.js ├── Storage │ ├── StorageChange.cs │ ├── StorageChanges.cs │ ├── Storage.cs │ └── StorageArea.cs ├── DeclarativeNetRequest │ ├── RulesMatchedDetails.cs │ ├── TestMatchOutcomeResult.cs │ ├── GetRulesFilter.cs │ ├── MatchedRuleInfoDebug.cs │ ├── GetDisabledRuleIdsOptions.cs │ ├── MatchedRule.cs │ ├── TabActionCountUpdate.cs │ ├── UnsupportedRegexReason.cs │ ├── IsRegexSupportedResult.cs │ ├── UpdateRuleOptions.cs │ ├── HeaderOperation.cs │ ├── Ruleset.cs │ ├── DomainType.cs │ ├── MatchedRuleInfo.cs │ ├── MatchedRulesFilter.cs │ ├── UpdateRulesetOptions.cs │ ├── ExtensionActionOptions.cs │ ├── QueryTransform.cs │ ├── RegexOptions.cs │ ├── UpdateStaticRulesOptions.cs │ ├── QueryKeyValue.cs │ ├── ModifyHeaderInfo.cs │ ├── RequestMethod.cs │ ├── Rule.cs │ ├── RuleActionType.cs │ ├── TestMatchRequestDetails.cs │ ├── Redirect.cs │ ├── RuleAction.cs │ ├── ResourceType.cs │ ├── URLTransform.cs │ ├── RequestDetails.cs │ ├── DeclarativeNetRequest.cs │ └── RuleCondition.cs ├── Runtime │ ├── OnUpdateAvailableDetails.cs │ ├── OnPerformanceWarningCategory.cs │ ├── OnPerformanceWarningSeverity.cs │ ├── ConnectInfo.cs │ ├── OnRestartRequiredReason.cs │ ├── OnPerformanceWarningDetails.cs │ ├── OnInstalledDetails.cs │ ├── OnInstalledReason.cs │ ├── MessageSender.cs │ └── Port.cs ├── wwwroot │ └── content-bridge-loader.js ├── Tabs │ ├── ReloadProperties.cs │ ├── ActiveInfo.cs │ ├── TabMessageOptions.cs │ ├── MutedInfo.cs │ ├── CreateTabProperties.cs │ ├── ChangeInfo.cs │ ├── Tabs.cs │ ├── TabQueryInfo.cs │ └── Tab.cs ├── Action │ ├── OpenPopupDetails.cs │ ├── UserSettings.cs │ ├── GetPopupDetails.cs │ ├── IsEnabledDetails.cs │ ├── GetTitleDetails.cs │ ├── GetBadgeTextDetails.cs │ ├── GetBadgeTextColorDetails.cs │ ├── GetBadgeBackgroundColorDetails.cs │ ├── SetBadgeBackgroundColorDetails.cs │ ├── SetBadgeTextDetails.cs │ ├── SetBadgeTextColorDetails.cs │ ├── SetTitleDetails.cs │ ├── SetPopupDetails.cs │ ├── SetIconDetails.cs │ └── Action.cs ├── Services │ ├── LocationChangeEvent.cs │ ├── ExtensionMode.cs │ └── ContentBridgeService.cs ├── Content │ ├── ContentOverlayRouteInfo.cs │ └── ContentLocationAttribute.cs ├── ExtensionTypes │ ├── FrameType.cs │ └── DocumentLifecycle.cs ├── ContentBridge │ ├── ExtensionContentBridgeOptions.cs │ ├── WrappedObjectJSObjectExtensions.cs │ ├── WrappedObjectProxy.cs │ └── ExtensionContentBridge.cs ├── Windows │ ├── WindowType.cs │ ├── GetInfo.cs │ ├── WindowState.cs │ ├── Windows.cs │ └── Window.cs ├── WebRequest │ ├── WebRequest.cs │ └── WebRequestEvent.cs ├── Events │ └── ExtensionEvent.cs ├── Browser.cs ├── build │ ├── SpawnDev.BlazorJS.BrowserExtension.props │ └── SpawnDev.BlazorJS.BrowserExtension.targets ├── SpawnDev.BlazorJS.BrowserExtension.csproj └── ContextMenus │ ├── ContextMenus.cs │ ├── MenuItemProperties.cs │ └── OnClickData.cs ├── SpawnDev.BlazorJS.BrowserExtension.Build ├── SpawnDev.BlazorJS.BrowserExtension.Build.csproj └── Tasks │ └── PostBuildTask.cs ├── .github └── FUNDING.yml ├── LICENSE.txt ├── README.md ├── SpawnDev.BlazorJS.BrowserExtension.sln ├── .gitattributes └── .gitignore /SpawnDev.BlazorJS.BrowserExtension/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Images/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LostBeard/SpawnDev.BlazorJS.BrowserExtension/main/SpawnDev.BlazorJS.BrowserExtension/Images/icon-128.png -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/buildcontent/patch.js: -------------------------------------------------------------------------------- 1 | /// Deprecated in favor of SpawnDev.BlazorJS.WebWorkers built in support for running in worker scope including ServiceWorkers 2 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Storage/StorageChange.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | using SpawnDev.BlazorJS; 3 | 4 | namespace SpawnDev.BlazorJS.BrowserExtension 5 | { 6 | public class StorageChange : JSObject 7 | { 8 | public StorageChange(IJSInProcessObjectReference _ref) : base(_ref) { } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/RulesMatchedDetails.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-RulesMatchedDetails 5 | /// 6 | public class RulesMatchedDetails 7 | { 8 | /// 9 | /// Rules matching the given filter. 10 | /// 11 | public MatchedRuleInfo[] RulesMatchedInfo { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/TestMatchOutcomeResult.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-TestMatchOutcomeResult 5 | /// 6 | public class TestMatchOutcomeResult 7 | { 8 | /// 9 | /// The rules (if any) that match the hypothetical request. 10 | /// 11 | public MatchedRule[] MatchedRules { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Runtime/OnUpdateAvailableDetails.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// Details passed to the event handler for Runtime.OnUpdateAvailable
5 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onUpdateAvailable#details 6 | ///
7 | public class OnUpdateAvailableDetails 8 | { 9 | /// 10 | /// The version number of the update 11 | /// 12 | public string Version { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/GetRulesFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-GetRulesFilter 6 | /// 7 | public class GetRulesFilter 8 | { 9 | /// 10 | /// An array of integer. The IDs of the rules to return. 11 | /// 12 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 13 | public int[]? RuleIds { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/wwwroot/content-bridge-loader.js: -------------------------------------------------------------------------------- 1 | // Loads an extension content bridge on the website side with serve enabled 2 | (() => { 3 | var src = document.currentScript.src; 4 | var url = new URL(src); 5 | var instanceId = url.searchParams.get('instanceId'); 6 | var remoteInstanceId = url.searchParams.get('remoteInstanceId'); 7 | if (instanceId && remoteInstanceId) { 8 | globalThis._cdA = new ExtensionContentBridge({ 9 | instanceId: instanceId, 10 | remoteInstanceId: remoteInstanceId, 11 | serve: true, 12 | }); 13 | } 14 | })(); 15 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Tabs/ReloadProperties.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Tab reload properties
7 | /// https://developer.chrome.com/docs/extensions/reference/api/tabs#parameters_20 8 | ///
9 | public class ReloadProperties 10 | { 11 | /// 12 | /// Whether to bypass local caching. Defaults to false. 13 | /// 14 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 15 | public bool? BypassCache { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/MatchedRuleInfoDebug.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-MatchedRuleInfoDebug 5 | /// 6 | public class MatchedRuleInfoDebug 7 | { 8 | /// 9 | /// Details about the request for which the rule was matched. 10 | /// 11 | public RequestDetails? Request { get; set; } 12 | /// 13 | /// Matched Rule 14 | /// 15 | public MatchedRule? Rule { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/OpenPopupDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options used for Action.OpenPopup()
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/openPopup#details 8 | ///
9 | public class OpenPopupDetails 10 | { 11 | /// 12 | /// integer. Window to open the popup for. Defaults to the current window. 13 | /// 14 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 15 | public int? WindowId { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/GetDisabledRuleIdsOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// An object containing details of the ruleset to return disabled rules for.
6 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-GetDisabledRuleIdsOptions 7 | ///
8 | public class GetDisabledRuleIdsOptions 9 | { 10 | /// 11 | /// 12 | /// 13 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 14 | public string? RulesetId { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/MatchedRule.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-MatchedRule 5 | /// 6 | public class MatchedRule 7 | { 8 | /// 9 | /// A matching rule's ID. 10 | /// 11 | public int RuleId { get; set; } 12 | /// 13 | /// ID of the Ruleset this rule belongs to. For a rule originating from the set of dynamic rules, this will be equal to DYNAMIC_RULESET_ID. 14 | /// 15 | public string RulesetId { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/TabActionCountUpdate.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-TabActionCountUpdate 5 | /// 6 | public class TabActionCountUpdate 7 | { 8 | /// 9 | /// The amount to increment the tab's action count by. Negative values will decrement the count. 10 | /// 11 | public int Incremenet{ get; set; } 12 | /// 13 | /// The tab for which to update the action count. 14 | /// 15 | public int TabId { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Runtime/OnPerformanceWarningCategory.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// The category of warning that dispatched the runtime.onPerformanceWarning event.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/OnPerformanceWarningCategory 8 | ///
9 | public enum OnPerformanceWarningCategory 10 | { 11 | /// 12 | /// The performance warning is for a slow content script in the listening extension. 13 | /// 14 | [JsonPropertyName("content_script")] 15 | ContentScript, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/UserSettings.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// An object containing the user-specified settings for the browser action.
5 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/getUserSettings#usersettings 6 | ///
7 | public class UserSettings 8 | { 9 | /// 10 | /// boolean. Whether the user has pinned the action's icon to the browser UI. This setting does not indicate whether the action icon is visible. The icon's visibility depends on the size of the browser window and the layout of the browser UI. 11 | /// 12 | public bool? IsOnToolbar { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Storage/StorageChanges.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | using SpawnDev.BlazorJS; 3 | 4 | namespace SpawnDev.BlazorJS.BrowserExtension 5 | { 6 | public class StorageChange : JSObject 7 | { 8 | public StorageChange(IJSInProcessObjectReference _ref) : base(_ref) { } 9 | public T OldValue() => JSRef.Get("oldValue"); 10 | public T NewValue() => JSRef.Get("newValue"); 11 | } 12 | public class StorageChanges : JSObject 13 | { 14 | public StorageChanges(IJSInProcessObjectReference _ref) : base(_ref) { } 15 | public List Keys => JS.Call>("Object.keys", JSRef); 16 | public StorageChange Get(string key) => JSRef.Get>(key); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Services/LocationChangeEvent.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | using SpawnDev.BlazorJS.JSObjects; 3 | 4 | namespace SpawnDev.BlazorJS.BrowserExtension.Services 5 | { 6 | /// 7 | /// Event handle for custom event dispatched when the page location change has been detected. 8 | /// 9 | class LocationChangeEvent : Event 10 | { 11 | /// 12 | /// Deserialization constructor 13 | /// 14 | /// 15 | public LocationChangeEvent(IJSInProcessObjectReference _ref) : base(_ref) { } 16 | /// 17 | /// The new location 18 | /// 19 | public string Detail => JSRef.Get("detail"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/UnsupportedRegexReason.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// Describes the reason why a given regular expression isn't supported.
6 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-UnsupportedRegexReason 7 | ///
8 | public enum UnsupportedRegexReason 9 | { 10 | /// 11 | /// Block the network request. 12 | /// 13 | [JsonPropertyName("syntaxError")] 14 | SyntaxError, 15 | /// 16 | /// Block the network request. 17 | /// 18 | [JsonPropertyName("memoryLimitExceeded")] 19 | MemoryLimitExceeded, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Content/ContentOverlayRouteInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | public class ContentOverlayRouteInfo 6 | { 7 | public string Location { get; init; } 8 | public Type ContentComponentType { get; init; } 9 | public Match Match { get; init; } 10 | public ContentLocationAttribute ContentLocationAttribute { get; init; } 11 | public ContentOverlayRouteInfo(string location, Type contentComponentType, Match match, ContentLocationAttribute contentLocationAttribute) 12 | { 13 | Location = location; 14 | ContentLocationAttribute = contentLocationAttribute; 15 | ContentComponentType = contentComponentType; 16 | Match = match; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/IsRegexSupportedResult.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-IsRegexSupportedResult 5 | /// 6 | public class IsRegexSupportedResult 7 | { 8 | /// 9 | /// boolean Whether the regular expression is supported. 10 | /// 11 | public bool IsSupported { get; set; } 12 | /// 13 | /// string Specifies the reason why the regular expression is not supported. Possible values are "syntaxError" and "memoryLimitExceeded". Only provided if isSupported is false. 14 | /// 15 | public EnumString? Reason { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/UpdateRuleOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-UpdateRuleOptions 6 | /// 7 | public class UpdateRuleOptions 8 | { 9 | /// 10 | /// Rules to add. 11 | /// 12 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 13 | public Rule[]? AddRules { get; set; } 14 | /// 15 | /// IDs of the rules to remove. Any invalid IDs will be ignored. 16 | /// 17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 18 | public int[]? RemoveRuleIds{ get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/ExtensionTypes/FrameType.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// The type of frame.
7 | /// https://developer.chrome.com/docs/extensions/reference/api/extensionTypes#type-FrameType 8 | ///
9 | public enum FrameType 10 | { 11 | /// 12 | /// OutermostFrame 13 | /// 14 | [JsonPropertyName("outermost_frame")] 15 | OutermostFrame, 16 | /// 17 | /// FencedFrame 18 | /// 19 | [JsonPropertyName("fenced_frame")] 20 | FencedFrame, 21 | /// 22 | /// SubFrame 23 | /// 24 | [JsonPropertyName("sub_frame")] 25 | SubFrame, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Tabs/ActiveInfo.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// Active Tab info
5 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onActivated#activeinfo_2 6 | ///
7 | public class ActiveInfo 8 | { 9 | /// 10 | /// integer. The ID of the previous activated tab, if that tab is still open. 11 | /// 12 | public int PreviousTabId { get; set; } 13 | /// 14 | /// integer. The ID of the tab that has become active. 15 | /// 16 | public int TabId { get; set; } 17 | /// 18 | /// integer. The ID of the tab's window. 19 | /// 20 | public int WindowId { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Tabs/TabMessageOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options object used with Tabs.SendMessage()
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/sendMessage#options 8 | ///
9 | public class TabMessageOptions 10 | { 11 | /// 12 | /// integer. Sends the message to a specific frame identified by frameId instead of all frames in the tab. Whether the content script is executed in all frames depends on the all_frames setting in the content_scripts section of manifest.json. 13 | /// 14 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 15 | public int? FrameId { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/HeaderOperation.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// This describes the possible operations for a "modifyHeaders" rule.
6 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-HeaderOperation 7 | ///
8 | public enum HeaderOperation 9 | { 10 | /// 11 | /// Append 12 | /// 13 | [JsonPropertyName("append")] 14 | Append, 15 | /// 16 | /// Set 17 | /// 18 | [JsonPropertyName("set")] 19 | Set, 20 | /// 21 | /// Remove 22 | /// 23 | [JsonPropertyName("remove")] 24 | Remove, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/Ruleset.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-Ruleset 5 | /// 6 | public class Ruleset 7 | { 8 | /// 9 | /// Whether the ruleset is enabled by default. 10 | /// 11 | public bool Enabled { get; set; } 12 | /// 13 | /// A non-empty string uniquely identifying the ruleset. IDs beginning with '_' are reserved for internal use. 14 | /// 15 | public string Id{ get; set; } 16 | /// 17 | /// The path of the JSON ruleset relative to the extension directory. 18 | /// 19 | public string Path { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension.Build/SpawnDev.BlazorJS.BrowserExtension.Build.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 10.0 6 | ..\SpawnDev.BlazorJS.BrowserExtension\tasks\netstandard2.0 7 | true 8 | 1.0.0 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/DomainType.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// This describes whether the request is first or third party to the frame in which it originated. A request is said to be first party if it has the same domain (eTLD+1) as the frame in which the request originated.
6 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-DomainType 7 | ///
8 | public enum DomainType 9 | { 10 | /// 11 | /// FirstParty 12 | /// 13 | [JsonPropertyName("firstParty")] 14 | FirstParty, 15 | /// 16 | /// ThirdParty 17 | /// 18 | [JsonPropertyName("thirdParty")] 19 | ThirdParty, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Runtime/OnPerformanceWarningSeverity.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// The severity of warning that dispatched the runtime.onPerformanceWarning event.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/OnPerformanceWarningSeverity 8 | ///
9 | public enum OnPerformanceWarningSeverity 10 | { 11 | /// 12 | /// Low 13 | /// 14 | [JsonPropertyName("low")] 15 | Low, 16 | /// 17 | /// Low 18 | /// 19 | [JsonPropertyName("medium")] 20 | Medium, 21 | /// 22 | /// Low 23 | /// 24 | [JsonPropertyName("high")] 25 | High, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Tabs/MutedInfo.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// This object contains a boolean indicating whether the tab is muted, and the reason for the last state change.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/MutedInfo 8 | ///
9 | public class MutedInfo : JSObject 10 | { 11 | /// 12 | /// Deserialization constructor 13 | /// 14 | public MutedInfo(IJSInProcessObjectReference _ref) : base(_ref) { } 15 | /// 16 | /// boolean. Whether the tab is currently muted. Equivalent to whether the muted audio indicator is showing. 17 | /// 18 | public bool Muted => JSRef!.Get("muted"); 19 | // TODO 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [LostBeard] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 15 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/MatchedRuleInfo.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-MatchedRuleInfo 5 | /// 6 | public class MatchedRuleInfo 7 | { 8 | /// 9 | /// The matched rule 10 | /// 11 | public MatchedRule Rule { get; set; } 12 | /// 13 | /// The tabId of the tab from which the request originated if the tab is still active. Else -1. 14 | /// 15 | public int TabId { get; set; } 16 | /// 17 | /// The time the rule was matched. Timestamps will correspond to the Javascript convention for times, i.e. number of milliseconds since the epoch. 18 | /// 19 | public double TimeStamp { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/MatchedRulesFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-MatchedRulesFilter 6 | /// 7 | public class MatchedRulesFilter 8 | { 9 | /// 10 | /// If specified, only matches rules after the given timestamp. 11 | /// 12 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 13 | public double? MinTimeStamp { get; set; } 14 | /// 15 | /// If specified, only matches rules for the given tab. Matches rules not associated with any active tab if set to -1. 16 | /// 17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 18 | public int? TabId { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/UpdateRulesetOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-UpdateRulesetOptions 6 | /// 7 | public class UpdateRulesetOptions 8 | { 9 | /// 10 | /// The set of ids corresponding to a static Ruleset that should be disabled. 11 | /// 12 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 13 | public string[] DisableRulesetIds { get; set; } 14 | /// 15 | /// The set of ids corresponding to a static Ruleset that should be enabled. 16 | /// 17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 18 | public string[] EnableRulesetIds { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/ContentBridge/ExtensionContentBridgeOptions.cs: -------------------------------------------------------------------------------- 1 | using SpawnDev.BlazorJS.JSObjects; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace SpawnDev.BlazorJS.BrowserExtension 5 | { 6 | public class ExtensionContentBridgeOptions 7 | { 8 | public string InstanceId { get; set; } 9 | public string RemoteInstanceId { get; set; } 10 | 11 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 12 | public bool? Serve { get; set; } 13 | 14 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 15 | public EventTarget? EventElement { get; set; } 16 | public ExtensionContentBridgeOptions(string instanceId, string remoteInstanceId, EventTarget? eventElement = null) 17 | { 18 | InstanceId = instanceId; 19 | RemoteInstanceId = remoteInstanceId; 20 | EventElement = eventElement; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Windows/WindowType.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// The type of browser window this is.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/WindowType 8 | ///
9 | public enum WindowType 10 | { 11 | /// 12 | /// Normal 13 | /// 14 | [JsonPropertyName("normal")] 15 | Normal, 16 | /// 17 | /// Popup 18 | /// 19 | [JsonPropertyName("popup")] 20 | Popup, 21 | /// 22 | /// Panel 23 | /// 24 | [JsonPropertyName("panel")] 25 | Panel, 26 | /// 27 | /// DevTools 28 | /// 29 | [JsonPropertyName("devtools")] 30 | DevTools, 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Content/ContentLocationAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | public class ContentLocationAttribute : Attribute 4 | { 5 | /// 6 | /// ContentLocationAttribute name 7 | /// 8 | public string Name { get; private set; } = ""; 9 | /// 10 | /// Higher weights will be used before lower 11 | /// 12 | public int Weight { get; private set; } = 0; 13 | /// 14 | /// The pattern that will be used to vaildate the route 15 | /// 16 | public string LocationRegexPattern { get; private set; } 17 | public ContentLocationAttribute(string locationRegexPattern, int weight = 0, string name = "") 18 | { 19 | Name = name ?? ""; 20 | LocationRegexPattern = locationRegexPattern; 21 | Weight = weight; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/GetPopupDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options used for Action.GetPopup()
7 | /// - If windowId and tabId are both supplied, the function fails.
8 | /// - If windowId and tabId are both omitted, the global popup is returned.
9 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/getPopup#details 10 | ///
11 | public class GetPopupDetails 12 | { 13 | /// 14 | /// integer. The tab whose popup to get. 15 | /// 16 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 17 | public int? TabId { get; set; } 18 | /// 19 | /// integer. The windows whose popup to get. 20 | /// 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 22 | public int? WindowId { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Runtime/ConnectInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Details of the connection
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connect#connectinfo 8 | ///
9 | public class ConnectInfo 10 | { 11 | /// 12 | /// string. Will be passed into runtime.onConnect for processes that are listening for the connection event. 13 | /// 14 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 15 | public string? Name { get; set; } 16 | /// 17 | /// boolean. Whether the TLS channel ID will be passed into runtime.onConnectExternal for processes that are listening for the connection event. 18 | /// 19 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 20 | public bool? IncludeTlsChannelId { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/IsEnabledDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options used for Action.IsEnabled()
7 | /// - If windowId and tabId are both supplied, the function fails.
8 | /// - If windowId and tabId are both omitted, the global enabled/disabled status is returned.
9 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/isEnabled#details 10 | ///
11 | public class IsEnabledDetails 12 | { 13 | /// 14 | /// integer. ID of a tab to check. 15 | /// 16 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 17 | public int? TabId { get; set; } 18 | /// 19 | /// integer. ID of a window to check. 20 | /// 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 22 | public int? WindowId { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Runtime/OnRestartRequiredReason.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// The reason that the onRestartRequired event is being dispatched.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/OnRestartRequiredReason 8 | ///
9 | public enum OnRestartRequiredReason 10 | { 11 | /// 12 | /// The application is being updated to a newer version. 13 | /// 14 | [JsonPropertyName("app_update")] 15 | AppUpdate, 16 | /// 17 | /// The browser/OS is updated to a newer version. 18 | /// 19 | [JsonPropertyName("os_update")] 20 | OSUpdate, 21 | /// 22 | /// The system has run for more than the permitted uptime set in the enterprise policy. 23 | /// 24 | [JsonPropertyName("periodic")] 25 | Periodic, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/ExtensionActionOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-ExtensionActionOptions 6 | /// 7 | public class ExtensionActionOptions 8 | { 9 | /// 10 | /// boolean Whether to automatically display the action count for a page as the extension's badge text. This preference persists across sessions. 11 | /// 12 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 13 | public bool? DisplayActionCountAsBadgeText { get; set; } 14 | /// 15 | /// TabActionCountUpdate. Details of how the tab's action count should be adjusted. See the tabUpdate section for more details. 16 | /// 17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 18 | public TabActionCountUpdate? TabUpdate { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/QueryTransform.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// An object describing how to add, remove, or replace query key-value pairs. Cannot be specified if 'query' is specified.
6 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest/URLTransform#querytransform 7 | ///
8 | public class QueryTransform 9 | { 10 | /// 11 | /// An array of objects describing the list of query key-value pairs to be added or replaced. 12 | /// 13 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 14 | public QueryKeyValue[]? AddOrReplaceParams { get; set; } 15 | /// 16 | /// An array of string. The list of query keys to be removed. 17 | /// 18 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 19 | public string[]? RemoveParams { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/GetTitleDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options used for Action.GetTitle()
7 | /// - If windowId and tabId are both supplied, the function fails and the promise it returns is rejected.
8 | /// - If windowId and tabId are both omitted, the global title is returned.
9 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/getTitle#details 10 | ///
11 | public class GetTitleDetails 12 | { 13 | /// 14 | /// integer. Sets the title only for the given tab. 15 | /// 16 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 17 | public int? TabId { get; set; } 18 | /// 19 | /// integer. Sets the title for the given window. 20 | /// 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 22 | public int? WindowId { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/GetBadgeTextDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options used for Action.GetBadgeText()
7 | /// - If windowId and tabId are both supplied, the function fails.
8 | /// - If windowId and tabId are both omitted, the global badge text is returned.
9 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/getBadgeText#details 10 | ///
11 | public class GetBadgeTextDetails 12 | { 13 | /// 14 | /// integer. Specifies the tab from which to get the badge text. 15 | /// 16 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 17 | public int? TabId { get; set; } 18 | /// 19 | /// integer. Specifies the window from which to get the badge text. 20 | /// 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 22 | public int? WindowId { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/RegexOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-RegexOptions 6 | /// 7 | public class RegexOptions 8 | { 9 | /// 10 | /// Whether the regex specified is case sensitive. Default is true. 11 | /// 12 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 13 | public bool? IsCaseSensitive { get; set; } 14 | /// 15 | /// The regular expresson to check. 16 | /// 17 | public string Regex{ get; set; } 18 | /// 19 | /// Whether the regex specified requires capturing. Capturing is only required for redirect rules which specify a regexSubstition action. The default is false. 20 | /// 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 22 | public bool? RequireCapturing { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/GetBadgeTextColorDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options used for Action.GetBadgeTextColor()
7 | /// - If windowId and tabId are both supplied, the function fails.
8 | /// - If windowId and tabId are both omitted, the global badge text color is returned.
9 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/getBadgeTextColor#details 10 | ///
11 | public class GetBadgeTextColorDetails 12 | { 13 | /// 14 | /// integer. Specifies the tab to get the badge text color from. 15 | /// 16 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 17 | public int? TabId { get; set; } 18 | /// 19 | /// integer. Specifies the window from which to get the badge text color. 20 | /// 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 22 | public int? WindowId { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/WebRequest/WebRequest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Add event listeners for the various stages of making an HTTP request, which includes websocket requests on ws:// and wss://. The event listener receives detailed information about the request and can modify or cancel the request.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest 8 | ///
9 | public partial class WebRequest : JSObject 10 | { 11 | /// 12 | /// Deserialization constructor 13 | /// 14 | /// 15 | public WebRequest(IJSInProcessObjectReference _ref) : base(_ref) { } 16 | public WebRequestEvent OnBeforeRequest { get => JSRef!.Get("onBeforeRequest"); set { } } 17 | 18 | } 19 | public class BlockingResponse 20 | { 21 | 22 | } 23 | public class RequestFilter 24 | { 25 | 26 | } 27 | public class WebRequestDetails 28 | { 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/UpdateStaticRulesOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-UpdateStaticRulesOptions 6 | /// 7 | public class UpdateStaticRulesOptions 8 | { 9 | /// 10 | /// Set of ids corresponding to rules in the Ruleset to disable. 11 | /// 12 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 13 | public int[]? DisableRuleIds { get; set; } 14 | /// 15 | /// Set of ids corresponding to rules in the Ruleset to enable. 16 | /// 17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 18 | public int[]? EnableRuleIds { get; set; } 19 | /// 20 | /// The id corresponding to a static Ruleset. 21 | /// 22 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 23 | public string? RulesetId { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/ExtensionTypes/DocumentLifecycle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.Json.Serialization; 6 | using System.Threading.Tasks; 7 | 8 | namespace SpawnDev.BlazorJS.BrowserExtension 9 | { 10 | /// 11 | /// The document lifecycle of the frame.
12 | /// https://developer.chrome.com/docs/extensions/reference/api/extensionTypes#type-DocumentLifecycle 13 | ///
14 | public enum DocumentLifecycle 15 | { 16 | /// 17 | /// Prerender 18 | /// 19 | [JsonPropertyName("perender")] 20 | Prerender, 21 | /// 22 | /// Active 23 | /// 24 | [JsonPropertyName("active")] 25 | Active, 26 | /// 27 | /// Cached 28 | /// 29 | [JsonPropertyName("cached")] 30 | Cached, 31 | /// 32 | /// PendingDeletion 33 | /// 34 | [JsonPropertyName("pending_deletion")] 35 | PendingDeletion, 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/GetBadgeBackgroundColorDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options used for Action.GetBadgeBackgroundColor()
7 | /// - If windowId and tabId are both supplied, the function fails.
8 | /// - If windowId and tabId are both omitted, the global badge background color is returned.
9 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/getBadgeBackgroundColor#details 10 | ///
11 | public class GetBadgeBackgroundColorDetails 12 | { 13 | /// 14 | /// integer. Specifies the tab to get the badge background color from. 15 | /// 16 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 17 | public int? TabId { get; set; } 18 | /// 19 | /// integer. Specifies the window from which to get the badge background color. 20 | /// 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 22 | public int? WindowId { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Services/ExtensionMode.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension.Services 2 | { 3 | /// 4 | /// Extension mode 5 | /// 6 | public enum ExtensionMode 7 | { 8 | /// 9 | /// Not running as part of an extension 10 | /// 11 | None, 12 | /// 13 | /// Running as a content script or page 14 | /// 15 | Content, 16 | /// 17 | /// Running as a background script or page 18 | /// 19 | Background, 20 | /// 21 | /// Running as an extension page (chrome-extension:// or moz-extension://) 22 | /// 23 | ExtensionPage, 24 | ///// 25 | ///// Running as a popup 26 | ///// 27 | //Popup, 28 | ///// 29 | ///// Running as an options invocation 30 | ///// 31 | //Options, 32 | ///// 33 | ///// Running as an invocation of an install event 34 | ///// 35 | //Installed, 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/QueryKeyValue.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// An object describing the list of query key-value pairs to be added or replaced.
6 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-QueryKeyValue
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest/URLTransform#addorreplaceparams 8 | ///
9 | public class QueryKeyValue 10 | { 11 | /// 12 | /// An array of integer. The IDs of the rules to return. 13 | /// 14 | public string Key { get; set; } 15 | /// 16 | /// If true, the query key is replaced only if it's already present. Otherwise, the key is also added if it's missing. Defaults to false. 17 | /// 18 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 19 | public bool? ReplaceOnly { get; set; } 20 | /// 21 | /// An array of integer. The IDs of the rules to return. 22 | /// 23 | public string Value { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Runtime/OnPerformanceWarningDetails.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// Details passed to the event handler for Runtime.OnPerformanceWarning
5 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onPerformanceWarning#details 6 | ///
7 | public class OnPerformanceWarningDetails 8 | { 9 | /// 10 | /// runtime.OnPerformanceWarningCategory. The category of the warning. 11 | /// 12 | public EnumString Category { get; set; } 13 | /// 14 | /// runtime.OnPerformanceWarningSeverity. The severity of the warning. 15 | /// 16 | public EnumString Severity { get; set; } 17 | /// 18 | /// integer. The ID of the tab that the performance warning relates to, if any. 19 | /// 20 | public int? TabId { get; set; } 21 | /// 22 | /// string. An explanation of what the warning means, possibly with information on how to address it. 23 | /// 24 | public string Description { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/ModifyHeaderInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// The request or response header to modify for a request, declared in the rule.action.requestHeaders array or rule.action.responseHeaders array for rules whose rule.action.type is "modifyHeaders".
6 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest/ModifyHeaderInfo 7 | ///
8 | public class ModifyHeaderInfo 9 | { 10 | /// 11 | /// A string. The name of the header to be modified. 12 | /// 13 | public string Header { get; set; } 14 | /// 15 | /// A string. The operation to be performed on a header. Possible values are "append", "set", and "remove". 16 | /// 17 | public EnumString Operation { get; set; } 18 | /// 19 | /// A string. The new value for the header. Must be specified for append and set operations. Not allowed for the "remove" operation. 20 | /// 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 22 | public string? Value { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Windows/GetInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options use with Windows.Get()
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/get#getinfo 8 | ///
9 | public class GetInfo 10 | { 11 | /// 12 | /// boolean. If true, the windows.Window object will have a tabs property that contains a list of tabs.Tab objects representing the tabs open in the window. The Tab objects only contain the url, title and favIconUrl properties if the extension's manifest file includes the "tabs" permission or a matching host permission. 13 | /// 14 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 15 | public bool? Populate { get; set; } 16 | /// 17 | /// array of windows.WindowType objects. If set, the windows.Window returned will be filtered based on its type. If unset the default filter is set to ['normal', 'panel', 'popup'], with 'panel' window types limited to the extension's own windows. 18 | /// 19 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 20 | public EnumString[]? WindowTypes{ get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Runtime/OnInstalledDetails.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// Details passed to the event handler for Runtime.OnInstalled
5 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onInstalled#details 6 | ///
7 | public class OnInstalledDetails 8 | { 9 | /// 10 | /// string. The ID of the imported shared module extension that updated. This is present only if the reason value is shared_module_update. 11 | /// 12 | public string? Id { get; set; } 13 | /// 14 | /// string. The previous version of the extension just updated. This is only present if the reason value is update. 15 | /// 16 | public string? PreviousVersion { get; set; } 17 | /// 18 | /// An runtime.OnInstalledReason value, stating the reason that this event is being dispatched. 19 | /// 20 | public EnumString? Reason { get; set; } 21 | /// 22 | /// boolean. True if the add-on was installed temporarily. For example, using the "about:debugging" page in Firefox or using web-ext run. False otherwise. 23 | /// 24 | public bool Temporary { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Runtime/OnInstalledReason.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// The reason that the runtime.onInstalled event is being dispatched.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/OnInstalledReason 8 | ///
9 | public enum OnInstalledReason 10 | { 11 | /// 12 | /// The extension was installed. 13 | /// 14 | [JsonPropertyName("install")] 15 | Install, 16 | /// 17 | /// The extension was updated to a new version. 18 | /// 19 | [JsonPropertyName("update")] 20 | Update, 21 | /// 22 | /// The browser was updated to a new version. 23 | /// 24 | [JsonPropertyName("browser_update")] 25 | BrowserUpdate, 26 | /// 27 | /// The browser was updated to a new version. 28 | /// 29 | [JsonPropertyName("chrome_update")] 30 | ChromeUpdate, 31 | /// 32 | /// Another extension, which contains a module used by this extension, was updated. 33 | /// 34 | [JsonPropertyName("shared_module_update")] 35 | SharedModuleUpdate, 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # SpawnDev.BlazorJS.BrowserExtension 3 | 4 | This project is new and under active development. A Nuget package will be released soon. 5 | 6 | SpawnDev.BlazorJS.BrowserExtension adds the ability for Blazor WASM to run as a web browser Manifest V3 extension. Blazor can run in all extension contexts. Runs in content context (in page with any site), popup window, options window, and the background. 7 | 8 | ## Features 9 | - Manifest V3 10 | - Create a fully functional Manifest V3 web browser extension without writing a single line of Javascript 11 | - Multi-platform extension builds (Firefox, Chrome, etc) 12 | - Supports non-SIMD compatible browsers/devices. Uses SIMD when available 13 | - Shared and platform specific manifest entries 14 | - Blazor WASM runs in ALL extension contexts: 15 | - Background page (Firefox) 16 | - Background ServiceWorker (Chrome) 17 | - Content script 18 | - Options, Popup, etc 19 | - Direct access to extension [APIs](https://developer.chrome.com/docs/extensions/reference/api) via C# 20 | - Extension, Runtime, Tabs, Windows, Storage, etc 21 | 22 | 23 | ### Dependencies 24 | - [SpawnDev.BlazorJS](https://github.com/LostBeard/SpawnDev.BlazorJS) - Enables full access to the Javascript environment, and Javascript class wrapping. 25 | - [SpawnDev.BlazorJS.WebWorkers](https://github.com/LostBeard/SpawnDev.BlazorJS.WebWorkers) - Enables running Blazor WebAssembly in any web browser context, and inter-context communication. 26 | 27 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Windows/WindowState.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// The state of this browser window.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/WindowState 8 | ///
9 | public enum WindowState 10 | { 11 | /// 12 | /// The window is at the default size or user-selected size. 13 | /// 14 | [JsonPropertyName("normal")] 15 | Normal, 16 | /// 17 | /// The window is only visible as an icon in the taskbar or . 18 | /// 19 | [JsonPropertyName("minimized")] 20 | Minimized, 21 | /// 22 | /// The window fills the screen on which it is displayed not including any screen areas reserved by the operating system. 23 | /// 24 | [JsonPropertyName("maximized")] 25 | Maximized, 26 | /// 27 | /// The window is running as a full screen application or content in a tab is using the Fullscreen API 28 | /// 29 | [JsonPropertyName("fullscreen")] 30 | Fullscreen, 31 | /// 32 | /// A docked window occupies a fixed position relative to other windows owned by the same application. 33 | /// 34 | [JsonPropertyName("docked")] 35 | Docked, 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/RequestMethod.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-RequestMethod 6 | /// 7 | public enum RequestMethod 8 | { 9 | /// 10 | /// Connect 11 | /// 12 | [JsonPropertyName("connect")] 13 | Connect, 14 | /// 15 | /// Delete 16 | /// 17 | [JsonPropertyName("delete")] 18 | Delete, 19 | /// 20 | /// Get 21 | /// 22 | [JsonPropertyName("get")] 23 | Get, 24 | /// 25 | /// Head 26 | /// 27 | [JsonPropertyName("head")] 28 | Head, 29 | /// 30 | /// Options 31 | /// 32 | [JsonPropertyName("options")] 33 | Options, 34 | /// 35 | /// Patch 36 | /// 37 | [JsonPropertyName("patch")] 38 | Patch, 39 | /// 40 | /// Post 41 | /// 42 | [JsonPropertyName("post")] 43 | Post, 44 | /// 45 | /// Put 46 | /// 47 | [JsonPropertyName("put")] 48 | Put, 49 | /// 50 | /// Other 51 | /// 52 | [JsonPropertyName("other")] 53 | Other, 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/Rule.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// The object describing the actions to take for matching requests. These can be specified in the static rule resources linked by the manifest.json's declarative_net_request key, or more dynamically through the declarativeNetRequest.updateDynamicRules or declarativeNetRequest.updateSessionRules methods.
6 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest/Rule 7 | ///
8 | public class Rule 9 | { 10 | /// 11 | /// declarativeNetRequest.RuleAction. The action to take if this rule is matched. 12 | /// 13 | public RuleAction Action { get; set; } = default!; 14 | /// 15 | /// declarativeNetRequest.RuleCondition. The condition under which this rule is triggered. 16 | /// 17 | public RuleCondition Condition { get; set; } = default!; 18 | /// 19 | /// number. An ID that uniquely identifies a rule within a ruleset. Mandatory and should be >= 1. 20 | /// 21 | public int Id { get; set; } 22 | /// 23 | /// number. Rule priority. Defaults to 1. When specified, should be >= 1. See Matching precedents for details on how priority affects which rules are applied. 24 | /// 25 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 26 | public int? Priority { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Events/ExtensionEvent.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// An extension event 7 | /// 8 | public class ExtensionEvent : JSObject 9 | { 10 | /// 11 | /// Contains Callback references that will be disposed when an equal number of add and remove listener calls are made 12 | /// 13 | protected static CallbackRef CallbackRef = new(); 14 | /// 15 | /// Deserialization constructor 16 | /// 17 | /// 18 | public ExtensionEvent(IJSInProcessObjectReference _ref) : base(_ref) { } 19 | /// 20 | /// Check whether listener is registered for this event. Returns true if it is listening, false otherwise. 21 | /// 22 | /// 23 | /// 24 | public bool HasListener(Callback callback) => JSRef!.Call("hasListener", callback); 25 | /// 26 | /// Adds a listener to this event. 27 | /// 28 | /// 29 | public void AddListener(Callback callback) => JSRef!.CallVoid("addListener", callback); 30 | /// 31 | /// Stop listening to this event. The listener argument is the listener to remove. 32 | /// 33 | /// 34 | public void RemoveListener(Callback callback) => JSRef!.CallVoid("removeListener", callback); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/RuleActionType.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// Describes the kind of action to take if a given RuleCondition matches.
6 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-RuleActionType 7 | ///
8 | public enum RuleActionType 9 | { 10 | /// 11 | /// Block the network request. 12 | /// 13 | [JsonPropertyName("block")] 14 | Block, 15 | /// 16 | /// Redirect the network request. 17 | /// 18 | [JsonPropertyName("redirect")] 19 | Redirect, 20 | /// 21 | /// Allow the network request. The request won't be intercepted if there is an allow rule which matches it. 22 | /// 23 | [JsonPropertyName("allow")] 24 | Allow, 25 | /// 26 | /// Upgrade the network request url's scheme to https if the request is http or ftp. 27 | /// 28 | [JsonPropertyName("upgradeScheme")] 29 | UpgradeScheme, 30 | /// 31 | /// Modify request/response headers from the network request. 32 | /// 33 | [JsonPropertyName("modifyHeaders")] 34 | ModifyHeaders, 35 | /// 36 | /// Allow all requests within a frame hierarchy, including the frame request itself. 37 | /// 38 | [JsonPropertyName("allowAllRequests")] 39 | AllowAllRequests, 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/SetBadgeBackgroundColorDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options used for Action.SetBadgeBackgroundColor()
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/setBadgeBackgroundColor#details 8 | ///
9 | public class SetBadgeBackgroundColorDetails 10 | { 11 | /// 12 | /// The color, specified as one of:
13 | /// - a string: any CSS <color> value, for example "red", "#FF0000", or "rgb(255 0 0)". If the string is not a valid color, the returned promise will be rejected and the background color won't be altered.
14 | /// - a action.ColorArray object.
15 | /// - null. If a tabId is specified, it removes the tab-specific badge background color so that the tab inherits the global badge background color. Otherwise it reverts the global badge background color to the default value.
16 | ///
17 | public Union? Color { get; set; } 18 | /// 19 | /// integer. Sets the badge background color only for the given tab. The color is reset when the user navigates this tab to a new page. 20 | /// 21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 22 | public int? TabId { get; set; } 23 | /// 24 | /// integer. Sets the badge background color only for the given tab. 25 | /// 26 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 27 | public int? WindowId { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/SetBadgeTextDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options used for Action.SetBadgeText()
7 | /// - If windowId and tabId are both supplied, the function fails.
8 | /// - If windowId and tabId are both omitted, the global badge is set.
9 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/setBadgeText#details 10 | ///
11 | public class SetBadgeTextDetails 12 | { 13 | /// 14 | /// string or null. Any number of characters can be passed, but only about four can fit in the space.
15 | /// Use an empty string - "" - if you don't want any badge.
16 | /// - If a tabId is specified, null removes the tab-specific badge text so that the tab inherits the global badge text. Otherwise it reverts the global badge text to "".
17 | /// - If a windowId is specified, null removes the window-specific badge text so that the tab inherits the global badge text. Otherwise it reverts the global badge text to "".
18 | ///
19 | public string? Text { get; set; } 20 | /// 21 | /// integer. Set the badge text only for the given tab. The text is reset when the user navigates this tab to a new page. 22 | /// 23 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 24 | public int? TabId { get; set; } 25 | /// 26 | /// integer. Set the badge text for the given window. 27 | /// 28 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 29 | public int? WindowId { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/TestMatchRequestDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-TestMatchRequestDetails 6 | /// 7 | public class TestMatchRequestDetails 8 | { 9 | /// 10 | /// A string. The initiator URL (if any) for the hypothetical request. 11 | /// 12 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 13 | public string? Initiator { get; set; } 14 | /// 15 | /// Standard HTTP method of the hypothetical request. Defaults to "get" for HTTP requests and is ignored for non-HTTP requests. 16 | /// 17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 18 | public EnumString? Method { get; set; } 19 | /// 20 | /// A number. The ID of the tab the hypothetical request takes place in. Does not need to correspond to a real tab ID. Default is -1, meaning that the request isn't related to a tab. 21 | /// 22 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 23 | public int? TabId { get; set; } 24 | /// 25 | /// The resource type of the hypothetical request. 26 | /// 27 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 28 | public EnumString? Type { get; set; } 29 | /// 30 | /// The URL of the hypothetical request. 31 | /// 32 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 33 | public string? Url { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/SetBadgeTextColorDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options used for Action.SetBadgeTextColor()
7 | /// - If windowId and tabId are both supplied, the function fails and the color is not set.
8 | /// - If windowId and tabId are both omitted, the global badge text color is set instead.
9 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/setBadgeTextColor#details 10 | ///
11 | public class SetBadgeTextColorDetails 12 | { 13 | /// 14 | /// The color, specified as one of:
15 | /// - a string: any CSS value, for example "red", "#FF0000", or "rgb(255 0 0)". If the string is not a valid color, the returned promise will be rejected and the text color won't be altered.
16 | /// - a action.ColorArray object.
17 | /// - null. If a tabId is specified, it removes the tab-specific badge text color so that the tab inherits the global badge text color. Otherwise it reverts the global badge text color to the default value.
18 | ///
19 | public Union? Color { get; set; } 20 | /// 21 | /// integer. Sets the badge text color only for the given tab. The color is reset when the user navigates this tab to a new page. 22 | /// 23 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 24 | public int? TabId { get; set; } 25 | /// 26 | /// integer. Sets the badge text color only for the given tab. 27 | /// 28 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 29 | public int? WindowId { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/SetTitleDetails.cs: -------------------------------------------------------------------------------- 1 | using SpawnDev.BlazorJS.JSObjects; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace SpawnDev.BlazorJS.BrowserExtension 5 | { 6 | /// 7 | /// Options used for Action.SetTitle()
8 | /// - If windowId and tabId are both supplied, the function fails and the title is not set.
9 | /// - If windowId and tabId are both omitted, the global title is set.
10 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/setTitle#details 11 | ///
12 | public class SetTitleDetails 13 | { 14 | /// 15 | /// string or null. The string the browser action should display when moused over.
16 | /// If title is an empty string, the used title will be the extension name, but action.getTitle will still provide the empty string.
17 | /// If title is null:
18 | /// - If tabId is specified, and the tab has a tab-specific title set, then the tab will inherit the title from the window to which it belongs.
19 | /// - if windowId is specified, and the window has a window-specific title set, then the window will inherit the global title.
20 | /// - Otherwise, the global title will be reset to the manifest title. 21 | ///
22 | public string? Title { get; set; } 23 | /// 24 | /// integer. Sets the title only for the given tab. 25 | /// 26 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 27 | public int? TabId { get; set; } 28 | /// 29 | /// integer. Sets the title for the given window. 30 | /// 31 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 32 | public int? WindowId { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Browser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Extension APIs 7 | /// 8 | public class Browser : JSObject 9 | { 10 | /// 11 | /// Deserialization constructor 12 | /// 13 | public Browser(IJSInProcessObjectReference _ref) : base(_ref) { } 14 | /// 15 | /// Read and modify attributes of and listen to clicks on the browser toolbar button defined with the action manifest key. 16 | /// 17 | public Action? Action => JSRef!.Get("action"); 18 | /// 19 | /// This module provides information about your extension and the environment it's running in. 20 | /// 21 | public Runtime? Runtime => JSRef!.Get("runtime"); 22 | /// 23 | /// Enables extensions to store and retrieve data, and listen for changes to stored items. 24 | /// 25 | public Storage? Storage => JSRef!.Get("storage"); 26 | /// 27 | /// Interact with the browser's tab system. 28 | /// 29 | public Tabs? Tabs => JSRef!.Get("tabs"); 30 | /// 31 | /// The chrome.declarativeNetRequest API is used to block or modify network requests by specifying declarative rules. This lets extensions modify network requests without intercepting them and viewing their content, thus providing more privacy. 32 | /// 33 | public DeclarativeNetRequest? DeclarativeNetRequest => JSRef!.Get("declarativeNetRequest"); 34 | /// 35 | /// Context menus 36 | /// 37 | public ContextMenus ContextMenus => JSRef!.Get("contextMenus"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/Redirect.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// Details describing how a redirect should be performed, as the redirect property of a RuleAction. Only valid for redirect rules.
6 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest/Redirect 7 | ///
8 | public class Redirect 9 | { 10 | /// 11 | /// A string. The path relative to the extension directory. Should start with '/'. The initiator of the request can only follow the redirect when the resource is listed in web_accessible_resources. 12 | /// 13 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 14 | public string? ExtensionPath { get; set; } 15 | /// 16 | /// A string. The substitution pattern for rules that specify a regexFilter. The first match of regexFilter within the URL is replaced with this pattern. Within regexSubstitution, backslash-escaped digits (\1 to \9) are used to insert the corresponding capture groups. \0 refers to the entire matching text. 17 | /// 18 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 19 | public string? RegexSubstitution { get; set; } 20 | /// 21 | /// declarativeNetRequest.URLTransform. The URL transformations to perform. 22 | /// 23 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 24 | public URLTransform? Transform { get; set; } 25 | /// 26 | /// A string. The redirect URL. Redirects to JavaScript URLs are not allowed. 27 | /// 28 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 29 | public string? Url { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Windows/Windows.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | using SpawnDev.BlazorJS.JSObjects; 3 | 4 | namespace SpawnDev.BlazorJS.BrowserExtension 5 | { 6 | /// 7 | /// Use the chrome.windows API to interact with browser windows. You can use this API to create, modify, and rearrange windows in the browser.
8 | /// https://developer.chrome.com/docs/extensions/reference/api/windows
9 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows
10 | ///
11 | public partial class Windows : JSObject 12 | { 13 | /// 14 | /// Deserialization constructor 15 | /// 16 | public Windows(IJSInProcessObjectReference _ref) : base(_ref) { } 17 | /// 18 | /// Gets details about a window, given its ID. 19 | /// 20 | public Task Get(int windowId, GetInfo details) => JSRef!.CallAsync("get", windowId, details); 21 | /// 22 | /// Gets the current window. 23 | /// 24 | /// 25 | /// 26 | public Task GetCurrent(GetInfo details) => JSRef!.CallAsync("getCurrent", details); 27 | /// 28 | /// Gets the window that was most recently focused — typically the window 'on top'. 29 | /// 30 | /// 31 | /// 32 | public Task GetLastFocused(GetInfo details) => JSRef!.CallAsync("getLastFocused", details); 33 | /// 34 | /// Gets all windows. 35 | /// 36 | /// 37 | /// 38 | public Task?> GetAll(GetInfo details) => JSRef!.CallAsync?>("getAll", details); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/SetPopupDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Options used for Action.SetPopup()
7 | /// - If windowId and tabId are both supplied, the function fails and the popup is not set.
8 | /// - If windowId and tabId are both omitted, the global popup is set.
9 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/setPopup#details 10 | ///
11 | public class SetPopupDetails 12 | { 13 | /// 14 | /// string or null. The HTML file to show in a popup, specified as a URL.
15 | /// This can point to a file packaged within the extension (for example, created using extension.getURL), or a remote document (e.g. https://example.org/).
16 | /// If an empty string ("") is passed here, the popup is disabled, and the extension will receive action.onClicked events.
17 | /// If popup is null:
18 | /// - If tabId is specified, removes the tab-specific popup so that the tab inherits the global popup.
19 | /// - If windowId is specified, removes the window-specific popup so that the window inherits the global popup.
20 | /// - If tabId and windowId are both omitted, reverts the global popup to the default value. 21 | ///
22 | public string? Popup { get; set; } 23 | /// 24 | /// integer. Sets the popup only for a specific tab. The popup is reset when the user navigates this tab to a new page. 25 | /// 26 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 27 | public int? TabId { get; set; } 28 | /// 29 | /// integer. Sets the popup only for the specified window. 30 | /// 31 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 32 | public int? WindowId { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension.Build/Tasks/PostBuildTask.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Build.Framework; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Text.Json; 8 | using System.Text.RegularExpressions; 9 | 10 | namespace SpawnDev.BlazorJS.BrowserExtension.Build.Tasks 11 | { 12 | public class PostBuildTask : Microsoft.Build.Utilities.Task 13 | { 14 | 15 | [Required] 16 | public ITaskItem[] StaticWebAsset { get; set; } 17 | 18 | [Required] 19 | public string ProjectDir { get; set; } 20 | 21 | [Required] 22 | public string OutputPath { get; set; } 23 | 24 | [Required] 25 | public string BasePath { get; set; } 26 | 27 | [Required] 28 | public string IntermediateOutputPath { get; set; } 29 | 30 | [Required] 31 | public bool PatchFramework { get; set; } 32 | 33 | [Required] 34 | public string PackageContentDir { get; set; } 35 | 36 | [Required] 37 | public bool DebugSpawnDevBrowserExtensionBuildTasks { get; set; } 38 | 39 | [Required] 40 | public bool PublishMode { get; set; } 41 | 42 | [Required] 43 | public string ExtensionPlatforms { get; set; } 44 | 45 | public string OutputWwwroot { get; set; } 46 | 47 | public bool Verbose { get; set; } 48 | 49 | public override bool Execute() 50 | { 51 | #if DEBUG 52 | Log.LogWarning($"********************************** PostBuildTask.Execute **********************************"); 53 | #endif 54 | if (DebugSpawnDevBrowserExtensionBuildTasks) 55 | { 56 | System.Diagnostics.Debugger.Launch(); 57 | } 58 | 59 | OutputWwwroot = Path.GetFullPath(Path.Combine(OutputPath, "wwwroot")); 60 | PackageContentDir = Path.GetFullPath(PackageContentDir); 61 | 62 | 63 | 64 | return true; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.10.34607.79 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpawnDev.BlazorJS.BrowserExtension", "SpawnDev.BlazorJS.BrowserExtension\SpawnDev.BlazorJS.BrowserExtension.csproj", "{B9A43F7C-22B1-408B-9D0A-05C86E304472}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {3A49DDD5-F202-447B-B140-BEA3D67DA191} = {3A49DDD5-F202-447B-B140-BEA3D67DA191} 9 | EndProjectSection 10 | EndProject 11 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpawnDev.BlazorJS.BrowserExtension.Build", "SpawnDev.BlazorJS.BrowserExtension.Build\SpawnDev.BlazorJS.BrowserExtension.Build.csproj", "{3A49DDD5-F202-447B-B140-BEA3D67DA191}" 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Any CPU = Debug|Any CPU 16 | Release|Any CPU = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {B9A43F7C-22B1-408B-9D0A-05C86E304472}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {B9A43F7C-22B1-408B-9D0A-05C86E304472}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {B9A43F7C-22B1-408B-9D0A-05C86E304472}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {B9A43F7C-22B1-408B-9D0A-05C86E304472}.Release|Any CPU.Build.0 = Release|Any CPU 23 | {3A49DDD5-F202-447B-B140-BEA3D67DA191}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {3A49DDD5-F202-447B-B140-BEA3D67DA191}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {3A49DDD5-F202-447B-B140-BEA3D67DA191}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {3A49DDD5-F202-447B-B140-BEA3D67DA191}.Release|Any CPU.Build.0 = Release|Any CPU 27 | EndGlobalSection 28 | GlobalSection(SolutionProperties) = preSolution 29 | HideSolutionNode = FALSE 30 | EndGlobalSection 31 | GlobalSection(ExtensibilityGlobals) = postSolution 32 | SolutionGuid = {2025B37E-D3A5-432E-8AA9-8D9AAEB68E5A} 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/ContentBridge/WrappedObjectJSObjectExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// Adds a few methods to JSObject instances that allow them to access the underlying proxy (if one) 5 | /// 6 | public static class WrappedObjectJSObjectExtensions 7 | { 8 | /// 9 | /// Returns true if the JSObject is a wrappedObject proxy 10 | /// 11 | /// 12 | /// 13 | public static bool IsWrappedObject(this JSObject _this) => !_this.JSRef!.IsUndefined("__wrappedObjectRelease"); 14 | /// 15 | /// Releases the object on the main content side 16 | /// 17 | /// 18 | /// 19 | public static bool WrappedObjectRelease(this JSObject _this) => _this.JSRef!.Call("__wrappedObjectRelease"); 20 | /// 21 | /// Requests a "clean" version of the object from the main side
22 | /// The object is cleaned by running it through JSON.Parse(JSON.stringify(object))
23 | /// This call may fail if the JSON.stringify method fails (possibly due to circular references) 24 | ///
25 | /// 26 | /// 27 | /// 28 | public static T WrappedObjectDecon(this JSObject _this) => _this.JSRef!.Call("__wrappedObjectDecon"); 29 | /// 30 | /// Requests an unwrapped (direct) version of the object
31 | /// This call may fail if the main side prevents the object from being returned 32 | ///
33 | /// 34 | /// 35 | /// 36 | public static T WrappedObjectDirect(this JSObject _this) => _this.JSRef!.Call("__wrappedObjectDirect"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/build/SpawnDev.BlazorJS.BrowserExtension.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | true 9 | 10 | Chrome;Firefox 11 | 12 | false 13 | 14 | wwwroot 15 | $(Configuration)Extension 16 | 17 | <_DebugSpawnDevBrowserExtensionBuildTasks Condition="'$(_DebugSpawnDevBrowserExtensionBuildTasks)' == ''">false 18 | <_SpawnDevBrowserExtensionBuildTasksAssembly Condition="'$(_SpawnDevBrowserExtensionBuildTasksAssembly)' == ''">$(MSBuildThisFileDirectory)..\tasks\netstandard2.0\SpawnDev.BlazorJS.BrowserExtension.Build.dll 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/RuleAction.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// Details of the action to take if a rule is matched, as the action property of a declarativeNetRequest.Rule.
6 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest/RuleAction 7 | ///
8 | public class RuleAction 9 | { 10 | /// 11 | /// declarativeNetRequest.Redirect. Describes how the redirect should be performed. Only valid for redirect rules. 12 | /// 13 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 14 | public Redirect? Redirect { get; set; } 15 | /// 16 | /// declarativeNetRequest.ModifyHeaderInfo. The request headers to modify for the request. Only valid if type is "modifyHeaders". 17 | /// 18 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 19 | public ModifyHeaderInfo[]? RequestHeaders { get; set; } 20 | /// 21 | /// declarativeNetRequest.ModifyHeaderInfo. The response headers to modify for the request. Only valid if type is "modifyHeaders". 22 | /// 23 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 24 | public ModifyHeaderInfo[]? ResponseHeaders { get; set; } 25 | /// 26 | /// A string. The type of action to perform. Possible values are "block", "redirect", "allow", "upgradeScheme", "modifyHeaders", and "allowAllRequests". The use of the "redirect" and "modifyHeaders" actions require host permissions for the request and request initiator. The "block" and "upgradeScheme" actions also require host permissions unless the "declarativeNetRequest" permission is specified. Without these permissions, matching rules are ignored. See Permissions at declarativeNetRequest for more information. More details about the effects of rule actions are provided in Matching precedents. 27 | /// 28 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 29 | public EnumString? Type { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Tabs/CreateTabProperties.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/create#createproperties
7 | /// https://developer.chrome.com/docs/extensions/reference/api/tabs#parameters_2
8 | ///
9 | public class CreateTabProperties 10 | { 11 | /// 12 | /// Whether the tab should become the active tab in the window. Does not affect whether the window is focused (see windows.update). Defaults to true. 13 | /// 14 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 15 | public bool? Active { get; set; } 16 | /// 17 | /// The position the tab should take in the window. The provided value is clamped to between zero and the number of tabs in the window. 18 | /// 19 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 20 | public int? Index { get; set; } 21 | /// 22 | /// The ID of the tab that opened this tab. If specified, the opener tab must be in the same window as the newly created tab. 23 | /// 24 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 25 | public int? OpenerTabId { get; set; } 26 | /// 27 | /// Whether the tab should be pinned. Defaults to false 28 | /// 29 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 30 | public bool? Pinned { get; set; } 31 | /// 32 | /// The URL to initially navigate the tab to. Fully-qualified URLs must include a scheme (i.e., 'http://www.google.com', not 'www.google.com'). Relative URLs are relative to the current page within the extension. Defaults to the New Tab Page. 33 | /// 34 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 35 | public string? Url { get; set; } 36 | /// 37 | /// The window in which to create the new tab. Defaults to the current window. 38 | /// 39 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 40 | public int? WindowId { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/ResourceType.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-ResourceType 6 | /// 7 | public enum ResourceType 8 | { 9 | /// 10 | /// MainFrame 11 | /// 12 | [JsonPropertyName("main_frame")] 13 | MainFrame, 14 | /// 15 | /// SubFrame 16 | /// 17 | [JsonPropertyName("sub_frame")] 18 | SubFrame, 19 | /// 20 | /// StyleSheet 21 | /// 22 | [JsonPropertyName("stylesheet")] 23 | StyleSheet, 24 | /// 25 | /// Script 26 | /// 27 | [JsonPropertyName("script")] 28 | Script, 29 | /// 30 | /// Image 31 | /// 32 | [JsonPropertyName("image")] 33 | Image, 34 | /// 35 | /// Font 36 | /// 37 | [JsonPropertyName("font")] 38 | Font, 39 | /// 40 | /// Object 41 | /// 42 | [JsonPropertyName("object")] 43 | Object, 44 | /// 45 | /// XMLHttpRequest 46 | /// 47 | [JsonPropertyName("xmlhttprequest")] 48 | XMLHttpRequest, 49 | /// 50 | /// Ping 51 | /// 52 | [JsonPropertyName("ping")] 53 | Ping, 54 | /// 55 | /// CSPReport 56 | /// 57 | [JsonPropertyName("csp_report")] 58 | CSPReport, 59 | /// 60 | /// Media 61 | /// 62 | [JsonPropertyName("media")] 63 | Media, 64 | /// 65 | /// WebSocket 66 | /// 67 | [JsonPropertyName("websocket")] 68 | WebSocket, 69 | /// 70 | /// WebTransport 71 | /// 72 | [JsonPropertyName("webtransport")] 73 | WebTransport, 74 | /// 75 | /// WebBundle 76 | /// 77 | [JsonPropertyName("webbundle")] 78 | WebBundle, 79 | /// 80 | /// Other 81 | /// 82 | [JsonPropertyName("other")] 83 | Other, 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Storage/Storage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | using SpawnDev.BlazorJS; 3 | 4 | namespace SpawnDev.BlazorJS.BrowserExtension 5 | { 6 | /// 7 | /// Enables extensions to store and retrieve data, and listen for changes to stored items.
8 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage 9 | ///
10 | public class Storage : JSObject 11 | { 12 | /// 13 | /// Deserialization constructor 14 | /// 15 | /// 16 | public Storage(IJSInProcessObjectReference _ref) : base(_ref) { } 17 | /// 18 | /// Represents the sync storage area. Items in sync storage are synced by the browser, and are available across all instances of that browser that the user is logged into, across different devices. 19 | /// 20 | public StorageArea Sync => JSRef!.Get("sync"); 21 | /// 22 | /// Represents the local storage area. Items in local storage are local to the machine the extension was installed on. 23 | /// 24 | public StorageArea Local => JSRef!.Get("local"); 25 | /// 26 | /// Represents the managed storage area. Items in managed storage are set by the domain administrator and are read-only for the extension. Trying to modify this namespace results in an error. 27 | /// 28 | public StorageArea Managed => JSRef!.Get("managed"); 29 | /// 30 | /// Represents the session storage area. Items in session storage are stored in memory and are not persisted to disk. 31 | /// 32 | public StorageArea Session => JSRef!.Get("session"); 33 | #region Events 34 | /// 35 | /// The function called when this event occurs. The function is passed these arguments:
36 | /// StorageChanges changes - Object describing the change. This object contains properties for all the keys in the storage area included in the storageArea.set call, even if key values are unchanged. The name of each property is the name of each key. The value of each key is a storage.StorageChange object describing the change to that item.
37 | /// string areaName - string. The name of the storage area ("sync", "local", or "managed") to which the changes were made. 38 | ///
39 | public ActionEvent OnChanged { get => JSRef!.Get>("onChanged"); set { } } 40 | #endregion 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/ContentBridge/WrappedObjectProxy.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// WrappedObjectProxy is a Javascript Proxy object that allows working with objects on website Javascript objects over a content bridge 7 | /// 8 | public class WrappedObjectProxy : JSObject 9 | { 10 | /// 11 | /// Deserialization constructor 12 | /// 13 | /// 14 | public WrappedObjectProxy(IJSInProcessObjectReference _ref) : base(_ref) { } 15 | /// 16 | /// The InstanceID of the content bridge dispatcher that owns the proxy 17 | /// 18 | public string? DispatcherId => JSRef!.Get("__wrappedObjectDispatcherId"); 19 | #region Methods 20 | /// 21 | /// Releases the wrapped object proxy 22 | /// 23 | /// 24 | public bool Release() => JSRef!.Call("__wrappedObjectRelease"); 25 | /// 26 | /// Returns the remote object as type T after a JSON.parse(JSON.stringify(data))
27 | /// This can aid in retrieving a copy of a remote object that otherwise would be blocked by the browser
28 | ///
29 | /// 30 | /// 31 | public T Decon() => JSRef!.Call("__wrappedObjectDecon"); 32 | /// 33 | /// Returns the remote object as type T
34 | /// The browser extension environment may block the request, which will cause an exception to be thrown
35 | ///
36 | /// 37 | /// 38 | public T Direct() => JSRef!.Call("__wrappedObjectDirect"); 39 | #endregion 40 | #region Static Methods 41 | /// 42 | /// Get WrappedObjectProxy from a JSObject 43 | /// 44 | /// 45 | /// 46 | public static WrappedObjectProxy GetWrappedObjectProxy(JSObject _ref) => _ref.JSRefCopy(); 47 | /// 48 | /// Returns true if the Javascript object is a WrappedObjectProxy 49 | /// 50 | /// 51 | /// 52 | public static bool IsWrappedObjectProxy(JSObject jsObject) => !string.IsNullOrEmpty(jsObject.JSRef!.Get("__wrappedObjectDispatcherId")); 53 | #endregion 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Tabs/ChangeInfo.cs: -------------------------------------------------------------------------------- 1 | namespace SpawnDev.BlazorJS.BrowserExtension 2 | { 3 | /// 4 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated#changeinfo_2 5 | /// 6 | public class ChangeInfo 7 | { 8 | /// 9 | /// boolean. Indicates whether the tab is drawing attention. For example, attention is true when the tab displays a modal dialog. 10 | /// 11 | public bool? Attention { get; set; } 12 | /// 13 | /// boolean. The tab's new audible state. 14 | /// 15 | public bool? Audible { get; set; } 16 | /// 17 | /// boolean. Whether the tab can be discarded by the browser. The default value is true. When set to false, the browser cannot automatically discard the tab. However, the tab can be discarded by tabs.discard. 18 | /// 19 | public bool? AutoDiscardable { get; set; } 20 | /// 21 | /// boolean. Whether the tab is discarded. A discarded tab is one whose content has been unloaded from memory but is visible in the tab strip. Its content gets reloaded the next time it's activated. 22 | /// 23 | public bool? Discarded { get; set; } 24 | /// 25 | /// string. The tab's new favicon URL. Not included when a tab loses its favicon (navigating from a page with a favicon to a page without one). Check favIconUrl in tab instead. 26 | /// 27 | public string? FavIconUrl { get; set; } 28 | /// 29 | /// boolean. True if the tab is hidden. 30 | /// 31 | public bool? Hidden { get; set; } 32 | /// 33 | /// boolean. True if the tab is an article and is therefore eligible for display in Reader Mode. 34 | /// 35 | public bool? IsArticle { get; set; } 36 | /// 37 | /// tabs.MutedInfo. The tab's new muted state and the reason for the change. 38 | /// 39 | public MutedInfo? MutedInfo { get; set; } 40 | /// 41 | /// boolean. The tab's new pinned state. 42 | /// 43 | public bool? Pinned { get; set; } 44 | /// 45 | /// string. The status of the tab. Can be either loading or complete. 46 | /// 47 | public string? Status { get; set; } 48 | /// 49 | /// string. The tab's new title. 50 | /// 51 | public string? Title{ get; set; } 52 | /// 53 | /// string. The tab's URL, if it has changed. 54 | /// 55 | public string? Url { get; set; } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/SpawnDev.BlazorJS.BrowserExtension.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0;net7.0;net8.0;net9.0 5 | enable 6 | enable 7 | 1.0.1-preview.0 8 | True 9 | true 10 | true 11 | Embedded 12 | SpawnDev.BlazorJS.BrowserExtension 13 | LostBeard 14 | Create Manifest V3 web browser extensions using Blazor WebAssembly 15 | https://github.com/LostBeard/SpawnDev.BlazorJS.BrowserExtension 16 | README.md 17 | LICENSE.txt 18 | icon-128.png 19 | https://github.com/LostBeard/SpawnDev.BlazorJS.BrowserExtension.git 20 | git 21 | Blazor;BlazorWebAssembly;BrowserExtension 22 | true 23 | true 24 | true 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | build 46 | 47 | 48 | true 49 | buildcontent 50 | 51 | 52 | true 53 | tasks 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/URLTransform.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// Details describing a URL transformation to perform for a redirect rule. This object can be specified at rule.action.redirect.transform.
6 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest/URLTransform 7 | ///
8 | public class URLTransform 9 | { 10 | /// 11 | /// A string. The new fragment for the request. Should be either empty, in which case the existing fragment is cleared; or should begin with '#'. 12 | /// 13 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 14 | public string? Fragment{ get; set; } 15 | /// 16 | /// A string. The new host name for the request. 17 | /// 18 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 19 | public string? Host { get; set; } 20 | /// 21 | /// A string. The new password for the request. 22 | /// 23 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 24 | public string? Password { get; set; } 25 | /// 26 | /// A string. The new path for the request. If empty, the existing path is cleared. 27 | /// 28 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 29 | public string? Path { get; set; } 30 | /// 31 | /// A string. The new port for the request. If empty, the existing port is cleared. 32 | /// 33 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 34 | public string? Port { get; set; } 35 | /// 36 | /// A string. The new query for the request. Should be either empty, in which case the existing query is cleared; or should begin with '?'. 37 | /// 38 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 39 | public string? Query { get; set; } 40 | /// 41 | /// An object describing how to add, remove, or replace query key-value pairs. Cannot be specified if 'query' is specified. 42 | /// 43 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 44 | public QueryTransform? QueryTransform{ get; set; } 45 | /// 46 | /// A string. The new scheme for the request. Allowed values are "http", "https", and the scheme of the extension, for example, "moz-extension" in Firefox or "chrome-extension" in Chrome. When the extension scheme is used, the host must be specified to generate a meaningful redirection target. 47 | /// 48 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 49 | public string? Scheme { get; set; } 50 | /// 51 | /// A string. The new username for the request. 52 | /// 53 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 54 | public string? Username { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/SetIconDetails.cs: -------------------------------------------------------------------------------- 1 | using SpawnDev.BlazorJS.JSObjects; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace SpawnDev.BlazorJS.BrowserExtension 5 | { 6 | /// 7 | /// object. An object containing the imageData or path property and, optionally, either or both of the tabId and windowId properties.
8 | /// - If windowId and tabId are both supplied, the function fails and the icon is not set.
9 | /// - If windowId and tabId are both omitted, the global icon is set.
10 | /// If each one of imageData and path is one of undefined, null or empty object:
11 | /// - If tabId is specified, and the tab has a tab-specific icon set, then the tab will inherit the icon from the window to which it belongs.
12 | /// - If windowId is specified, and the window has a window-specific icon set, then the window will inherit the global icon.
13 | /// - Otherwise, the global icon will be reset to the manifest icon. 14 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/setIcon#details 15 | ///
16 | public class SetIconDetails 17 | { 18 | /// 19 | /// action.ImageDataType or object. This is either a single ImageData object or a dictionary object.
20 | /// Use a dictionary object to specify multiple ImageData objects in different sizes, so the icon does not have to be scaled for a device with a different pixel density. If imageData is a dictionary, the value of each property is an ImageData object, and its name is its size.
21 | /// The browser will choose the image to use depending on the screen's pixel density. See Choosing icon sizes for more information on this. 22 | ///
23 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 24 | public Union>? ImageDataType { get; set; } 25 | /// 26 | /// string or object. This is either a relative path to an icon file or it is a dictionary object.
27 | /// Use a dictionary object to specify multiple icon files in different sizes, so the icon does not have to be scaled for a device with a different pixel density. If path is a dictionary, the value of each property is a relative path, and its name is its size.
28 | /// The browser will choose the image to use depending on the screen's pixel density. See Choosing icon sizes for more information on this. 29 | ///
30 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 31 | public Union>? Path { get; set; } 32 | /// 33 | /// integer. Sets the icon only for the given tab. The icon is reset when the user navigates this tab to a new page. 34 | /// 35 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 36 | public int? TabId { get; set; } 37 | /// 38 | /// integer. Sets the icon for the given window. 39 | /// 40 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 41 | public int? WindowId { get; set; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Runtime/MessageSender.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// An object containing information about the sender of a message or connection request that is passed to the runtime.onMessage() listener.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/MessageSender 8 | ///
9 | public class MessageSender : JSObject 10 | { 11 | /// 12 | /// Deserialization constructor 13 | /// 14 | public MessageSender(IJSInProcessObjectReference _ref) : base(_ref) { } 15 | /// 16 | /// string. A UUID of the document that opened the connection. 17 | /// 18 | public string? DocumentId => JSRef!.Get("documentId"); 19 | /// 20 | /// string. The lifecycle state the document that opened the connection was in when the port was created. Note that the lifecycle state of the document may have changed since the port was created. 21 | /// 22 | public string? DocumentLifecycle => JSRef!.Get("documentLifecycle"); 23 | /// 24 | /// integer. The frame that opened the connection. Zero for top-level frames, positive for child frames. This is only set when tab is set. 25 | /// 26 | public int? FrameId => JSRef!.Get("frameId"); 27 | /// 28 | /// string. The origin of the page or frame that opened the connection. It can differ from the url property (e.g., about:blank) or be opaque (e.g., sandboxed iframes). This is useful for identifying if the origin can be trusted if it isn't apparent from the URL. 29 | /// 30 | public string? Origin => JSRef!.Get("origin"); 31 | /// 32 | /// tabs.Tab. The tabs.Tab which opened the connection. This property is only present when the connection was opened from a tab (including content scripts). 33 | /// 34 | public Tab? Tab => JSRef!.Get("tab"); 35 | /// 36 | /// string. The TLS channel ID of the page or frame that opened the connection, if requested by the extension and available. 37 | /// 38 | public string? TlsChannelId => JSRef!.Get("tlsChannelId"); 39 | /// 40 | /// string. The URL of the page or frame hosting the script that sent the message.
41 | /// If the sender is a script running in an extension page (such as a background page, an options page, or a browser action or page action popup), the URL is in the form "moz-extension://<extension-internal-id>/path/to/page.html". If the sender is a background script and you haven't included a background page, it is "moz-extension://<extension-internal-id>/_generated_background_page.html".
42 | /// If the sender is a script running in a web page (including content and normal page scripts), then url is the web page URL. If the script is running in an iframe, url is the iframe's URL. 43 | ///
44 | public string? Url => JSRef!.Get("url"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Services/ContentBridgeService.cs: -------------------------------------------------------------------------------- 1 | using SpawnDev.BlazorJS.JSObjects; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension.Services 4 | { 5 | /// 6 | /// ContentBridgeService lets the Blazor App running in an Extension Content mode, which has an isolated Javascript scope, 7 | /// access the web page's Javascript scope via proxies
8 | ///
9 | public class ContentBridgeService : IAsyncBackgroundService 10 | { 11 | public Task Ready => _Ready ??= InitAsync(); 12 | private Task? _Ready = null; 13 | string MessageKey = Guid.NewGuid().ToString(); 14 | string instanceId = ""; 15 | string remoteInstanceId = ""; 16 | BrowserExtensionService BrowserExtensionService; 17 | /// 18 | /// ContentBridge Dispatcher 19 | /// 20 | public ExtensionContentBridge? SyncDispatcher { get; private set; } 21 | BlazorJSRuntime JS; 22 | public ContentBridgeService(BlazorJSRuntime js, BrowserExtensionService browserExtensionService) 23 | { 24 | JS = js; 25 | instanceId = $"{MessageKey}-a"; 26 | remoteInstanceId = $"{MessageKey}-b"; 27 | BrowserExtensionService = browserExtensionService; 28 | if (BrowserExtensionService.ExtensionMode == ExtensionMode.Content) 29 | { 30 | SyncDispatcher = new ExtensionContentBridge(new ExtensionContentBridgeOptions(instanceId, remoteInstanceId)); 31 | JS.Set("_syncDispatcher", SyncDispatcher); 32 | } 33 | } 34 | async Task InitAsync() 35 | { 36 | if (BrowserExtensionService.ExtensionMode == ExtensionMode.Content) 37 | { 38 | // This loads the other side of the content-bridge into the website 39 | await ContentSiteContextScriptLoader("_content/SpawnDev.BlazorJS.BrowserExtension/content-bridge.js"); 40 | await ContentSiteContextScriptLoader($"_content/SpawnDev.BlazorJS.BrowserExtension/content-bridge-loader.js?instanceId={remoteInstanceId}&remoteInstanceId={instanceId}"); 41 | } 42 | } 43 | async Task ContentSiteContextScriptLoader(string jsFile) 44 | { 45 | var fileUrl = BrowserExtensionService.GetURL(jsFile); 46 | var document = JS.Get("document"); 47 | using var scriptEl = document.CreateElement("script"); 48 | scriptEl.Type = "text/javascript"; 49 | scriptEl.Src = fileUrl; 50 | using var head = document.Head; 51 | if (head != null) 52 | { 53 | head.AppendChild(scriptEl); 54 | } 55 | else 56 | { 57 | using var body = document.Body; 58 | if (body != null) 59 | { 60 | body.AppendChild(scriptEl); 61 | } 62 | else 63 | { 64 | using var html = document.DocumentElement; 65 | html!.AppendChild(scriptEl); 66 | } 67 | } 68 | await scriptEl.OnLoadAsync(); 69 | scriptEl.Remove(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Windows/Window.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | using SpawnDev.BlazorJS.JSObjects; 3 | 4 | namespace SpawnDev.BlazorJS.BrowserExtension 5 | { 6 | /// 7 | /// Information about a browser window.
8 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/Window 9 | ///
10 | //public partial class Windows; 11 | public class Window : JSObject 12 | { 13 | /// 14 | /// Deserialization constructor 15 | /// 16 | public Window(IJSInProcessObjectReference _ref) : base(_ref) { } 17 | /// 18 | /// boolean. Whether the window is set to be always on top. 19 | /// 20 | public bool AlwaysOnTop => JSRef!.Get("alwaysOnTop"); 21 | /// 22 | /// boolean. Whether the window is currently the focused window. 23 | /// 24 | public bool Focused => JSRef!.Get("focused"); 25 | /// 26 | /// integer. The height of the window, including the frame, in pixels. 27 | /// 28 | public int? Height => JSRef!.Get("height"); 29 | /// 30 | /// integer. The ID of the window. Window IDs are unique within a browser session. 31 | /// 32 | public int? Id => JSRef!.Get("id"); 33 | /// 34 | /// boolean. Whether the window is incognito (private). 35 | /// 36 | public bool Incognito => JSRef!.Get("incognito"); 37 | /// 38 | /// integer. The offset of the window from the left edge of the screen in pixels. 39 | /// 40 | public int? Left => JSRef!.Get("left"); 41 | /// 42 | /// string. The session ID used to uniquely identify a Window obtained from the sessions API. 43 | /// 44 | public string? SessionId => JSRef!.Get("sessionId"); 45 | /// 46 | /// A windows.WindowState value representing the state of this browser window — maximized, minimized, etc. 47 | /// 48 | public EnumString? State => JSRef!.Get?>("state"); 49 | /// 50 | /// Array of tabs.Tab objects representing the current tabs in the window. 51 | /// 52 | public Array? Tabs => JSRef!.Get?>("tabs"); 53 | /// 54 | /// The title of the browser window. Requires "tabs" permission or host permissions for the active tab's URL. Read only. 55 | /// 56 | public string? Title => JSRef!.Get("title"); 57 | /// 58 | /// integer. The offset of the window from the top edge of the screen in pixels. 59 | /// 60 | public int? Top => JSRef!.Get("top"); 61 | /// 62 | /// A windows.WindowType value representing the type of browser window this is — normal browser window, popup, etc. 63 | /// 64 | public EnumString? Type => JSRef!.Get?>("type"); 65 | /// 66 | /// integer. The width of the window, including the frame, in pixels. 67 | /// 68 | public int? Width => JSRef!.Get("width"); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/RequestDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest#type-RequestDetails 6 | /// 7 | public class RequestDetails 8 | { 9 | /// 10 | /// The unique identifier for the frame's document, if this request is for a frame. 11 | /// 12 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 13 | public string? DocumentId { get; set; } 14 | /// 15 | /// The lifecycle of the frame's document, if this request is for a frame. 16 | /// 17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 18 | public EnumString? DocumentLifecycle { get; set; } 19 | /// 20 | /// The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (type is main_frame or sub_frame), frameId indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab. 21 | /// 22 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 23 | public int FrameId { get; set; } 24 | /// 25 | /// The type of the frame, if this request is for a frame. 26 | /// 27 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 28 | public EnumString? FrameType { get; set; } 29 | /// 30 | /// The origin where the request was initiated. This does not change through redirects. If this is an opaque origin, the string 'null' will be used. 31 | /// 32 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 33 | public string? Initiator{ get; set; } 34 | /// 35 | /// Standard HTTP method. 36 | /// 37 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 38 | public string? Method { get; set; } 39 | /// 40 | /// ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. 41 | /// 42 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 43 | public int? ParentDocumentId { get; set; } 44 | /// 45 | /// The ID of the request. Request IDs are unique within a browser session. 46 | /// 47 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 48 | public string? RequestId { get; set; } 49 | /// 50 | /// The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. 51 | /// 52 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 53 | public int? TabId { get; set; } 54 | /// 55 | /// The resource type of the request. 56 | /// 57 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 58 | public EnumString? Type { get; set; } 59 | /// 60 | /// The URL of the request. 61 | /// 62 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 63 | public string? Url { get; set; } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Storage/StorageArea.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// StorageArea is an object representing a storage area.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/StorageArea 8 | ///
9 | public class StorageArea : JSObject 10 | { 11 | /// 12 | /// Deserialization constructor 13 | /// 14 | public StorageArea(IJSInProcessObjectReference _ref) : base(_ref) { } 15 | 16 | #region Methods 17 | /// 18 | /// Gets the amount of storage space (in bytes) used one or more items being stored in the storage area. 19 | /// 20 | /// 21 | /// 22 | public Task GetBytesInUse(params string[] keys) => JSRef!.CallAsync("getBytesInUse", keys); 23 | /// 24 | /// Removes one or more items from the storage area. 25 | /// 26 | /// A string, or array of strings, representing the key(s) of the item(s) to be removed. 27 | /// A Promise that will be fulfilled with no arguments if the operation succeeded. If the operation failed, the promise will be rejected with an error message. 28 | public Task Remove(params string[] keys) => JSRef!.CallVoidAsync("remove", keys); 29 | /// 30 | /// Removes all items from the storage area. 31 | /// 32 | /// 33 | public Task Clear() => JSRef!.CallVoidAsync("clear"); 34 | /// 35 | /// Returns a list of keys in the storage area. 36 | /// 37 | /// 38 | public async Task> GetKeys() 39 | { 40 | using var all = await JSRef!.CallAsync("get"); 41 | var keys = JS.Call>("Object.keys", all); 42 | return keys; 43 | } 44 | /// 45 | /// Sets the access level for the storage area. 46 | /// 47 | /// 48 | /// 49 | public Task SetAccessLevel(string accessLevel) => JSRef!.CallVoidAsync("setAccessLevel", accessLevel); 50 | 51 | public async Task Get(string key) 52 | { 53 | using var tmp = await JSRef!.CallAsync("get", key); 54 | if (tmp == null || tmp.JSRef!.IsUndefined(key)) return default(T); 55 | return tmp.JSRef!.Get(key); 56 | } 57 | public async Task Get(string key, T defaultValue) 58 | { 59 | using var tmp = await JSRef!.CallAsync("get", key); 60 | if (tmp == null || tmp.JSRef!.IsUndefined(key)) return defaultValue; 61 | return tmp.JSRef!.Get(key); 62 | } 63 | public async Task Exists(string key) 64 | { 65 | using var tmp = await JSRef!.CallAsync("get", key); 66 | return tmp != null && !tmp.JSRef!.IsUndefined(key); 67 | } 68 | 69 | public Task Set(string key, object value) => JSRef!.CallVoidAsync("set", new Dictionary { { key, value } }); 70 | #endregion 71 | 72 | #region Events 73 | /// 74 | /// The function called when this event occurs. The function is passed these arguments:
75 | /// StorageChanges changes - Object describing the change. This object contains properties for all the keys in the storage area included in the storageArea.set call, even if key values are unchanged. The name of each property is the name of each key. The value of each key is a storage.StorageChange object describing the change to that item.
76 | /// Changes - StorageChanges
77 | /// AreaName - string 78 | ///
79 | public ActionEvent OnChanged { get => JSRef!.Get>("onChanged"); set { } } 80 | #endregion 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Runtime/Port.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | using SpawnDev.BlazorJS.IJSInProcessObjectReferenceAnyKey; 3 | using SpawnDev.BlazorJS.JSObjects; 4 | 5 | namespace SpawnDev.BlazorJS.BrowserExtension 6 | { 7 | /// 8 | /// A Port object represents one end of a connection between two specific contexts, which can be used to exchange messages.
9 | /// One side initiates the connection, using a connect() API. This returns a Port object. The other side listens for connection attempts using an onConnect listener. This is passed a corresponding Port object.
10 | /// Once both sides have Port objects, they can exchange messages using Port.postMessage() and Port.onMessage. When they are finished, either end can disconnect using Port.disconnect(), which will generate a Port.onDisconnect event at the other end, enabling the other end to do any cleanup required.
11 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port 12 | ///
13 | public class Port : JSObject 14 | { 15 | /// 16 | /// Deserialization constructor 17 | /// 18 | public Port(IJSInProcessObjectReference _ref) : base(_ref) { } 19 | /// 20 | /// string. The port's name, defined in the runtime.connect() or tabs.connect() call that created it. If this port is connected to a native application, its name is the name of the native application. 21 | /// 22 | public string? Name => JSRef!.Get("name"); 23 | /// 24 | /// runtime.MessageSender. Contains information about the sender of the message. This property will only be present on ports passed to onConnect/onConnectExternal listeners. 25 | /// 26 | public MessageSender? Sender => JSRef!.Get("sender"); 27 | /// 28 | /// function. Send a message to the other end. This takes one argument, which is a serializable value (see Data cloning algorithm) representing the message to send. It will be delivered to any script listening to the port's onMessage event, or to the native application if this port is connected to a native application. 29 | /// 30 | /// 31 | public void PostMessage(object message) => JSRef!.CallVoid("postMessage", message); 32 | /// 33 | /// object. If the port was disconnected due to an error, this will be set to an object with a string property message, giving you more information about the error. See onDisconnect. 34 | /// 35 | public Error? Error => JSRef!.Get("error"); 36 | /// 37 | /// function. Disconnects a port. Either end can call this when they have finished with the port. It will cause onDisconnect to be fired at the other end. This is useful if the other end is maintaining some state relating to this port, which can be cleaned up on disconnect. If this port is connected to a native application, this function will close the native application. 38 | /// 39 | public void Disconnect() => JSRef!.CallVoid("disconnect"); 40 | /// 41 | /// object. This contains the addListener() and removeListener() functions common to all events for extensions built using WebExtension APIs. Listener functions will be called when the other end has called Port.disconnect(). This event will only be fired once for each port. The listener function will be passed the Port object. If the port was disconnected due to an error, then the Port argument will contain an error property giving more information about the error: 42 | /// 43 | public ActionEvent OnDisconnect { get => JSRef!.Get>("onDisconnect"); set { } } 44 | /// 45 | /// object. This contains the addListener() and removeListener() functions common to all events for extensions built using WebExtension APIs. Listener functions will be called when the other end has sent this port a message. The listener will be passed the value that the other end sent. 46 | /// 47 | public ActionEvent OnMessage { get => JSRef!.Get>("onMessage"); set { } } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/ContextMenus/ContextMenus.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// https://developer.chrome.com/docs/extensions/reference/api/contextMenus
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Context_menu_items
8 | ///
9 | public class ContextMenus : JSObject 10 | { 11 | /// 12 | /// Deserialization constructor 13 | /// 14 | public ContextMenus(IJSInProcessObjectReference _ref) : base(_ref) { } 15 | /// 16 | /// Creates a new context menu item. If an error occurs during creation, it may not be detected until the creation callback fires; details will be in runtime.lastError. 17 | /// 18 | /// 19 | /// The ID of the newly created item. (number | string) 20 | public JSObject Create(MenuItemProperties createProperties) => JSRef!.Call("create", createProperties); 21 | /// 22 | /// Creates a new context menu item. If an error occurs during creation, it may not be detected until the creation callback fires; details will be in runtime.lastError. 23 | /// 24 | /// 25 | /// 26 | /// The ID of the newly created item. (number | string) 27 | public JSObject Create(MenuItemProperties createProperties, ActionCallback callback) => JSRef!.Call("create", createProperties, callback); 28 | /// 29 | /// Removes a context menu item. 30 | /// 31 | /// 32 | /// 33 | public void Remove(string menuItemId, ActionCallback callback) => JSRef!.CallVoid("remove", menuItemId, callback); 34 | /// 35 | /// Removes a context menu item. 36 | /// 37 | /// 38 | public void Remove(int menuItemId) => JSRef!.CallVoid("remove", menuItemId); 39 | /// 40 | /// Removes a context menu item. 41 | /// 42 | /// 43 | public void Remove(string menuItemId) => JSRef!.CallVoid("remove", menuItemId); 44 | /// 45 | /// Removes a context menu item. 46 | /// 47 | /// 48 | /// 49 | public void Remove(int menuItemId, ActionCallback callback) => JSRef!.CallVoid("remove", menuItemId, callback); 50 | /// 51 | /// Removes all context menu items added by this extension. 52 | /// 53 | /// 54 | public void RemoveAll(ActionCallback callback) => JSRef!.CallVoid("removeAll", callback); 55 | /// 56 | /// Removes all context menu items added by this extension. 57 | /// 58 | public void RemoveAll() => JSRef!.CallVoid("removeAll"); 59 | /// 60 | /// Updates a previously created context menu item. 61 | /// 62 | /// 63 | /// 64 | /// 65 | public void Update(string menuItemId, MenuItemProperties updateProperties, ActionCallback callback) => JSRef!.CallVoid("update", menuItemId, updateProperties, callback); 66 | /// 67 | /// Updates a previously created context menu item. 68 | /// 69 | /// 70 | /// 71 | public void Update(string menuItemId, MenuItemProperties updateProperties) => JSRef!.CallVoid("update", menuItemId, updateProperties); 72 | /// 73 | /// Updates a previously created context menu item. 74 | /// 75 | /// 76 | /// 77 | /// 78 | public void Update(int menuItemId, MenuItemProperties updateProperties, ActionCallback callback) => JSRef!.CallVoid("update", menuItemId, updateProperties, callback); 79 | /// 80 | /// Updates a previously created context menu item. 81 | /// 82 | /// 83 | /// 84 | public void Update(int menuItemId, MenuItemProperties updateProperties) => JSRef!.CallVoid("update", menuItemId, updateProperties); 85 | /// 86 | /// Fired when a context menu item is clicked. 87 | /// 88 | public ActionEvent OnClicked { get => JSRef!.Get>("onClicked"); set { } } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Tabs/Tabs.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Interact with the browser's tab system.
7 | /// Note: The Tabs API can be used by the service worker and extension pages, but not content scripts.
8 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs 9 | ///
10 | public class Tabs : JSObject 11 | { 12 | /// 13 | /// A special ID value given to tabs that are not browser tabs (for example, tabs in devtools windows). 14 | /// 15 | public static int TAB_ID_NONE { get; } = -1; 16 | /// 17 | /// Deserialization constructor 18 | /// 19 | public Tabs(IJSInProcessObjectReference _ref) : base(_ref) { } 20 | #region Methods 21 | /// 22 | /// Creates a new tab. 23 | /// 24 | /// 25 | /// 26 | public Task Create(CreateTabProperties createProperties) => JSRef!.CallAsync("create", createProperties); 27 | 28 | /// 29 | /// Retrieves details about the specified tab. 30 | /// 31 | /// 32 | /// 33 | public Task Get(int tabId) => JSRef!.CallAsync("get", tabId); 34 | /// 35 | /// Gets all tabs that have the specified properties, or all tabs if no properties are specified. 36 | /// 37 | /// 38 | /// 39 | public Task Query(TabQueryInfo queryInfo) => JSRef!.CallAsync("query", queryInfo); 40 | /// 41 | /// Sends a single message to the content script(s) in the specified tab. 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | public Task SendMessage(int tabId, object message) => JSRef!.CallAsync("sendMessage", tabId, message); 48 | /// 49 | /// Sends a single message to the content script(s) in the specified tab. 50 | /// 51 | /// 52 | /// 53 | /// 54 | public Task SendMessage(int tabId, object message) => JSRef!.CallVoidAsync("sendMessage", tabId, message); 55 | /// 56 | /// Sends a single message to the content script(s) in the specified tab. 57 | /// 58 | /// 59 | /// 60 | /// 61 | /// 62 | /// 63 | public Task SendMessage(int tabId, object message, TabMessageOptions options) => JSRef!.CallVoidAsync("sendMessage", tabId, message, options); 64 | /// 65 | /// Sends a single message to the content script(s) in the specified tab. 66 | /// 67 | /// 68 | /// 69 | /// 70 | /// 71 | public Task SendMessage(int tabId, object message, TabMessageOptions options) => JSRef!.CallAsync("sendMessage", tabId, message, options); 72 | /// 73 | /// Reload a tab. 74 | /// 75 | /// 76 | public Task Reload() => JSRef!.CallVoidAsync("reload"); 77 | /// 78 | /// Reload a tab. 79 | /// 80 | /// 81 | /// 82 | public Task Reload(int tabId) => JSRef!.CallVoidAsync("reload", tabId); 83 | /// 84 | /// Reload a tab. 85 | /// 86 | /// 87 | /// 88 | /// 89 | public Task Reload(int tabId, ReloadProperties reloadProperties) => JSRef!.CallVoidAsync("reload", tabId, reloadProperties); 90 | #endregion 91 | #region Events 92 | // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs#events 93 | /// 94 | /// Fires when the active tab in a window changes. Note that the tab's URL may not be set at the time this event fired. 95 | /// 96 | public ActionEvent OnActivated { get => JSRef!.Get>("onActivated"); set { } } 97 | /// 98 | /// Fired when a tab is updated. 99 | /// 100 | public ActionEvent OnUpdated { get => JSRef!.Get>("onUpdated"); set { } } 101 | 102 | #endregion 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/ContentBridge/ExtensionContentBridge.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | using SpawnDev.BlazorJS.JSObjects; 3 | 4 | namespace SpawnDev.BlazorJS.BrowserExtension 5 | { 6 | /// 7 | /// Enables accessing the website Javascript scope from the extension side in a content script or page 8 | /// 9 | public class ExtensionContentBridge : JSObject 10 | { 11 | /// 12 | /// Creates a new instance of ExtensionContentBridge 13 | /// 14 | /// 15 | public ExtensionContentBridge(ExtensionContentBridgeOptions options) : base(JS.New(nameof(ExtensionContentBridge), options)) { } 16 | /// 17 | /// Deserialization constructor 18 | /// 19 | /// 20 | public ExtensionContentBridge(IJSInProcessObjectReference _ref) : base(_ref) { } 21 | /// 22 | /// Enables sharing resources from this side with the other side
23 | /// WARNING: This should not be enabled on the extension side
24 | /// setter is disabled here to discourage setting true 25 | ///
26 | public bool Serve { get => JSRef!.Get("serve"); set { } } 27 | /// 28 | /// Gets a proxied instance of window 29 | /// 30 | /// 31 | public Window GetWindow() => GetGlobal("window"); 32 | /// 33 | /// Get a global property value of type T from the remote global scope 34 | /// 35 | /// 36 | /// 37 | /// 38 | public T GetGlobal(string identifier) => JSRef!.Call("getGlobal", identifier); 39 | /// 40 | /// Call a method on the remote scope with a return value of type T 41 | /// 42 | /// 43 | /// 44 | /// 45 | public T CallGlobal(string identifier) => JSRef!.Call("callGlobal", identifier); 46 | /// 47 | /// Call a method on the remote scope with no return value 48 | /// 49 | /// 50 | public void CallGlobalVoid(string identifier) => JSRef!.CallVoid("callGlobal", identifier); 51 | /// 52 | /// Call an async method on the remote scope with a return value of type T 53 | /// 54 | /// 55 | /// 56 | /// 57 | public Task CallGlobalAsync(string identifier) => JSRef!.CallAsync("callGlobal", identifier); 58 | /// 59 | /// Call an async method on the remote scope with no return value 60 | /// 61 | /// 62 | /// 63 | public Task CallGlobalVoidAsync(string identifier) => JSRef!.CallVoidAsync("callGlobal", identifier); 64 | /// 65 | /// Set a value on the remote global scope 66 | /// 67 | /// 68 | /// 69 | public void SetGlobal(string identifier, object value) => JSRef!.CallVoid("setGlobal", identifier, value); 70 | /// 71 | /// Delete a property from the remote glboal scope 72 | /// 73 | /// 74 | /// 75 | public bool DeleteGlobal(string identifier) => JSRef!.Call("deleteGlobal", identifier); 76 | /// 77 | /// Releases all resources for the given proxied object 78 | /// 79 | /// 80 | /// 81 | public bool Release(JSObject obj) => JSRef!.Call("release", obj); 82 | /// 83 | /// Creates a selector string for the given element usable with document.querySelector()
84 | /// The selector string may not be valid after any DOM changes but is useful as a reference to an element that can be passed across content scopes 85 | ///
86 | /// 87 | /// 88 | public string MakeQuerySelector(Node node) => JSRef!.Call("makeQuerySelector", node); 89 | /// 90 | /// Returns the same document element from the website side which allows accessing any owned Javascript variables 91 | /// 92 | /// 93 | /// 94 | /// 95 | public T? GetDocumentElementRemote(T node1) where T : Element 96 | { 97 | using var node = node1.JSRefCopy(); 98 | if (node == null) return null; 99 | var selector = MakeQuerySelector(node); 100 | using var d = GetGlobal("document"); 101 | var el = d.QuerySelector(selector); 102 | d.WrappedObjectRelease(); 103 | return el; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/WebRequest/WebRequestEvent.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | public class WebRequestEvent : JSObject 6 | { 7 | /// 8 | /// Contains Callback references that will be disposed when an equal number of add and remove listener calls are made 9 | /// 10 | protected static CallbackRef CallbackRef = new(); 11 | /// 12 | /// Deserialization constructor 13 | /// 14 | /// 15 | public WebRequestEvent(IJSInProcessObjectReference _ref) : base(_ref) { } 16 | /// 17 | /// Adds a listener to this event. 18 | /// 19 | public void AddListener(Callback callback, RequestFilter requestFilter) => JSRef!.CallVoid("addListener", callback, requestFilter); 20 | /// 21 | /// Adds a listener to this event. 22 | /// 23 | public void AddListener(Callback callback, RequestFilter requestFilter, string[] extraInfoSpec) => JSRef!.CallVoid("addListener", callback, requestFilter, extraInfoSpec); 24 | /// 25 | /// Adds a listener to this event. 26 | /// 27 | public void AddListener(Action callback, RequestFilter requestFilter) => JSRef!.CallVoid("addListener", CallbackRef.RefAdd(callback), requestFilter); 28 | /// 29 | /// Adds a listener to this event. 30 | /// 31 | public void AddListener(Action callback, RequestFilter requestFilter, string[] extraInfoSpec) => JSRef!.CallVoid("addListener", CallbackRef.RefAdd(callback), requestFilter, extraInfoSpec); 32 | /// 33 | /// Adds a listener to this event. 34 | /// 35 | public void AddListener(Func callback, RequestFilter requestFilter) => JSRef!.CallVoid("addListener", CallbackRef.RefAdd(callback), requestFilter); 36 | /// 37 | /// Adds a listener to this event. 38 | /// 39 | public void AddListener(Func callback, RequestFilter requestFilter, string[] extraInfoSpec) => JSRef!.CallVoid("addListener", CallbackRef.RefAdd(callback), requestFilter, extraInfoSpec); 40 | /// 41 | /// Adds a listener to this event. 42 | /// 43 | public void AddListener(Func> callback, RequestFilter requestFilter) => JSRef!.CallVoid("addListener", CallbackRef.RefAdd(callback), requestFilter); 44 | /// 45 | /// Adds a listener to this event. 46 | /// 47 | public void AddListener(Func> callback, RequestFilter requestFilter, string[] extraInfoSpec) => JSRef!.CallVoid("addListener", CallbackRef.RefAdd(callback), requestFilter, extraInfoSpec); 48 | /// 49 | /// Adds a listener to this event. 50 | /// 51 | public void AddListener(Func callback, RequestFilter requestFilter) => JSRef!.CallVoid("addListener", CallbackRef.RefAdd(callback), requestFilter); 52 | /// 53 | /// Adds a listener to this event. 54 | /// 55 | public void AddListener(Func callback, RequestFilter requestFilter, string[] extraInfoSpec) => JSRef!.CallVoid("addListener", CallbackRef.RefAdd(callback), requestFilter, extraInfoSpec); 56 | /// 57 | /// Stop listening to this event. The listener argument is the listener to remove. 58 | /// 59 | public void RemoveListener(Callback callback) => JSRef!.CallVoid("removeListener", callback); 60 | /// 61 | /// Stop listening to this event. The listener argument is the listener to remove. 62 | /// 63 | public void RemoveListener(Func> listener) 64 | { 65 | var callback = CallbackRef.RefGet(listener, false); 66 | if (callback == null) return; 67 | RemoveListener(callback); 68 | CallbackRef.RefDel(listener); 69 | } 70 | /// 71 | /// Stop listening to this event. The listener argument is the listener to remove. 72 | /// 73 | public void RemoveListener(Func listener) 74 | { 75 | var callback = CallbackRef.RefGet(listener, false); 76 | if (callback == null) return; 77 | RemoveListener(callback); 78 | CallbackRef.RefDel(listener); 79 | } 80 | /// 81 | /// Stop listening to this event. The listener argument is the listener to remove. 82 | /// 83 | public void RemoveListener(Func listener) 84 | { 85 | var callback = CallbackRef.RefGet(listener, false); 86 | if (callback == null) return; 87 | RemoveListener(callback); 88 | CallbackRef.RefDel(listener); 89 | } 90 | /// 91 | /// Stop listening to this event. The listener argument is the listener to remove. 92 | /// 93 | public void RemoveListener(Action listener) 94 | { 95 | var callback = CallbackRef.RefGet(listener, false); 96 | if (callback == null) return; 97 | RemoveListener(callback); 98 | CallbackRef.RefDel(listener); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Tabs/TabQueryInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// The query() function gets the tabs whose properties match the properties included here.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query#queryinfo 8 | ///
9 | public class TabQueryInfo 10 | { 11 | /// 12 | /// boolean. Whether the tabs are active in their windows. 13 | /// 14 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 15 | public bool? Active { get; set; } 16 | /// 17 | /// boolean. Indicates whether the tabs are drawing attention. 18 | /// 19 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 20 | public bool? Attention { get; set; } 21 | /// 22 | /// boolean. Whether the tabs are audible. 23 | /// 24 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 25 | public bool? Audible { get; set; } 26 | /// 27 | /// boolean. Whether the tab can be discarded by the browser. The default value is true. When set to false, the browser cannot automatically discard the tab. However, the tab can be discarded by tabs.discard. 28 | /// 29 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 30 | public bool? AutoDiscardable { get; set; } 31 | /// 32 | /// string or array of string. Use this to return tabs whose tab.cookieStoreId matches any of the cookieStoreId strings. This option is only available if the add-on has the "cookies" permission. See Work with contextual identities for more information. 33 | /// 34 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 35 | public Union? CookieStoreId { get; set; } 36 | /// 37 | /// boolean. Whether the tabs are in the current window. 38 | /// 39 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 40 | public bool? CurrentWindow { get; set; } 41 | /// 42 | /// boolean. Whether the tabs are discarded. A discarded tab is one whose content has been unloaded from memory, but is still visible in the tab strip. Its content gets reloaded the next time it's activated. 43 | /// 44 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 45 | public bool? Discarded { get; set; } 46 | /// 47 | /// boolean. Whether the tabs are hidden. 48 | /// 49 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 50 | public bool? Hidden { get; set; } 51 | /// 52 | /// boolean. Whether the tabs are highlighted. 53 | /// 54 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 55 | public bool? Highlighted { get; set; } 56 | /// 57 | /// integer. The position of the tabs within their windows. 58 | /// 59 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 60 | public int? Index { get; set; } 61 | /// 62 | /// boolean. Whether the tabs are muted. 63 | /// 64 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 65 | public bool? Muted { get; set; } 66 | /// 67 | /// boolean. Whether the tabs are in the last focused window. 68 | /// 69 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 70 | public bool? LastFocusedWindow { get; set; } 71 | /// 72 | /// boolean. Whether the tabs are pinned. 73 | /// 74 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 75 | public bool? Pinned { get; set; } 76 | /// 77 | /// tabs.TabStatus. Whether the tabs have completed loading.
78 | /// Values of this type are strings. Possible values are: "loading" and "complete". 79 | ///
80 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 81 | public string? TabStatus { get; set; } 82 | /// 83 | /// string. Match page titles against a pattern. Requires the "tabs" permission or host permissions for the tab to match. 84 | /// 85 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 86 | public string? Title { get; set; } 87 | /// 88 | /// string or array of string. Match tabs against one or more match patterns. Note that fragment identifiers are not matched. Requires the "tabs" permission or host permissions for the tab to match. 89 | /// 90 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 91 | public Union? Url { get; set; } 92 | /// 93 | /// integer. The id of the parent window, or windows.WINDOW_ID_CURRENT for the current window. 94 | /// 95 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 96 | public int? WindowId { get; set; } 97 | /// 98 | /// tabs.WindowType. The type of window the tabs are in.
99 | /// Values of this type are strings. Possible values are:
100 | /// - "normal"
101 | /// - "popup"
102 | /// - "panel"
103 | /// - "devtools" 104 | ///
105 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 106 | public string? WindowType { get; set; } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/ContextMenus/MenuItemProperties.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Properties of the new context menu item.
7 | /// Properties vary between Firefox and Chrome
8 | /// https://developer.chrome.com/docs/extensions/reference/api/contextMenus#type-CreateProperties
9 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/menus/create#createproperties 10 | ///
11 | public class MenuItemProperties 12 | { 13 | /// 14 | /// string. String describing an action that should be taken when the user clicks the item. The recognized values are:
15 | /// "_execute_browser_action": simulate a click on the extension's browser action, opening its popup if it has one (Manifest V2 only)
16 | /// "_execute_action": simulate a click on the extension's action, opening its popup if it has one (Manifest V3 only)
17 | /// "_execute_page_action": simulate a click on the extension's page action, opening its popup if it has one
18 | /// "_execute_sidebar_action": open the extension's sidebar
19 | /// When one of the recognized values is specified, clicking the item does not trigger the menus.onClicked event; instead, the default action triggers, such as opening a pop-up.
20 | /// Otherwise, clicking the item triggers menus.onClicked and the event can be used to implement fallback behavior. 21 | ///
22 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 23 | public string? Command { get; set; } 24 | /// 25 | /// object. One or more custom icons to display next to the item. Custom icons can only be set for items appearing in submenus. This property is an object with one property for each supplied icon: the property's name should include the icon's size in pixels, and path is relative to the icon from the extension's root directory. The browser tries to choose a 16x16 pixel icon for a normal display or a 32x32 pixel icon for a high-density display. To avoid any scaling, you can specify icons like this: 26 | /// 27 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 28 | public Dictionary? Icons { get; set; } 29 | 30 | 31 | /// 32 | /// The initial state of a checkbox or radio button: true for selected, false for unselected. Only one radio button can be selected at a time in a given group. 33 | /// 34 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 35 | public bool? Checked { get; set; } 36 | /// 37 | /// List of contexts this menu item will appear in. Defaults to ['page']. 38 | /// 39 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 40 | public IEnumerable? Contexts { get; set; } 41 | /// 42 | /// Restricts the item to apply only to documents or frames whose URL matches one of the given patterns. For details on pattern formats, see Match Patterns. 43 | /// 44 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 45 | public IEnumerable? DocumentUrlPatterns { get; set; } 46 | /// 47 | /// Whether this context menu item is enabled or disabled. Defaults to true. 48 | /// 49 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 50 | public bool? Enabled { get; set; } 51 | /// 52 | /// The unique ID to assign to this item. Mandatory for event pages. Cannot be the same as another ID for this extension. 53 | /// 54 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 55 | public string? Id { get; set; } 56 | /// 57 | /// The ID of a parent menu item; this makes the item a child of a previously added item. 58 | /// 59 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 60 | public Union? ParentId { get; set; } 61 | /// 62 | /// Similar to documentUrlPatterns, filters based on the src attribute of img, audio, and video tags and the href attribute of a tags. 63 | /// 64 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 65 | public IEnumerable? TargetUrlPatterns { get; set; } 66 | /// 67 | /// The text to display in the item; this is required unless type is separator. When the context is selection, use %s within the string to show the selected text. For example, if this parameter's value is "Translate '%s' to Pig Latin" and the user selects the word "cool", the context menu item for the selection is "Translate 'cool' to Pig Latin". 68 | /// 69 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 70 | public string? Title { get; set; } 71 | /// 72 | /// The type of menu item. Defaults to normal. 73 | /// 74 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 75 | public string? ItemType { get; set; } 76 | /// 77 | /// Whether the item is visible in the menu. 78 | /// 79 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 80 | public bool? Visible { get; set; } 81 | /// 82 | /// A function that is called back when the menu item is clicked. This is not available inside of a service worker; instead, you should register a listener for contextMenus.onClicked. 83 | /// 84 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 85 | public ActionCallback? OnClick { get; set; } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/ContextMenus/OnClickData.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// Information sent when a context menu item is clicked.
7 | /// https://developer.chrome.com/docs/extensions/reference/api/contextMenus#type-OnClickData
8 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/menus/OnClickData 9 | ///
10 | public class OnClickData : JSObject 11 | { 12 | /// 13 | /// Deserialization constructor 14 | /// 15 | public OnClickData(IJSInProcessObjectReference _ref) : base(_ref) { } 16 | /// 17 | /// integer. Which mouse button was pressed. The values are the same as for MouseEvent.button.
18 | /// (Firefox) 19 | ///
20 | public int? Button => JSRef!.Get("button"); 21 | /// 22 | /// string. The ID of the bookmark where the context menu was clicked.
23 | /// (Firefox 24 | ///
25 | public string? BookmarkId => JSRef!.Get("bookmarkId"); 26 | /// 27 | /// A flag indicating the state of a checkbox or radio item after it is clicked. 28 | /// 29 | public bool? Checked => JSRef!.Get("checked"); 30 | /// 31 | /// A flag indicating whether the element is editable (text input, textarea, etc.). 32 | /// 33 | public bool? Editable => JSRef!.Get("editable"); 34 | /// 35 | /// integer. The ID of the frame in which the item was clicked. The frame ID can be used in other APIs that accept frame IDs, such as tabs.sendMessage(). If the item was clicked in the top level document, frameId is zero. If the item was clicked outside the page entirely (for example, in the tools_menu or tab context), then frameId is undefined. 36 | /// 37 | public int? FrameId => JSRef!.Get("frameId"); 38 | /// 39 | /// string. The URL of the frame of the element where the context menu was clicked, if it was in a frame. 40 | /// 41 | public string? FrameUrl => JSRef!.Get("frameUrl"); 42 | /// 43 | /// If the element is a link, the URL it points to. 44 | /// 45 | public string? LinkUrl => JSRef!.Get("linkUrl"); 46 | /// 47 | /// string. If the element is a link, the text for the link. If the link contains no text, the URL itself is given here.
48 | /// (Firefox) 49 | ///
50 | public string? LinkText => JSRef!.Get("linkText"); 51 | /// 52 | /// One of 'image', 'video', or 'audio' if the context menu was activated on one of these types of elements. 53 | /// 54 | public string? MediaType => JSRef!.Get("mediaType"); 55 | /// 56 | /// The ID of the menu item that was clicked.
57 | /// read as a string 58 | ///
59 | public string? MenuItemId => JSRef!.Get("menuItemId"); 60 | /// 61 | /// array of string. An array containing any modifier keys that were pressed when the item was clicked. Possible values are: "Alt", "Command", "Ctrl", "MacCtrl", and "Shift". On a Mac, if the user has the Control key pressed, then both "Ctrl" and "MacCtrl" are included.
62 | /// (Firefox) 63 | ///
64 | public string[]? Modifiers => JSRef!.Get("modifiers"); 65 | /// 66 | /// The ID of the menu item that was clicked.
67 | /// read as an int 68 | ///
69 | public int? MenuItemIdI => JSRef!.Get("menuItemId"); 70 | /// 71 | /// The URL of the page where the menu item was clicked. This property is not set if the click occured in a context where there is no current page, such as in a launcher context menu. 72 | /// 73 | public string? PageUrl => JSRef!.Get("pageUrl"); 74 | /// 75 | /// The parent ID, if any, for the item clicked.
76 | /// read as an string 77 | ///
78 | public string? ParentMenuId => JSRef!.Get("parentMenuId"); 79 | /// 80 | /// The parent ID, if any, for the item clicked.
81 | /// read as an int 82 | ///
83 | public int? ParentMenuIdI => JSRef!.Get("parentMenuId"); 84 | /// 85 | /// The text for the context selection, if any. 86 | /// 87 | public string? SelectionText => JSRef!.Get("selectionText"); 88 | /// 89 | /// Will be present for elements with a 'src' URL. 90 | /// 91 | public string? SrcUrl => JSRef!.Get("srcUrl"); 92 | /// 93 | /// integer. An identifier of the element, if any, over which the context menu was created. Use menus.getTargetElement() in the content script to locate the element. Note that this is not the id attribute of the page element.
94 | /// (Firefox) 95 | ///
96 | public int? TargetElementId => JSRef!.Get("targetElementId"); 97 | /// 98 | /// ViewType. The type of extension view.
99 | /// (Firefox) 100 | ///
101 | public string? ViewType => JSRef!.Get("viewType"); 102 | /// 103 | /// A flag indicating the state of a checkbox or radio item before it was clicked. 104 | /// 105 | public bool? WasChecked => JSRef!.Get("wasChecked"); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/build/SpawnDev.BlazorJS.BrowserExtension.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <_SpawnDevBrowserExtensionBuildContentDirectory>$(MSBuildThisFileDirectory)..\buildcontent 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | <_SpawnDevBrowserExtensionBuild_Project_Assets_Directory>$(ProjectDir)$(SpawnDevBrowserExtensionBuildAssetsPath) 21 | <_SpawnDevBrowserExtensionBuild_Project_Assets_ManifestJson_FilePath>$(_SpawnDevBrowserExtensionBuild_Project_Assets_Directory)\manifest.json 22 | <_SpawnDevBrowserExtensionBuild_Project_BuildOutput_Assets_Directory>$(TargetDir)$(SpawnDevBrowserExtensionBuildAssetsPath) 23 | <_SpawnDevBrowserExtensionBuild_Project_BuildOutput_SpawnDevBrowserExtensionBuild_Directory>$(TargetDir)$(SpawnDevBrowserExtensionBuildOutputPath) 24 | <_SpawnDevBrowserExtensionBuild_Project_BuildOutput_SpawnDevBrowserExtensionBuild_OriginalFramework_Directory>$(_SpawnDevBrowserExtensionBuild_Project_BuildOutput_SpawnDevBrowserExtensionBuild_Directory)\_framework 25 | 31 | <_SpawnDevBrowserExtensionBuild_Project_BuildOutput_StaticWebAssets_Manifest_FilePath>$(TargetDir)$(ProjectName).staticwebassets.runtime.json 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Action/Action.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace SpawnDev.BlazorJS.BrowserExtension 5 | { 6 | /// 7 | /// Read and modify attributes of and listen to clicks on the browser toolbar button defined with the action manifest key.
8 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action 9 | ///
10 | public class Action : JSObject 11 | { 12 | /// 13 | /// Deserialization constructor 14 | /// 15 | public Action(IJSInProcessObjectReference _ref) : base(_ref) { } 16 | /// 17 | /// Sets the browser action's title. This will be displayed in a tooltip. 18 | /// 19 | public void SetTitle(SetTitleDetails details) => JSRef!.CallVoid("setTitle", details); 20 | /// 21 | /// Gets the browser action's title. 22 | /// 23 | /// 24 | public Task GetTitle(GetTitleDetails details) => JSRef!.CallAsync("getTitle", details); 25 | /// 26 | /// Sets the browser action's icon. 27 | /// 28 | /// 29 | /// 30 | public Task SetIcon(SetIconDetails details) => JSRef!.CallVoidAsync("setIcon", details); 31 | /// 32 | /// Sets the HTML document to be opened as a popup when the user clicks on the browser action's icon. 33 | /// 34 | /// 35 | public void SetPopup(SetPopupDetails details) => JSRef!.CallVoid("setPopup", details); 36 | /// 37 | /// Gets the HTML document set as the browser action's popup. 38 | /// 39 | /// 40 | /// 41 | public Task GetPopup(GetPopupDetails details) => JSRef!.CallAsync("getPopup", details); 42 | /// 43 | /// Open the browser action's popup. 44 | /// 45 | /// 46 | /// 47 | public Task OpenPopup(OpenPopupDetails details) => JSRef!.CallVoidAsync("openPopup", details); 48 | /// 49 | /// Sets the browser action's badge text. The badge is displayed on top of the icon. 50 | /// 51 | /// 52 | /// 53 | public Task SetBadgeText(SetBadgeTextDetails details) => JSRef!.CallVoidAsync("setBadgeText", details); 54 | /// 55 | /// Gets the browser action's badge text. 56 | /// 57 | /// 58 | /// 59 | public Task GetBadgeText(GetBadgeTextDetails details) => JSRef!.CallAsync("getBadgeText", details); 60 | /// 61 | /// Sets the badge's background color. 62 | /// 63 | /// 64 | /// 65 | public Task SetBadgeBackgroundColor(SetBadgeBackgroundColorDetails details) => JSRef!.CallVoidAsync("setBadgeBackgroundColor", details); 66 | /// 67 | /// Gets the badge's background color. 68 | /// 69 | /// 70 | /// 71 | public Task GetBadgeBackgroundColor(GetBadgeBackgroundColorDetails details) => JSRef!.CallAsync("getBadgeBackgroundColor", details); 72 | /// 73 | /// Sets the badge's text color. 74 | /// 75 | /// 76 | /// 77 | public Task SetBadgeTextColor(SetBadgeTextColorDetails details) => JSRef!.CallVoidAsync("setBadgeTextColor", details); 78 | /// 79 | /// Gets the badge's text color. 80 | /// 81 | /// 82 | /// 83 | public Task GetBadgeTextColor(GetBadgeTextColorDetails details) => JSRef!.CallAsync("getBadgeTextColor", details); 84 | /// 85 | /// Gets the user-specified settings for the browser action. 86 | /// 87 | /// 88 | public Task GetUserSettings() => JSRef!.CallAsync("getUserSettings"); 89 | /// 90 | /// Enables the browser action for a tab. By default, browser actions are enabled for all tabs. 91 | /// 92 | public void Enable() => JSRef!.CallVoid("enable"); 93 | /// 94 | /// Enables the browser action for a tab. By default, browser actions are enabled for all tabs. 95 | /// 96 | /// 97 | public void Enable(int tabId) => JSRef!.CallVoid("enable", tabId); 98 | /// 99 | /// Disables the browser action for a tab, meaning that it cannot be clicked when that tab is active. 100 | /// 101 | public void Disable() => JSRef!.CallVoid("disable"); 102 | /// 103 | /// Disables the browser action for a tab, meaning that it cannot be clicked when that tab is active. 104 | /// 105 | /// 106 | public void Disable(int tabId) => JSRef!.CallVoid("disable", tabId); 107 | /// 108 | /// Checks whether the browser action is enabled or not. 109 | /// 110 | /// 111 | /// 112 | public Task IsEnabled(IsEnabledDetails details) => JSRef!.CallAsync("isEnabled", details); 113 | /// 114 | /// Fired when a browser action icon is clicked. This event will not fire if the browser action has a popup. 115 | /// 116 | public ActionEvent OnClicked { get => JSRef!.Get>("onClicked"); set { } } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/DeclarativeNetRequest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | using SpawnDev.BlazorJS.JSObjects; 3 | using System.Text.Json.Serialization; 4 | namespace SpawnDev.BlazorJS.BrowserExtension 5 | { 6 | /// 7 | /// This API enables extensions to specify conditions and actions that describe how network requests should be handled. These declarative rules enable the browser to evaluate and modify network requests without notifying extensions about individual network requests.
8 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest
9 | /// https://developer.chrome.com/docs/extensions/reference/api/declarativeNetRequest 10 | ///
11 | public partial class DeclarativeNetRequest : JSObject 12 | { 13 | /// 14 | /// Deserialization constructor 15 | /// 16 | public DeclarativeNetRequest(IJSInProcessObjectReference _ref) : base(_ref) { } 17 | /// 18 | /// Returns the number of static rules an extension can enable before the global static rule limit is reached. 19 | /// 20 | /// 21 | public Task GetAvailableStaticRuleCount() => JSRef!.CallAsync("getAvailableStaticRuleCount"); 22 | /// 23 | /// Returns the IDs of the disabled rules in a static ruleset. 24 | /// 25 | /// 26 | public Task GetDisabledRuleIds() => JSRef!.CallAsync("getDisabledRuleIds"); 27 | /// 28 | /// Returns the IDs of the disabled rules in a static ruleset. 29 | /// 30 | /// 31 | public Task GetDisabledRuleIds(GetDisabledRuleIdsOptions options) => JSRef!.CallAsync("getDisabledRuleIds", options); 32 | /// 33 | /// Returns the set of dynamic rules for the extension. 34 | /// 35 | public Task> GetDynamicRules() => JSRef!.CallAsync>("getDynamicRules"); 36 | /// 37 | /// Returns the set of dynamic rules for the extension. 38 | /// 39 | public Task> GetDynamicRules(GetRulesFilter filter) => JSRef!.CallAsync>("getDynamicRules", filter); 40 | /// 41 | /// Returns the IDs for the set of enabled static rulesets. 42 | /// 43 | /// 44 | public Task GetEnabledRulesets() => JSRef!.CallAsync("getEnabledRulesets"); 45 | /// 46 | /// Returns all the rules matched for the extension. 47 | /// 48 | /// 49 | public Task GetMatchedRules() => JSRef!.CallAsync("getMatchedRules"); 50 | /// 51 | /// Returns all the rules matched for the extension. 52 | /// 53 | /// 54 | /// 55 | public Task GetMatchedRules(MatchedRulesFilter filter) => JSRef!.CallAsync("getMatchedRules", filter); 56 | /// 57 | /// Returns the set of session rules for the extension. 58 | /// 59 | public Task> GetSessionRules() => JSRef!.CallAsync>("getSessionRules"); 60 | /// 61 | /// Returns the set of session rules for the extension. 62 | /// 63 | public Task> GetSessionRules(GetRulesFilter filter) => JSRef!.CallAsync>("getSessionRules", filter); 64 | /// 65 | /// Checks if a regular expression is supported as a declarativeNetRequest.RuleCondition.regexFilter rule condition. 66 | /// 67 | /// 68 | /// 69 | public Task IsRegexSupported(RegexOptions options) => JSRef!.CallAsync("isRegexSupported", options); 70 | /// 71 | /// Configures how the action count for tabs are handled. 72 | /// 73 | /// 74 | /// 75 | public Task SetExtensionActionOptions(ExtensionActionOptions options) => JSRef!.CallVoidAsync("setExtensionActionOptions", options); 76 | /// 77 | /// Checks if any of the extension's declarativeNetRequest rules would match a hypothetical request. 78 | /// 79 | /// 80 | public Task TestMatchOutcome(TestMatchRequestDetails options) => JSRef!.CallAsync("testMatchOutcome", options); 81 | /// 82 | /// Modifies the active set of dynamic rules for the extension. 83 | /// 84 | /// 85 | /// 86 | public Task UpdateDynamicRules(UpdateRuleOptions options) => JSRef!.CallVoidAsync("updateDynamicRules", options); 87 | /// 88 | /// Updates the set of active static rulesets for the extension. 89 | /// 90 | /// 91 | /// 92 | public Task UpdateEnabledRulesets(UpdateRulesetOptions options) => JSRef!.CallVoidAsync("updateEnabledRulesets", options); 93 | /// 94 | /// Modifies the set of session-scoped rules for the extension. 95 | /// 96 | /// 97 | /// 98 | public Task UpdateSessionRules(UpdateRuleOptions options) => JSRef!.CallVoidAsync("updateSessionRules", options); 99 | /// 100 | /// Modifies the enabled state of rules in a static ruleset. The number of rules that can be disabled in a ruleset is limited to the value of MAX_NUMBER_OF_DISABLED_STATIC_RULES.
101 | /// Rules can be enabled and disabled while the ruleset containing them is disabled. Any changes become effective when the ruleset is enabled. 102 | ///
103 | /// 104 | /// 105 | public Task UpdateStaticRules(UpdateStaticRulesOptions options) => JSRef!.CallVoidAsync("updateStaticRules", options); 106 | /// 107 | /// Fired when a rule is matched with a request. Only available for unpacked extensions with the "declarativeNetRequestFeedback" permission as this is intended to be used for debugging purposes only. 108 | /// 109 | public ActionEvent OnRuleMatchedDebug { get => JSRef!.Get>("onRuleMatchedDebug"); set { } } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/Tabs/Tab.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace SpawnDev.BlazorJS.BrowserExtension 4 | { 5 | /// 6 | /// The type tabs.Tab contains information about a tab. This provides access to information about what content is in the tab, how large the content is, what special states or restrictions are in effect, and so forth.
7 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/Tab 8 | ///
9 | public class Tab : JSObject 10 | { 11 | /// 12 | /// Deserialization constructor 13 | /// 14 | public Tab(IJSInProcessObjectReference _ref) : base(_ref) { } 15 | /// 16 | /// boolean. Whether the tab is active in its window. This may be true even if the tab's window is not currently focused.
17 | /// The active tab is usually the selected one. However, on Firefox for Android, extension popups open in a new tab. When this popup tab is selected, the active tab will instead be the one in which the popup opened. 18 | ///
19 | public bool Active => JSRef!.Get("active"); 20 | /// 21 | /// boolean. Indicates whether the tab is drawing attention. For example, when the tab displays a modal dialog, attention will be true. 22 | /// 23 | public bool? Attention => JSRef!.Get("attention"); 24 | /// 25 | /// boolean. Indicates whether the tab is producing sound. However, the user will not hear the sound if the tab is muted (see the mutedInfo property). 26 | /// 27 | public bool? Audible => JSRef!.Get("audible"); 28 | /// 29 | /// boolean. Whether the tab can be discarded by the browser. The default value is true. When set to false, the browser cannot automatically discard the tab. However, the tab can be discarded by tabs.discard. 30 | /// 31 | public bool? AutoDiscardable => JSRef!.Get("autoDiscardable"); 32 | /// 33 | /// string. The cookie store of the tab. See Work with contextual identities for more information. 34 | /// 35 | public string? CookieStoreId => JSRef!.Get("cookieStoreId"); 36 | /// 37 | /// boolean. Whether the tab is discarded. A discarded tab is one whose content has been unloaded from memory, but is still visible in the tab strip. Its content gets reloaded the next time it's activated. 38 | /// 39 | public bool? Discarded => JSRef!.Get("discarded"); 40 | /// 41 | /// string. The URL of the tab's favicon. Only present if the extension has the "tabs" permission or host permissions. It may also be undefined if the page has no favicon, or an empty string if the tab is loading. 42 | /// 43 | public string? FavIconUrl => JSRef!.Get("favIconUrl"); 44 | /// 45 | /// integer. The height of the tab in pixels. 46 | /// 47 | public int? Height => JSRef!.Get("height"); 48 | /// 49 | /// boolean. Whether the tab is hidden. 50 | /// 51 | public bool Hidden => JSRef!.Get("hidden"); 52 | /// 53 | /// boolean. Whether the tab is highlighted, i.e. part of the current tab selection. An active tab is always highlighted, but some browsers may allow additional tabs to be highlighted, for example by clicking them while holding Ctrl, Shift or ⌘ Command keys.
54 | /// Firefox for Android doesn't support highlighting multiple tabs. 55 | ///
56 | public bool Highlighted => JSRef!.Get("highlighted"); 57 | /// 58 | /// integer. The tab's ID. Tab IDs are unique within a browser session. The tab ID may also be set to tabs.TAB_ID_NONE (-1) for browser windows that don't host content tabs (for example, devtools windows). 59 | /// 60 | public int Id => JSRef!.Get("id"); 61 | /// 62 | /// boolean. Whether the tab is in a private browsing window. 63 | /// 64 | public bool Incognito => JSRef!.Get("incognito"); 65 | /// 66 | /// integer. The zero-based index of the tab within its window. 67 | /// 68 | public int Index => JSRef!.Get("index"); 69 | /// 70 | /// boolean. True if the tab can be rendered in Reader Mode, false otherwise. 71 | /// 72 | public bool IsArticle => JSRef!.Get("isArticle"); 73 | /// 74 | /// boolean. True if the tab is currently being rendered in Reader Mode, false otherwise. 75 | /// 76 | public bool IsInReaderMode => JSRef!.Get("isInReaderMode"); 77 | /// 78 | /// double. Time at which the tab was last accessed, in milliseconds since the epoch. 79 | /// 80 | public double LastAccessed => JSRef!.Get("lastAccessed"); 81 | /// 82 | /// tabs.MutedInfo. The current muted state for the tab and the reason for the last state change. 83 | /// 84 | public MutedInfo? MutedInfo => JSRef!.Get("mutedInfo"); 85 | /// 86 | /// integer. The ID of the tab that opened this tab, if any. This property is only present if the opener tab still exists and is in the same window. 87 | /// 88 | public int? OpenerTabId => JSRef!.Get("openerTabId"); 89 | /// 90 | /// string. The URL the tab is navigating to, before it has committed. This property is only present if the extension's manifest includes the "tabs" permission and there is a pending navigation. 91 | /// 92 | public string? PendingUrl => JSRef!.Get("pendingUrl"); 93 | /// 94 | /// boolean. Whether the tab is pinned. 95 | /// 96 | public bool Pinned => JSRef!.Get("pinned"); 97 | /// 98 | /// string. The session ID used to uniquely identify a Tab obtained from the sessions API. 99 | /// 100 | public string? SessionId => JSRef!.Get("sessionId"); 101 | /// 102 | /// string. Either loading or complete. 103 | /// 104 | public string? Status => JSRef!.Get("status"); 105 | /// 106 | /// integer The ID of the tab's successor. 107 | /// 108 | public int? SuccessorTabId => JSRef!.Get("successorTabId"); 109 | /// 110 | /// string. The title of the tab. Only present if the extension has the "tabs" permission or host permissions that matches the tab's URL. 111 | /// 112 | public string? Title=> JSRef!.Get("title"); 113 | /// 114 | /// string. The URL of the document that the tab is displaying. Only present if the extension has the "tabs" permission or a matching host permissions. 115 | /// 116 | public string? Url => JSRef!.Get("url"); 117 | /// 118 | /// integer. The width of the tab in pixels. 119 | /// 120 | public int? Width => JSRef!.Get("width"); 121 | /// 122 | /// integer. The ID of the window that hosts this tab. 123 | /// 124 | public int WindowId=> JSRef!.Get("windowId"); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # ignore built dlls from SpawnDev.BlazorJS.BrowserExtension.Build 7 | SpawnDev.BlazorJS.BrowserExtension/tasks/netstandard2.0/* 8 | 9 | # User-specific files 10 | *.rsuser 11 | *.suo 12 | *.user 13 | *.userosscache 14 | *.sln.docstates 15 | 16 | # User-specific files (MonoDevelop/Xamarin Studio) 17 | *.userprefs 18 | 19 | # Mono auto generated files 20 | mono_crash.* 21 | 22 | # Build results 23 | [Dd]ebug/ 24 | [Dd]ebugPublic/ 25 | [Rr]elease/ 26 | [Rr]eleases/ 27 | x64/ 28 | x86/ 29 | [Ww][Ii][Nn]32/ 30 | [Aa][Rr][Mm]/ 31 | [Aa][Rr][Mm]64/ 32 | bld/ 33 | [Bb]in/ 34 | [Oo]bj/ 35 | [Oo]ut/ 36 | [Ll]og/ 37 | [Ll]ogs/ 38 | 39 | # Visual Studio 2015/2017 cache/options directory 40 | .vs/ 41 | # Uncomment if you have tasks that create the project's static files in wwwroot 42 | #wwwroot/ 43 | 44 | # Visual Studio 2017 auto generated files 45 | Generated\ Files/ 46 | 47 | # MSTest test Results 48 | [Tt]est[Rr]esult*/ 49 | [Bb]uild[Ll]og.* 50 | 51 | # NUnit 52 | *.VisualState.xml 53 | TestResult.xml 54 | nunit-*.xml 55 | 56 | # Build Results of an ATL Project 57 | [Dd]ebugPS/ 58 | [Rr]eleasePS/ 59 | dlldata.c 60 | 61 | # Benchmark Results 62 | BenchmarkDotNet.Artifacts/ 63 | 64 | # .NET Core 65 | project.lock.json 66 | project.fragment.lock.json 67 | artifacts/ 68 | 69 | # ASP.NET Scaffolding 70 | ScaffoldingReadMe.txt 71 | 72 | # StyleCop 73 | StyleCopReport.xml 74 | 75 | # Files built by Visual Studio 76 | *_i.c 77 | *_p.c 78 | *_h.h 79 | *.ilk 80 | *.meta 81 | *.obj 82 | *.iobj 83 | *.pch 84 | *.pdb 85 | *.ipdb 86 | *.pgc 87 | *.pgd 88 | *.rsp 89 | *.sbr 90 | *.tlb 91 | *.tli 92 | *.tlh 93 | *.tmp 94 | *.tmp_proj 95 | *_wpftmp.csproj 96 | *.log 97 | *.vspscc 98 | *.vssscc 99 | .builds 100 | *.pidb 101 | *.svclog 102 | *.scc 103 | 104 | # Chutzpah Test files 105 | _Chutzpah* 106 | 107 | # Visual C++ cache files 108 | ipch/ 109 | *.aps 110 | *.ncb 111 | *.opendb 112 | *.opensdf 113 | *.sdf 114 | *.cachefile 115 | *.VC.db 116 | *.VC.VC.opendb 117 | 118 | # Visual Studio profiler 119 | *.psess 120 | *.vsp 121 | *.vspx 122 | *.sap 123 | 124 | # Visual Studio Trace Files 125 | *.e2e 126 | 127 | # TFS 2012 Local Workspace 128 | $tf/ 129 | 130 | # Guidance Automation Toolkit 131 | *.gpState 132 | 133 | # ReSharper is a .NET coding add-in 134 | _ReSharper*/ 135 | *.[Rr]e[Ss]harper 136 | *.DotSettings.user 137 | 138 | # TeamCity is a build add-in 139 | _TeamCity* 140 | 141 | # DotCover is a Code Coverage Tool 142 | *.dotCover 143 | 144 | # AxoCover is a Code Coverage Tool 145 | .axoCover/* 146 | !.axoCover/settings.json 147 | 148 | # Coverlet is a free, cross platform Code Coverage Tool 149 | coverage*.json 150 | coverage*.xml 151 | coverage*.info 152 | 153 | # Visual Studio code coverage results 154 | *.coverage 155 | *.coveragexml 156 | 157 | # NCrunch 158 | _NCrunch_* 159 | .*crunch*.local.xml 160 | nCrunchTemp_* 161 | 162 | # MightyMoose 163 | *.mm.* 164 | AutoTest.Net/ 165 | 166 | # Web workbench (sass) 167 | .sass-cache/ 168 | 169 | # Installshield output folder 170 | [Ee]xpress/ 171 | 172 | # DocProject is a documentation generator add-in 173 | DocProject/buildhelp/ 174 | DocProject/Help/*.HxT 175 | DocProject/Help/*.HxC 176 | DocProject/Help/*.hhc 177 | DocProject/Help/*.hhk 178 | DocProject/Help/*.hhp 179 | DocProject/Help/Html2 180 | DocProject/Help/html 181 | 182 | # Click-Once directory 183 | publish/ 184 | 185 | # Publish Web Output 186 | *.[Pp]ublish.xml 187 | *.azurePubxml 188 | # Note: Comment the next line if you want to checkin your web deploy settings, 189 | # but database connection strings (with potential passwords) will be unencrypted 190 | *.pubxml 191 | *.publishproj 192 | 193 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 194 | # checkin your Azure Web App publish settings, but sensitive information contained 195 | # in these scripts will be unencrypted 196 | PublishScripts/ 197 | 198 | # NuGet Packages 199 | *.nupkg 200 | # NuGet Symbol Packages 201 | *.snupkg 202 | # The packages folder can be ignored because of Package Restore 203 | **/[Pp]ackages/* 204 | # except build/, which is used as an MSBuild target. 205 | !**/[Pp]ackages/build/ 206 | # Uncomment if necessary however generally it will be regenerated when needed 207 | #!**/[Pp]ackages/repositories.config 208 | # NuGet v3's project.json files produces more ignorable files 209 | *.nuget.props 210 | *.nuget.targets 211 | 212 | # Microsoft Azure Build Output 213 | csx/ 214 | *.build.csdef 215 | 216 | # Microsoft Azure Emulator 217 | ecf/ 218 | rcf/ 219 | 220 | # Windows Store app package directories and files 221 | AppPackages/ 222 | BundleArtifacts/ 223 | Package.StoreAssociation.xml 224 | _pkginfo.txt 225 | *.appx 226 | *.appxbundle 227 | *.appxupload 228 | 229 | # Visual Studio cache files 230 | # files ending in .cache can be ignored 231 | *.[Cc]ache 232 | # but keep track of directories ending in .cache 233 | !?*.[Cc]ache/ 234 | 235 | # Others 236 | ClientBin/ 237 | ~$* 238 | *~ 239 | *.dbmdl 240 | *.dbproj.schemaview 241 | *.jfm 242 | *.pfx 243 | *.publishsettings 244 | orleans.codegen.cs 245 | 246 | # Including strong name files can present a security risk 247 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 248 | #*.snk 249 | 250 | # Since there are multiple workflows, uncomment next line to ignore bower_components 251 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 252 | #bower_components/ 253 | 254 | # RIA/Silverlight projects 255 | Generated_Code/ 256 | 257 | # Backup & report files from converting an old project file 258 | # to a newer Visual Studio version. Backup files are not needed, 259 | # because we have git ;-) 260 | _UpgradeReport_Files/ 261 | Backup*/ 262 | UpgradeLog*.XML 263 | UpgradeLog*.htm 264 | ServiceFabricBackup/ 265 | *.rptproj.bak 266 | 267 | # SQL Server files 268 | *.mdf 269 | *.ldf 270 | *.ndf 271 | 272 | # Business Intelligence projects 273 | *.rdl.data 274 | *.bim.layout 275 | *.bim_*.settings 276 | *.rptproj.rsuser 277 | *- [Bb]ackup.rdl 278 | *- [Bb]ackup ([0-9]).rdl 279 | *- [Bb]ackup ([0-9][0-9]).rdl 280 | 281 | # Microsoft Fakes 282 | FakesAssemblies/ 283 | 284 | # GhostDoc plugin setting file 285 | *.GhostDoc.xml 286 | 287 | # Node.js Tools for Visual Studio 288 | .ntvs_analysis.dat 289 | node_modules/ 290 | 291 | # Visual Studio 6 build log 292 | *.plg 293 | 294 | # Visual Studio 6 workspace options file 295 | *.opt 296 | 297 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 298 | *.vbw 299 | 300 | # Visual Studio LightSwitch build output 301 | **/*.HTMLClient/GeneratedArtifacts 302 | **/*.DesktopClient/GeneratedArtifacts 303 | **/*.DesktopClient/ModelManifest.xml 304 | **/*.Server/GeneratedArtifacts 305 | **/*.Server/ModelManifest.xml 306 | _Pvt_Extensions 307 | 308 | # Paket dependency manager 309 | .paket/paket.exe 310 | paket-files/ 311 | 312 | # FAKE - F# Make 313 | .fake/ 314 | 315 | # CodeRush personal settings 316 | .cr/personal 317 | 318 | # Python Tools for Visual Studio (PTVS) 319 | __pycache__/ 320 | *.pyc 321 | 322 | # Cake - Uncomment if you are using it 323 | # tools/** 324 | # !tools/packages.config 325 | 326 | # Tabs Studio 327 | *.tss 328 | 329 | # Telerik's JustMock configuration file 330 | *.jmconfig 331 | 332 | # BizTalk build output 333 | *.btp.cs 334 | *.btm.cs 335 | *.odx.cs 336 | *.xsd.cs 337 | 338 | # OpenCover UI analysis results 339 | OpenCover/ 340 | 341 | # Azure Stream Analytics local run output 342 | ASALocalRun/ 343 | 344 | # MSBuild Binary and Structured Log 345 | *.binlog 346 | 347 | # NVidia Nsight GPU debugger configuration file 348 | *.nvuser 349 | 350 | # MFractors (Xamarin productivity tool) working folder 351 | .mfractor/ 352 | 353 | # Local History for Visual Studio 354 | .localhistory/ 355 | 356 | # BeatPulse healthcheck temp database 357 | healthchecksdb 358 | 359 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 360 | MigrationBackup/ 361 | 362 | # Ionide (cross platform F# VS Code tools) working folder 363 | .ionide/ 364 | 365 | # Fody - auto-generated XML schema 366 | FodyWeavers.xsd -------------------------------------------------------------------------------- /SpawnDev.BlazorJS.BrowserExtension/DeclarativeNetRequest/RuleCondition.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace SpawnDev.BlazorJS.BrowserExtension 3 | { 4 | /// 5 | /// Details of the condition that determines whether a rule matches a request, as the condition property of a declarativeNetRequest.Rule.
6 | /// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest/RuleCondition 7 | ///
8 | public class RuleCondition 9 | { 10 | /// 11 | /// A string. Specifies whether the network request is first-party or third-party. The request is considered first-party if it's for the same domain as the document or subdocument that initiates the request. Otherwise, it's considered third-party. If omitted, all requests are accepted. Possible values are "firstParty" and "thirdParty". 12 | /// 13 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 14 | public EnumString? DomainType { get; set; } 15 | /// 16 | /// An array of string. The rule only matches network requests originating from this list of domains. If the list is omitted, the rule is applied to requests from all domains. An empty list is not allowed. A canonical domain should be used. This matches against the request initiator and not the request URL. 17 | /// 18 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 19 | public string? InitiatorDomains { get; set; } 20 | /// 21 | /// An array of string. The rule does not match network requests originating from this list of domains. If the list is empty or omitted, no domains are excluded. This takes precedence over initiatorDomains. A canonical domain should be used. This matches against the request initiator and not the request URL. 22 | /// 23 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 24 | public string[]? ExcludedInitiatorDomains { get; set; } 25 | /// 26 | /// A boolean. Whether the urlFilter or regexFilter (whichever is specified) is case sensitive. While there is consensus on defaulting to false across browsers in WECG issue 269, the value used to be true in (older) versions of Chrome and Safari. See Browser compatibility for details. 27 | /// 28 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 29 | public bool? IsUrlFilterCaseSensitive { get; set; } 30 | /// 31 | /// A string. Regular expression to match against the network request URL. Note that:
32 | /// - The supported format is not stable and varies across browsers, see "Regular expressions in DNR API (regexFilter)" in WECG issue 344 for details.
33 | /// - Only one of urlFilter or regexFilter can be specified.
34 | /// - The regexFilter must be composed of only ASCII characters. This is matched against a URL where the host is encoded in the punycode format (in case of internationalized domains) and any other non-ascii characters are percent-encoded in UTF-8. 35 | ///
36 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 37 | public string? RegexFilter { get; set; } 38 | /// 39 | /// An array of string. The rule only matches network requests when the domain matches one from this list. If the list is omitted, the rule is applied to requests from all domains. An empty list is not allowed. A canonical domain should be used. 40 | /// 41 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 42 | public string[]? RequestDomains { get; set; } 43 | /// 44 | /// An array of string. The rule does not match network requests when the domains matches one from this list. If the list is empty or omitted, no domains are excluded. This takes precedence over requestDomains. A canonical domain should be used. 45 | /// 46 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 47 | public string[]? ExcludedRequestDomains { get; set; } 48 | /// 49 | /// An array of string. List of HTTP request methods that the rule matches. An empty list is not allowed. Specifying a requestMethods rule condition also excludes non-HTTP(s) requests, whereas specifying excludedRequestMethods does not. 50 | /// 51 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 52 | public EnumString[]? RequestMethods { get; set; } 53 | /// 54 | /// An array of string. List of request methods that the rule does not match on. Only one of requestMethods and excludedRequestMethods should be specified. If neither of them is specified, all request methods are matched. 55 | /// 56 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 57 | public EnumString[]? ExcludedRequestMethods { get; set; } 58 | /// 59 | /// An array of declarativeNetRequest.ResourceType. List of resource types that the rule matches with. An empty list is not allowed. This must be specified for "allowAllRequests" rules and may only include the "sub_frame" and "main_frame" resource types. 60 | /// 61 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 62 | public EnumString[]? ResourceTypes { get; set; } 63 | /// 64 | /// An array of declarativeNetRequest.ResourceType. List of resource types that the rule does not match on. Only one of resourceTypes and excludedResourceTypes should be specified. If neither of them is specified, all resource types except "main_frame" are blocked. 65 | /// 66 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 67 | public EnumString[]? ExcludedResourceTypes { get; set; } 68 | /// 69 | /// An array of number. List of tabs.Tab.id that the rule should match. An ID of tabs.TAB_ID_NONE matches requests that don't originate from a tab. An empty list is not allowed. Only supported for session-scoped rules. 70 | /// 71 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 72 | public int[]? TabIds { get; set; } 73 | /// 74 | /// An array of number. List of tabs.Tab.id that the rule should not match. An ID of tabs.TAB_ID_NONE excludes requests that do not originate from a tab. Only supported for session-scoped rules. 75 | /// 76 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 77 | public int[]? ExcludedTabIds { get; set; } 78 | /// 79 | /// A string. The pattern that is matched against the network request URL. Supported constructs:
80 | /// - * : Wildcard: Matches any number of characters.
81 | /// - | : Left or right anchor: If used at either end of the pattern, specifies the beginning or end of the URL respectively.
82 | /// - || : Domain name anchor: If used at the beginning of the pattern, specifies the start of a (sub-)domain of the URL.
83 | /// - ^ : Separator character: This matches anything except a letter, a digit, or one of _, -, ., or %. The last ^ may also match the end of the URL instead of a separator character.
84 | /// urlFilter is composed of the following parts: (optional left/domain name anchor) + pattern + (optional right anchor). If omitted, all URLs are matched. An empty string is not allowed. A pattern beginning with ||* is not allowed. Use * instead. Note that:
85 | /// - Only one of urlFilter or regexFilter can be specified.
86 | /// - The urlFilter must be composed of only ASCII characters. This is matched against a URL where the host is encoded in the punycode format (in case of internationalized domains) and any other non-ASCII characters are percent-encoded in UTF-8. For example, when the request URL is http://abc.рф?q=ф, the urlFilter is matched against the URL http://abc.xn--p1ai/?q=%D1%84. 87 | ///
88 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] 89 | public string? UrlFilter { get; set; } 90 | } 91 | } 92 | --------------------------------------------------------------------------------