Skip to content
This repository was archived by the owner on Feb 26, 2021. It is now read-only.

Commit 8ed8557

Browse files
committed
add named pages to entity types
2 parents 7e3d85d + 81cb31f commit 8ed8557

89 files changed

Lines changed: 3951 additions & 3185 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.eslintignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ extension/onboarding/onboardingController.js
99
extension/onboarding/onboardingView.js
1010
extension/wakeword/wakewordController.js
1111
extension/wakeword/wakewordView.js
12-
extension/intents/pocket/contentScript.js
12+
extension/intents/pocket/contentScript.js
13+
*.bundle.js

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@ manifest.json
3737
Thumbs.db
3838
/build
3939
/bin/username-cache.json
40+
*.bundle.js

.taskcluster.yml

Lines changed: 319 additions & 0 deletions
Large diffs are not rendered by default.

bin/rollup-content-scripts.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env node
2+
3+
const rollup = require("rollup");
4+
const glob = require("glob");
5+
const scriptUtils = require("./script-utils.js");
6+
const path = require("path");
7+
const tmp = require("tmp");
8+
9+
async function run() {
10+
for (const input of glob.sync(
11+
path.join(scriptUtils.extensionDir, "**/*.content.js")
12+
)) {
13+
const tmpObj = tmp.fileSync();
14+
const outputFilename = input.replace(/\.content\.js$/, ".bundle.js");
15+
const bundle = await rollup.rollup({
16+
input,
17+
});
18+
await bundle.write({
19+
format: "iife",
20+
sourcemap: "inline",
21+
file: tmpObj.name,
22+
});
23+
scriptUtils.copyFile(tmpObj.name, outputFilename, true);
24+
tmpObj.removeCallback();
25+
}
26+
}
27+
28+
run();

bin/script-utils.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,8 @@ exports.writeFile = function(path, content, verbose = false) {
2727
console.log(`Wrote ${displayPath(path)} (${content.length} chars)`);
2828
}
2929
};
30+
31+
exports.copyFile = function(source, dest, verbose = false) {
32+
const existing = fs.readFileSync(source, { encoding: "UTF-8" });
33+
exports.writeFile(dest, existing, verbose);
34+
};

