2017-09-29 18:29:36 +01:00
|
|
|
/** Inject an input element into unsuspecting webpages and provide an API for interaction with tridactyl */
|
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
import Logger from "./logging"
|
2018-04-24 19:49:44 +01:00
|
|
|
import * as config from "./config"
|
2018-05-20 13:17:28 +01:00
|
|
|
import { theme } from "./styling"
|
2018-04-13 19:28:03 +01:00
|
|
|
const logger = new Logger("messaging")
|
2017-12-29 23:58:23 +00:00
|
|
|
|
2017-10-13 22:10:33 -07:00
|
|
|
/* TODO:
|
2017-09-29 18:29:36 +01:00
|
|
|
CSS
|
|
|
|
Friendliest-to-webpage way of injecting commandline bar?
|
|
|
|
Security: how to prevent other people's JS from seeing or accessing the bar or its output?
|
|
|
|
- Method here is isolation via iframe
|
|
|
|
- Web content can replace the iframe, but can't view or edit its content.
|
|
|
|
- see doc/escalating-privilege.md for other approaches.
|
|
|
|
*/
|
|
|
|
|
2017-10-02 00:59:51 +01:00
|
|
|
// inject the commandline iframe into a content page
|
2017-09-29 18:29:36 +01:00
|
|
|
|
2017-10-05 15:27:45 +01:00
|
|
|
let cmdline_iframe: HTMLIFrameElement = undefined
|
2018-04-26 01:10:33 +01:00
|
|
|
let enabled = false
|
2017-10-05 15:27:45 +01:00
|
|
|
|
2018-04-24 19:49:44 +01:00
|
|
|
/** Initialise the cmdline_iframe element unless the window location is included in a value of config/noiframeon */
|
|
|
|
async function init() {
|
|
|
|
let noiframeon = await config.getAsync("noiframeon")
|
2018-04-26 01:10:33 +01:00
|
|
|
enabled =
|
2018-04-24 19:49:44 +01:00
|
|
|
noiframeon.length == 0 ||
|
|
|
|
noiframeon.find(url => window.location.href.includes(url)) === undefined
|
|
|
|
if (enabled && cmdline_iframe === undefined) {
|
2017-10-23 09:42:50 +01:00
|
|
|
try {
|
|
|
|
cmdline_iframe = window.document.createElement("iframe")
|
2018-03-04 14:15:26 +01:00
|
|
|
cmdline_iframe.className = "cleanslate"
|
2018-04-13 19:28:03 +01:00
|
|
|
cmdline_iframe.setAttribute(
|
|
|
|
"src",
|
|
|
|
browser.extension.getURL("static/commandline.html"),
|
|
|
|
)
|
2017-10-28 20:16:15 +08:00
|
|
|
cmdline_iframe.setAttribute("id", "cmdline_iframe")
|
2017-10-23 09:42:50 +01:00
|
|
|
hide()
|
2018-05-20 17:50:08 +01:00
|
|
|
document.documentElement.appendChild(cmdline_iframe)
|
2018-05-20 13:17:28 +01:00
|
|
|
// first theming of page root
|
|
|
|
await theme(window.document.querySelector(":root"))
|
2017-10-23 09:42:50 +01:00
|
|
|
} catch (e) {
|
2017-12-30 00:46:26 +00:00
|
|
|
logger.error("Couldn't initialise cmdline_iframe!", e)
|
2017-10-23 09:42:50 +01:00
|
|
|
}
|
|
|
|
}
|
2017-10-05 15:27:45 +01:00
|
|
|
}
|
2018-04-19 18:39:04 +01:00
|
|
|
|
2018-05-20 17:50:08 +01:00
|
|
|
// Load the iframe immediately if we can (happens if tridactyl is reloaded or on ImageDocument)
|
2018-04-19 18:39:04 +01:00
|
|
|
// Else load lazily to avoid upsetting page JS that hates foreign iframes.
|
2018-05-20 17:50:08 +01:00
|
|
|
try {
|
2018-04-19 18:39:04 +01:00
|
|
|
init()
|
2018-05-20 17:50:08 +01:00
|
|
|
} catch (e) {
|
2018-04-19 18:39:04 +01:00
|
|
|
// Surrender event loop with setTimeout() to page JS in case it's still doing stuff.
|
|
|
|
document.addEventListener("DOMContentLoaded", () => setTimeout(init, 0))
|
|
|
|
}
|
2017-10-06 04:16:02 +01:00
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
export function show() {
|
2018-05-17 21:05:58 +01:00
|
|
|
try {
|
2018-04-26 01:10:33 +01:00
|
|
|
const height =
|
|
|
|
cmdline_iframe.contentWindow.document.body.offsetHeight + "px"
|
|
|
|
cmdline_iframe.setAttribute("style", `height: ${height} !important;`)
|
2018-05-17 21:05:58 +01:00
|
|
|
} catch (e) {}
|
2017-10-05 15:27:45 +01:00
|
|
|
}
|
2017-09-29 18:29:36 +01:00
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
export function hide() {
|
2018-05-17 21:05:58 +01:00
|
|
|
try {
|
2018-04-26 01:10:33 +01:00
|
|
|
cmdline_iframe.setAttribute("style", "height: 0px !important;")
|
2018-05-17 21:05:58 +01:00
|
|
|
} catch (e) {}
|
2017-10-04 21:35:52 +01:00
|
|
|
}
|
2017-10-05 12:34:18 +01:00
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
export function focus() {
|
2018-05-17 21:05:58 +01:00
|
|
|
try {
|
2018-04-26 01:10:33 +01:00
|
|
|
cmdline_iframe.focus()
|
2018-05-17 21:05:58 +01:00
|
|
|
} catch (e) {}
|
2017-10-05 12:34:18 +01:00
|
|
|
}
|
2017-10-28 19:20:31 +08:00
|
|
|
|
|
|
|
export function blur() {
|
2018-05-17 21:05:58 +01:00
|
|
|
try {
|
2018-04-26 01:10:33 +01:00
|
|
|
cmdline_iframe.blur()
|
2018-05-17 21:05:58 +01:00
|
|
|
} catch (e) {}
|
2017-10-28 19:20:31 +08:00
|
|
|
}
|
2017-10-28 13:42:54 +01:00
|
|
|
|
2018-03-08 22:14:32 +01:00
|
|
|
export function executeWithoutCommandLine(fn) {
|
|
|
|
let parent
|
|
|
|
if (cmdline_iframe) {
|
|
|
|
parent = cmdline_iframe.parentNode
|
|
|
|
parent.removeChild(cmdline_iframe)
|
|
|
|
}
|
|
|
|
let result
|
|
|
|
try {
|
|
|
|
result = fn()
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e)
|
|
|
|
}
|
|
|
|
if (cmdline_iframe) parent.appendChild(cmdline_iframe)
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
import * as Messaging from "./messaging"
|
|
|
|
import * as SELF from "./commandline_content"
|
|
|
|
Messaging.addListener("commandline_content", Messaging.attributeCaller(SELF))
|