This repository has been archived by the owner on Feb 26, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 123
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- This adds some support just for Spotify, as a first service - Does some service detection, so in the future other services can be detected from history - Loads services dynamically from extension/services/* - Renames the services.js module to background/serviceList.js - Implements a generic content script injection system
- Loading branch information
Showing
13 changed files
with
359 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* globals log */ | ||
|
||
this.content = (function() { | ||
const NO_RECEIVER_MESSAGE = | ||
"Could not establish connection. Receiving end does not exist"; | ||
const exports = {}; | ||
exports.lazyInject = async function(tabId, scripts) { | ||
if (typeof scripts === "string") { | ||
scripts = [scripts]; | ||
} | ||
const scriptKey = scripts.join(","); | ||
let available = true; | ||
try { | ||
available = await browser.tabs.sendMessage(tabId, { | ||
type: "ping", | ||
scriptKey, | ||
}); | ||
} catch (e) { | ||
available = false; | ||
if (String(e).includes(NO_RECEIVER_MESSAGE)) { | ||
// This is a normal error | ||
} else { | ||
log.error("Error sending message:", String(e)); | ||
} | ||
available = false; | ||
} | ||
if (available) { | ||
return; | ||
} | ||
scripts = [ | ||
"/buildSettings.js", | ||
"/log.js", | ||
"/content/helpers.js", | ||
"/content/communicate.js", | ||
] | ||
.concat(scripts) | ||
.concat(["/content/responder.js"]); | ||
for (const script of scripts) { | ||
await browser.tabs.executeScript(tabId, { file: script }); | ||
} | ||
await browser.tabs.sendMessage(tabId, { | ||
type: "scriptsLoaded", | ||
scriptKey, | ||
}); | ||
}; | ||
return exports; | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* globals log */ | ||
|
||
this.communicate = (function() { | ||
const exports = {}; | ||
const HANDLERS = {}; | ||
exports.register = function(type, handler) { | ||
if (HANDLERS[type]) { | ||
throw new Error(`There is already a handler registerd for ${type}`); | ||
} | ||
HANDLERS[type] = handler; | ||
}; | ||
exports.handle = function(message, sender) { | ||
if (!HANDLERS[message.type]) { | ||
log.warn("Message of unknown type:", message.type, message); | ||
throw new Error(`No handler for ${message.type}`); | ||
} | ||
try { | ||
return HANDLERS[message.type](message, sender); | ||
} catch (e) { | ||
log.error(`Error in ${message.type} handler: ${e}`, e.stack); | ||
throw e; | ||
} | ||
}; | ||
return exports; | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
this.helpers = (function() { | ||
const exports = {}; | ||
|
||
exports.waitForSelector = function(selector, options) { | ||
const interval = (options && options.interval) || 50; | ||
const timeout = (options && options.timeout) || 1000; | ||
return new Promise((resolve, reject) => { | ||
const start = Date.now(); | ||
const id = setInterval(() => { | ||
const result = document.querySelector(selector); | ||
if (result) { | ||
clearTimeout(id); | ||
resolve(result); | ||
return; | ||
} | ||
if (Date.now() > start + timeout) { | ||
const e = new Error(`Timeout waiting for ${selector}`); | ||
e.name = "TimeoutError"; | ||
clearTimeout(id); | ||
reject(e); | ||
} | ||
}, interval); | ||
}); | ||
}; | ||
|
||
exports.setReactInputValue = function(input, value) { | ||
// See https://hustle.bizongo.in/simulate-react-on-change-on-controlled-components-baa336920e04 | ||
// for the why of this | ||
const nativeInputValueSetter = Object.getOwnPropertyDescriptor( | ||
window.HTMLInputElement.prototype, | ||
"value" | ||
).set; | ||
nativeInputValueSetter.call(input, value); | ||
const inputEvent = new Event("input", { bubbles: true }); | ||
input.dispatchEvent(inputEvent); | ||
}; | ||
|
||
return exports; | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* globals communicate */ | ||
// Note this should always be loaded last, because once it's ready to response we consider the content script "loaded" | ||
|
||
this.responder = (function() { | ||
const loadedScripts = {}; | ||
|
||
function init() { | ||
browser.runtime.onMessage.addListener((message, sender) => { | ||
if (message.type === "ping") { | ||
if (message.scriptKey) { | ||
return !!loadedScripts[message.scriptKey]; | ||
} | ||
return true; | ||
} else if (message.type === "scriptsLoaded") { | ||
loadedScripts[message.scriptKey] = true; | ||
return null; | ||
} | ||
return communicate.handle(message, sender); | ||
}); | ||
} | ||
init(); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* globals intentRunner, serviceList */ | ||
|
||
this.intents.music = (function() { | ||
const exports = {}; | ||
const SERVICES = {}; | ||
exports.register = function(service) { | ||
SERVICES[service.name] = service; | ||
}; | ||
|
||
intentRunner.registerIntent({ | ||
name: "music.play", | ||
examples: ["Play Green Day"], | ||
match: ` | ||
play [query] | ||
`, | ||
async run(context) { | ||
const service = await serviceList.getService("music", SERVICES); | ||
await service.playQuery(context.slots.query); | ||
}, | ||
}); | ||
|
||
intentRunner.registerIntent({ | ||
name: "music.pause", | ||
examples: ["Pause music"], | ||
match: ` | ||
pause music | ||
stop music | ||
`, | ||
async run(context) { | ||
const service = await serviceList.getService("music", SERVICES); | ||
await service.pause(); | ||
}, | ||
}); | ||
|
||
intentRunner.registerIntent({ | ||
name: "music.unpause", | ||
examples: ["Unpause", "continue music", "play music"], | ||
match: ` | ||
unpause | ||
continue music | ||
play music | ||
`, | ||
priority: "high", | ||
async run(context) { | ||
const service = await serviceList.getService("music", SERVICES); | ||
await service.unpause(); | ||
}, | ||
}); | ||
|
||
intentRunner.registerIntent({ | ||
name: "music.focus", | ||
examples: ["Open music"], | ||
match: ` | ||
open music | ||
show music | ||
focus music | ||
`, | ||
async run(context) { | ||
const service = await serviceList.getService("music", SERVICES); | ||
await service.activateOrOpen(); | ||
}, | ||
}); | ||
|
||
return exports; | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.