docs/writing-an-intent.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ intentRunner.registerIntent({
6464

6565
Some things to note:
6666

67-
- We use [JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) in most of the extension (except for content scripts).
67+
- We use [JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) in most of the extension
6868
- Intents often don't actually export anything, they work by calling `intentRunner.register()`. But you can [export](https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export) if you want.
6969
- We use [eslint](https://eslint.org/) in the codebase, and it's recommended you configure your editor to show warnings.
7070
- You can (and usually will) have multiple intents in a single module and config file (e.g., `someIntent.otherCommand` and so on)
@@ -95,7 +95,7 @@ Patterns have words, words with alternatives, slots, typed slots, and parameters
9595

9696
**Typed slots:** these are things like `[service:musicServiceName]`. These "types" are lists of specific strings. These types are in the `background/entityTypes.js` module. Right now this system isn't very extensible.
9797

98-
**Parameters:** sometimes you care _which_ phrase is matched, not just a slot. If you include `[param=value]` then `contents.parameters.param === "value"` (if that specific phrase is matched). You can see an example in [`extensions/intents/music/music.js`](https://github.com/mozilla/firefox-voice/blob/master/extension/intents/music/music.js) in `music.move`.
98+
**Parameters:** sometimes you care _which_ phrase is matched, not just a slot. If you include `[param=value]` then `context.parameters.param === "value"` (if that specific phrase is matched). You can see an example in [`extensions/intents/music/music.js`](https://github.com/mozilla/firefox-voice/blob/master/extension/intents/music/music.js) in `music.move`.
9999

100100
### Matching an utterance to an intent
101101

@@ -138,38 +138,38 @@ To prepare a tab to do your custom stuff, run:
138138
```js
139139
async run(context) {
140140
const activeTab = await browserUtil.activeTab();
141-
await content.inject(activeTab.id, "intents/someName/contentScript.js");
141+
await content.inject(activeTab.id, "intents/someName/someScript.content.js");
142142
// Now the script, and a bunch of helpers are available
143143
const resp = await browser.tabs.sendMessage(activeTab.id, {type: "doSomething"});
144144
}
145145
```
146146

147-
`content.inject` will make sure the script is available and fully loaded, and will not re-load the script if called multiple times on the same tab. It also loads [`content/communicate.js`](../extension/content/communicate.js) and [`content/helpers.js`](../extension/content/helpers.js).
147+
`content.inject` will load the built script (scripts like these are packaged up into `someScript.bundle.js`). These scripts _must_ be named with `.content.js`.
148148

149-
You can use this pattern in your script (`contentScript.js` in this example):
149+
You can use this pattern in your script (`someScript.content.js` in this example):
150150

151151
```js
152-
(function() {
153-
communicate.register("doSomething", message => {
154-
// Do something, and return a value
155-
});
156-
})();
152+
import { registerHandler } from "../../communicate.js";
153+
154+
registerHandler("doSomething", message => {
155+
// Do something, and return a value
156+
});
157157
```
158158

159159
Or maybe:
160160

161161
```js
162-
(function() {
163-
class MyThing extends helpers.Runner {
164-
async action_doSomething(message) {
165-
const el = await this.waitForSelector(".some-element");
166-
...
167-
}
168-
};
169-
})();
170-
```
162+
import {Runner} from "../../content/helpers.js";
171163

172-
Note you _cannot_ use JavaScript modules in content scripts.
164+
class MyThing extends Runner {
165+
async action_doSomething(message) {
166+
const el = await this.waitForSelector(".some-element");
167+
...
168+
}
169+
}
170+
171+
MyThing.register();
172+
```
173173

174174
## Logging
175175

extension/background/content.js

Lines changed: 8 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,20 @@
1-
/* globals log */
2-
3-
const NO_RECEIVER_MESSAGE =
4-
"Could not establish connection. Receiving end does not exist";
5-
61
export async function inject(tabId, scripts) {
72
if (!tabId) {
83
throw new Error(`Invalid tabId: ${tabId}`);
94
}
105
if (typeof scripts === "string") {
116
scripts = [scripts];
127
}
13-
const scriptKey = scripts.join(",");
14-
let available = true;
15-
try {
16-
available = await browser.tabs.sendMessage(tabId, {
17-
type: "ping",
18-
scriptKey,
19-
});
20-
if (!available) {
21-
available = "some";
22-
}
23-
} catch (e) {
24-
available = false;
25-
if (String(e).includes(NO_RECEIVER_MESSAGE)) {
26-
// This is a normal error
27-
} else {
28-
log.error("Error sending message:", String(e));
29-
}
30-
}
31-
if (available === "some") {
32-
for (const script of scripts) {
33-
await browser.tabs.executeScript(tabId, {
34-
file: script,
35-
runAt: "document_idle",
36-
});
37-
}
38-
await browser.tabs.sendMessage(tabId, {
39-
type: "scriptsLoaded",
40-
scriptKey,
41-
});
42-
return;
8+
if (!scripts.filter(s => s.endsWith(".content.js")).length) {
9+
throw new Error(`Not a bundle script: ${scripts}`);
4310
}
44-
if (available) {
45-
return;
46-
}
47-
scripts = [
48-
"/buildSettings.js",
49-
"/log.js",
50-
"/content/helpers.js",
51-
"/content/communicate.js",
52-
]
53-
.concat(scripts)
54-
.concat(["/content/responder.js"]);
55-
56-
for (const script of scripts) {
11+
const bundleScripts = scripts.map(script =>
12+
script.replace(/\.content\.js$/, ".bundle.js")
13+
);
14+
const execScripts = ["/buildSettings.js", "/log.js"].concat(bundleScripts);
15+
for (const file of execScripts) {
5716
try {
58-
await browser.tabs.executeScript(tabId, { file: script });
17+
await browser.tabs.executeScript(tabId, { file });
5918
} catch (error) {
6019
if (error.message.includes("Missing host permission for the tab")) {
6120
const e = new Error("That does not work on this kind of page");
@@ -66,29 +25,4 @@ export async function inject(tabId, scripts) {
6625
}
6726
}
6827
}
69-
70-
await browser.tabs.sendMessage(tabId, {
71-
type: "scriptsLoaded",
72-
scriptKey,
73-
});
74-
}
75-
76-
export async function hasScript(tabId, scripts) {
77-
if (!tabId) {
78-
throw new Error(`Invalid tabId: ${tabId}`);
79-
}
80-
if (typeof scripts === "string") {
81-
scripts = [scripts];
82-
}
83-
const scriptKey = scripts.join(",");
84-
let available;
85-
try {
86-
available = await browser.tabs.sendMessage(tabId, {
87-
type: "ping",
88-
scriptKey,
89-
});
90-
} catch (e) {
91-
available = false;
92-
}
93-
return available;
9428
}

extension/background/entityTypes.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ for (const id in metadata.music) {
2121
}
2222
}
2323

24+
export const namedPages = [];
25+
26+
for (const id in metadata.name) {
27+
const item = metadata.name[id];
28+
for (const name of item.names) {
29+
namedPages.push(name);
30+
}
31+
}
32+
2433
export const entityTypes = convertEntities({
2534
serviceName: allServiceNames,
2635
musicServiceName: musicServiceNames,

extension/background/googleContentScript.js

Lines changed: 0 additions & 151 deletions
This file was deleted.

0 commit comments

Comments
 (0)