Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Move to a monorepo #44

Merged
merged 10 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,4 @@
.store/
dist/
node_modules/
# For some reson, tsc will generate some in place js files
src/**/*.j*
!src/prefs.js

**/.turbo
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,35 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/// <reference path="../link.d.ts" />

export type ClickHandlerMessage = {
name: 'openlink'
data: { href: string }
} & { target: JSWindowActorParent }
// @ts-check
/// <reference types="@browser/link" />

export class ClickHandlerChild extends JSWindowActorChild {
getHrefIfExists(target: Node): string | undefined {
if ((target as HTMLAnchorElement).href) {
return (target as HTMLAnchorElement).href
/**
* @param {Node} target
* @returns {string | undefined}
*/
getHrefIfExists(target) {
/** @type {HTMLAnchorElement} */
// @ts-expect-error We cant cast with as, so this is how I am casting :/
const asAnchor = target

if (asAnchor.href) {
return asAnchor.href
}

if (target.parentElement) {
return this.getHrefIfExists(target.parentElement)
}
}

handleEvent(event: MouseEvent) {
/**
* @param {MouseEvent & { target: Node }} event
*/
handleEvent(event) {
if (event.defaultPrevented || !event.target) return

const href = this.getHrefIfExists(event.target as Node)
const href = this.getHrefIfExists(event.target)

const ctrlClick = event.button === 0 && event.ctrlKey
const middleClick = event.button === 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/// <reference path="../link.d.ts" />
import { ClickHandlerMessage } from './ClickHandlerChild'

// @ts-check
/// <reference types="@browser/link" />

export class ClickHandlerParent extends JSWindowActorParent {
receiveMessage(event: ClickHandlerMessage) {
/**
* @param {ClickHandlerMessage} event
*/
receiveMessage(event) {
if (event.name == 'openlink') {
const win = event.target.browsingContext.embedderElement.ownerGlobal
const uri = Services.io.newURI(event.data.href)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,58 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/// <reference path="../link.d.ts" />
// @ts-check
/// <reference types="@browser/link" />
import { lazyESModuleGetters } from 'resource://app/modules/TypedImportUtils.sys.mjs'

import type { ContextMenuInfo, MediaInfo } from './ContextMenu.types'

const lazy = lazyESModuleGetters({
SelectionUtils: 'resource://gre/modules/SelectionUtils.sys.mjs',
E10SUtils: 'resource://gre/modules/E10SUtils.sys.mjs',
})

export class ContextMenuChild extends JSWindowActorChild {
getHrefIfExists(target: Node): string | undefined {
if ((target as HTMLAnchorElement).href) {
return (target as HTMLAnchorElement).href
/**
* @param {Node} target
* @returns {string | undefined}
*/
getHrefIfExists(target) {
/** @type {HTMLAnchorElement} */
// @ts-expect-error We cant cast with as, so this is how I am casting :/
const asAnchor = target
if (asAnchor.href) {
return asAnchor.href
}

if (target.parentElement) {
return this.getHrefIfExists(target.parentElement)
}
}

getImageSrcIfExists(target: Node): string | undefined {
if ((target as HTMLImageElement).src) {
return (target as HTMLImageElement).src
/**
* @param {Node} target
* @returns {string | undefined}
*/
getImageSrcIfExists(target) {
/** @type {HTMLImageElement} */
// @ts-expect-error We cant cast with as, so this is how I am casting :/
const asImg = target
if (asImg.src) {
return asImg.src
}
}

/**
* This code was based on the code from here: https://searchfox.org/mozilla-central/source/browser/actors/ContextMenuChild.sys.mjs#568
* @param {Node & nsIImageLoadingContentType} target
*/
getMediaInfo(target: Node & nsIImageLoadingContentType) {
getMediaInfo(target) {
// @ts-expect-error - Ci interfaces are not instanceofable
if (!(target instanceof Ci.nsIImageLoadingContent && target.currentURI)) {
return
}

const mediaInfo: MediaInfo = {}
/** @type {ContextMenuMediaInfo} */
const mediaInfo = {}

try {
const imageCache = Cc['@mozilla.org/image/tools;1']
Expand Down Expand Up @@ -72,21 +87,23 @@ export class ContextMenuChild extends JSWindowActorChild {
return mediaInfo
}

getReferrerInfo(target: Element) {
/** @param {Element} target */
getReferrerInfo(target) {
/** @type {nsIReferrerInfoType} */
// @ts-expect-error - Ci interfaces are really poorly typed at the moment
const referrerInfo = Cc['@mozilla.org/referrer-info;1'].createInstance(
Ci.nsIReferrerInfo,
) as nsIReferrerInfoType
)
referrerInfo.initWithElement(target)
return lazy.E10SUtils.serializeReferrerInfo(referrerInfo)
}

handleEvent(
event: MouseEvent & { inputSource: number; composedTarget?: EventTarget },
) {
const data: {
position: ContextMenuInfo['position']
context: ContextMenuInfo['context']
} & Partial<ContextMenuInfo> = {
/**
* @param {MouseEvent & { inputSource: number; composedTarget?: EventTarget & Node; target?: Node }} event
*/
handleEvent(event) {
/** @type {{ position: ContextMenuInfo['position']; context: ContextMenuInfo['context']} & Partial<ContextMenuInfo>} */
const data = {
position: {
screenX: event.screenX,
screenY: event.screenY,
Expand All @@ -95,8 +112,7 @@ export class ContextMenuChild extends JSWindowActorChild {

context: {
principal:
(event.target &&
(event.target as Node).ownerDocument?.nodePrincipal) ||
(event.target && event.target.ownerDocument?.nodePrincipal) ||
undefined,
},
}
Expand All @@ -111,18 +127,18 @@ export class ContextMenuChild extends JSWindowActorChild {

if (
event.composedTarget &&
(event.composedTarget as Node).nodeType === Node.ELEMENT_NODE
event.composedTarget.nodeType === Node.ELEMENT_NODE
) {
const node = event.composedTarget as Node
/** @type {Element & nsIImageLoadingContentType} */
// @ts-expect-error - Ci interfaces are a pain
const node = event.composedTarget

data.href = this.getHrefIfExists(node)
data.imageSrc = this.getImageSrcIfExists(node)
data.mediaInfo = this.getMediaInfo(
node as Node & nsIImageLoadingContentType,
)
data.context.referrerInfo = this.getReferrerInfo(node as Element)
data.mediaInfo = this.getMediaInfo(node)
data.context.referrerInfo = this.getReferrerInfo(node)
}

this.sendAsyncMessage('contextmenu', data satisfies ContextMenuInfo)
this.sendAsyncMessage('contextmenu', data)
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import type { ContextMenuInfo } from './ContextMenu.types'

type ContextMenuEvent = {
name: 'contextmenu'
data: ContextMenuInfo
target: ContextMenuParent
}
// @ts-check
/// <reference types="@browser/link" />

export class ContextMenuParent extends JSWindowActorParent {
receiveMessage(event: ContextMenuEvent) {
/** @param {ContextMenuEvent} event */
receiveMessage(event) {
if (event.name == 'contextmenu') {
const win = event.target.browsingContext.embedderElement.ownerGlobal
win.windowApi.contextMenu.showContextMenu(event.data, this)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/// <reference path="../link.d.ts" />
// @ts-check
/// <reference types="@browser/link" />
import { FaviconLoader } from 'resource://app/modules/FaviconLoader.sys.mjs'

declare global {
interface Document {
documentURIObject: nsIURIType
}

interface HTMLElement {
ownerGlobal: Window
}
}

type DOMLinkAdded = Event & { target: HTMLLinkElement; type: 'DOMLinkAdded' }
type DOMHeadParsed = Event & {
target: HTMLHeadElement
type: 'DOMHeadElementParsed'
}
type PageShow = PageTransitionEvent & { type: 'pageshow' }
type PageHide = PageTransitionEvent & { type: 'pagehide' }

export class LinkHandlerChild extends JSWindowActorChild {
iconLoader = new FaviconLoader(this)
loadedTabIcon = false
Expand All @@ -40,25 +23,37 @@ export class LinkHandlerChild extends JSWindowActorChild {
}
}

onPageShow(event: PageShow) {
/**
* @param {PageShowEvent} event
*/
onPageShow(event) {
if (event.target != this.document) return
this.fetchRootFavicon()
if (this.iconLoader) this.iconLoader.onPageShow()
}

onPageHide(event: PageHide) {
/**
* @param {PageHideEvent} event
*/
onPageHide(event) {
if (event.target != this.document) return
if (this.iconLoader) this.iconLoader.onPageHide()
this.loadedTabIcon = false
}

onHeadParsed(event: DOMHeadParsed) {
/**
* @param {DOMHeadParsedEvent} event
*/
onHeadParsed(event) {
if (event.target.ownerDocument != this.document) return
this.fetchRootFavicon()
if (this.iconLoader) this.iconLoader.onPageShow()
}

onLinkEvent(event: DOMLinkAdded) {
/**
* @param {DOMLinkAddedEvent} event
*/
onLinkEvent(event) {
const link = event.target
// Ignore sub-frames (bugs 305472, 479408).
if (link.ownerGlobal != this.contentWindow) {
Expand All @@ -76,7 +71,8 @@ export class LinkHandlerChild extends JSWindowActorChild {
// whole content
let iconAdded = false
let searchAdded = false
const rels: Record<string, boolean> = {}
/** @type {Record<string, boolean>} */
const rels = {}
for (const relString of rel.split(/\s+/)) {
rels[relString] = true
}
Expand Down Expand Up @@ -139,7 +135,10 @@ export class LinkHandlerChild extends JSWindowActorChild {
}
}

handleEvent(event: PageShow | PageHide | DOMHeadParsed | DOMLinkAdded) {
/**
* @param {PageShowEvent | PageHideEvent | DOMHeadParsedEvent | DOMLinkAddedEvent} event
*/
handleEvent(event) {
switch (event.type) {
case 'pageshow':
return this.onPageShow(event)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/// <reference path="../link.d.ts" />
// @ts-check
/// <reference types="@browser/link" />

export class LinkHandlerParent extends JSWindowActorParent {
receiveMessage(aMsg: { name: 'Link:SetIcon'; data: { iconURL: string } }) {
/** @param {{ name: 'Link:SetIcon'; data: { iconURL: string } }} aMsg */
receiveMessage(aMsg) {
const win = this.browsingContext.topChromeWindow

switch (aMsg.name) {
Expand Down
9 changes: 9 additions & 0 deletions apps/actors/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "actors",
"version": "1.0.0",
"description": "",
"dependencies": {
"@browser/link": "workspace:*"
},
"license": "ISC"
}
Loading
Loading