Runtime Decorators
The Runtime decorators allow you to easily respond to browser runtime events in your extension services. These decorators provide a clean way to handle extension lifecycle events such as installation, startup, updates, and suspension.
Method Decorators
onInstalled
This decorator handles events that fire when the extension is installed or updated, or when Chrome is updated.
import { onInstalled, InjectableService } from 'deco-ext';
@InjectableService()
class SetupService {
@onInstalled()
handleInstallation(details: browser.Runtime.OnInstalledDetailsType) {
const { reason, previousVersion } = details;
if (reason === 'install') {
console.log('Extension was installed for the first time');
this.setupFirstTimeUser();
}
else if (reason === 'update') {
console.log(`Extension updated from version ${previousVersion}`);
this.migrateUserData();
}
}
private setupFirstTimeUser() {
// Initialize default settings
}
private migrateUserData() {
// Handle data migration between versions
}
}
With parameter decorator:
import { onInstalled, installedDetails, InjectableService } from 'deco-ext';
@InjectableService()
class SetupService {
@onInstalled()
handleInstallation(
@installedDetails('reason') reason: string,
@installedDetails('previousVersion') previousVersion?: string,
@installedDetails('temporary') isTemporary?: boolean
) {
if (reason === 'install') {
console.log('First-time installation');
} else if (reason === 'update') {
console.log(`Updated from ${previousVersion}`);
}
if (isTemporary) {
console.log('This is a temporary installation (developer mode)');
}
}
}
The onInstalled
decorator also accepts filtering options to only execute for specific installation reasons:
import { onInstalled, InjectableService } from 'deco-ext';
@InjectableService()
class SetupService {
// Only runs on first installation
@onInstalled({ reason: 'install' })
firstTimeSetup(details: browser.Runtime.OnInstalledDetailsType) {
console.log('Setting up extension for first time use');
}
// Only runs on updates
@onInstalled({ reason: 'update' })
handleUpdate(details: browser.Runtime.OnInstalledDetailsType) {
console.log(`Updating from version ${details.previousVersion}`);
}
// Only runs for temporary installations (during development)
@onInstalled({ temporary: true })
devModeSetup(details: browser.Runtime.OnInstalledDetailsType) {
console.log('Dev mode detected, setting up debugging tools');
}
}
onBrowserStartup
This decorator handles events that fire when the browser starts up with the extension already installed.
import { onBrowserStartup, InjectableService } from 'deco-ext';
@InjectableService()
class StartupService {
@onBrowserStartup()
handleBrowserStartup() {
console.log('Browser has started');
this.refreshCachedData();
}
private refreshCachedData() {
// Refresh any cached data
}
}
onExtensionSuspend
This decorator handles events that fire when the extension is about to be unloaded, typically when the browser is shutting down.
import { onExtensionSuspend, InjectableService } from 'deco-ext';
@InjectableService()
class ShutdownService {
@onExtensionSuspend()
handleSuspend() {
console.log('Extension is being suspended');
this.saveState();
this.closeConnections();
}
private saveState() {
// Save any unsaved state
}
private closeConnections() {
// Close any open database connections or other resources
}
}
onSuspendCanceled
This decorator handles events that fire when the extension suspension has been canceled.
import { onSuspendCanceled, InjectableService } from 'deco-ext';
@InjectableService()
class SuspendService {
@onSuspendCanceled()
handleSuspendCanceled() {
console.log('Extension suspension was canceled');
this.reopenConnections();
}
private reopenConnections() {
// Reopen any connections that were closed during suspend
}
}
onUpdateAvailable
This decorator handles events that fire when an update for the extension is available.
import { onUpdateAvailable, InjectableService } from 'deco-ext';
@InjectableService()
class UpdateService {
@onUpdateAvailable()
handleUpdateAvailable(details: { version: string }) {
console.log(`Update available: version ${details.version}`);
// Optionally reload to apply update immediately
// browser.runtime.reload();
}
}
With parameter decorator:
import { onUpdateAvailable, updateDetails, InjectableService } from 'deco-ext';
@InjectableService()
class UpdateService {
@onUpdateAvailable()
handleUpdateAvailable(@updateDetails('version') newVersion: string) {
console.log(`Update available: version ${newVersion}`);
// Show update notification to user
this.notifyUserAboutUpdate(newVersion);
}
private notifyUserAboutUpdate(version: string) {
// Display a notification about the update
}
}
Parameter Decorators
The Runtime API includes parameter decorators for specific event types:
installedDetails
Used with onInstalled
to extract specific properties from the installation details:
import { onInstalled, installedDetails, InjectableService } from 'deco-ext';
@InjectableService()
class ExtensionLifecycle {
@onInstalled()
logInstallationDetails(
@installedDetails('reason') reason: string,
@installedDetails('previousVersion') prevVersion?: string
) {
console.log(`Installation event: ${reason}`);
if (reason === 'update' && prevVersion) {
console.log(`Previous version: ${prevVersion}`);
}
}
}
updateDetails
Used with onUpdateAvailable
to extract properties from the update details object:
import { onUpdateAvailable, updateDetails, InjectableService } from 'deco-ext';
@InjectableService()
class UpdateService {
@onUpdateAvailable()
logUpdate(@updateDetails('version') newVersion: string) {
console.log(`New version available: ${newVersion}`);
}
}
Installation Reasons
The onInstalled
decorator can filter by installation reason:
install
: The extension was installed for the first timeupdate
: The extension was updated to a new versionchrome_update
: The browser was updated to a new versionshared_module_update
: A shared module was updated
Implementation Details
These decorators use a singleton pattern to ensure only one event listener is registered per event type, and then route events to all decorated methods. When a runtime event occurs:
- The event is received by the single registered browser API listener
- The event data is passed to all registered method handlers
- For each handler:
- The class instance is resolved from the dependency injection container
- If the class has an
init
method, it's called before handling the event - If parameter decorators are used, the event data is transformed accordingly
- The method is called with the appropriate parameters
The decorators can only be used on methods within classes that have been decorated with the InjectableService
decorator from deco-ext.