diff options
Diffstat (limited to 'src/webview/recipe.js')
-rw-r--r-- | src/webview/recipe.js | 132 |
1 files changed, 73 insertions, 59 deletions
diff --git a/src/webview/recipe.js b/src/webview/recipe.js index 8da45864b..d143675dc 100644 --- a/src/webview/recipe.js +++ b/src/webview/recipe.js | |||
@@ -1,11 +1,9 @@ | |||
1 | /* eslint-disable import/first */ | 1 | /* eslint-disable import/first */ |
2 | import { ipcRenderer } from 'electron'; | 2 | import { contextBridge, ipcRenderer } from 'electron'; |
3 | import { getCurrentWebContents } from '@electron/remote'; | ||
4 | import path from 'path'; | 3 | import path from 'path'; |
5 | import { autorun, computed, observable } from 'mobx'; | 4 | import { autorun, computed, observable } from 'mobx'; |
6 | import fs from 'fs-extra'; | 5 | import fs from 'fs-extra'; |
7 | import { debounce } from 'lodash'; | 6 | import { debounce } from 'lodash'; |
8 | import { FindInPage } from 'electron-find'; | ||
9 | 7 | ||
10 | // For some services darkreader tries to use the chrome extension message API | 8 | // For some services darkreader tries to use the chrome extension message API |
11 | // This will cause the service to fail loading | 9 | // This will cause the service to fail loading |
@@ -23,16 +21,81 @@ import customDarkModeCss from './darkmode/custom'; | |||
23 | import RecipeWebview from './lib/RecipeWebview'; | 21 | import RecipeWebview from './lib/RecipeWebview'; |
24 | import Userscript from './lib/Userscript'; | 22 | import Userscript from './lib/Userscript'; |
25 | 23 | ||
26 | import { switchDict, getSpellcheckerLocaleByFuzzyIdentifier } from './spellchecker'; | 24 | import { BadgeHandler } from './badge'; |
27 | import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode'; | ||
28 | import contextMenu from './contextMenu'; | 25 | import contextMenu from './contextMenu'; |
29 | import './notifications'; | 26 | import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode'; |
30 | import { screenShareCss } from './screenshare'; | 27 | import FindInPage from './find'; |
28 | import { NotificationsHandler, notificationsClassDefinition } from './notifications'; | ||
29 | import { getDisplayMediaSelector, screenShareCss, screenShareJs } from './screenshare'; | ||
30 | import { switchDict, getSpellcheckerLocaleByFuzzyIdentifier } from './spellchecker'; | ||
31 | 31 | ||
32 | import { DEFAULT_APP_SETTINGS, isDevMode } from '../environment'; | 32 | import { DEFAULT_APP_SETTINGS } from '../environment'; |
33 | 33 | ||
34 | const debug = require('debug')('Ferdi:Plugin'); | 34 | const debug = require('debug')('Ferdi:Plugin'); |
35 | 35 | ||
36 | const badgeHandler = new BadgeHandler(); | ||
37 | |||
38 | const notificationsHandler = new NotificationsHandler(); | ||
39 | |||
40 | // Patching window.open | ||
41 | const originalWindowOpen = window.open; | ||
42 | |||
43 | window.open = (url, frameName, features) => { | ||
44 | debug('window.open', url, frameName, features); | ||
45 | if (!url) { | ||
46 | // The service hasn't yet supplied a URL (as used in Skype). | ||
47 | // Return a new dummy window object and wait for the service to change the properties | ||
48 | const newWindow = { | ||
49 | location: { | ||
50 | href: '', | ||
51 | }, | ||
52 | }; | ||
53 | |||
54 | const checkInterval = setInterval(() => { | ||
55 | // Has the service changed the URL yet? | ||
56 | if (newWindow.location.href !== '') { | ||
57 | if (features) { | ||
58 | originalWindowOpen(newWindow.location.href, frameName, features); | ||
59 | } else { | ||
60 | // Open the new URL | ||
61 | ipcRenderer.sendToHost('new-window', newWindow.location.href); | ||
62 | } | ||
63 | clearInterval(checkInterval); | ||
64 | } | ||
65 | }, 0); | ||
66 | |||
67 | setTimeout(() => { | ||
68 | // Stop checking for location changes after 1 second | ||
69 | clearInterval(checkInterval); | ||
70 | }, 1000); | ||
71 | |||
72 | return newWindow; | ||
73 | } | ||
74 | |||
75 | // We need to differentiate if the link should be opened in a popup or in the systems default browser | ||
76 | if (!frameName && !features && typeof features !== 'string') { | ||
77 | return ipcRenderer.sendToHost('new-window', url); | ||
78 | } | ||
79 | |||
80 | if (url) { | ||
81 | return originalWindowOpen(url, frameName, features); | ||
82 | } | ||
83 | }; | ||
84 | |||
85 | // We can't override APIs here, so we first expose functions via window.ferdi, | ||
86 | // then overwrite the corresponding field of the window object by injected JS. | ||
87 | contextBridge.exposeInMainWorld('ferdi', { | ||
88 | open: window.open, | ||
89 | setBadge: (direct, indirect) => badgeHandler.setBadge(direct || 0, indirect || 0), | ||
90 | displayNotification: (title, options) => notificationsHandler.displayNotification(title, options), | ||
91 | getDisplayMediaSelector, | ||
92 | }); | ||
93 | |||
94 | ipcRenderer.sendToHost('inject-js-unsafe', | ||
95 | 'window.open = window.ferdi.open;', | ||
96 | notificationsClassDefinition, | ||
97 | screenShareJs); | ||
98 | |||
36 | class RecipeController { | 99 | class RecipeController { |
37 | @observable settings = { | 100 | @observable settings = { |
38 | overrideSpellcheckerLanguage: false, | 101 | overrideSpellcheckerLanguage: false, |
@@ -97,7 +160,7 @@ class RecipeController { | |||
97 | autorun(() => this.update()); | 160 | autorun(() => this.update()); |
98 | 161 | ||
99 | document.addEventListener('DOMContentLoaded', () => { | 162 | document.addEventListener('DOMContentLoaded', () => { |
100 | this.findInPage = new FindInPage(getCurrentWebContents(), { | 163 | this.findInPage = new FindInPage({ |
101 | inputFocusColor: '#CE9FFC', | 164 | inputFocusColor: '#CE9FFC', |
102 | textColor: '#212121', | 165 | textColor: '#212121', |
103 | }); | 166 | }); |
@@ -111,7 +174,7 @@ class RecipeController { | |||
111 | // Delete module from cache | 174 | // Delete module from cache |
112 | delete require.cache[require.resolve(modulePath)]; | 175 | delete require.cache[require.resolve(modulePath)]; |
113 | try { | 176 | try { |
114 | this.recipe = new RecipeWebview(); | 177 | this.recipe = new RecipeWebview(badgeHandler, notificationsHandler); |
115 | // eslint-disable-next-line | 178 | // eslint-disable-next-line |
116 | require(modulePath)(this.recipe, {...config, recipe,}); | 179 | require(modulePath)(this.recipe, {...config, recipe,}); |
117 | debug('Initialize Recipe', config, recipe); | 180 | debug('Initialize Recipe', config, recipe); |
@@ -327,52 +390,3 @@ class RecipeController { | |||
327 | /* eslint-disable no-new */ | 390 | /* eslint-disable no-new */ |
328 | new RecipeController(); | 391 | new RecipeController(); |
329 | /* eslint-enable no-new */ | 392 | /* eslint-enable no-new */ |
330 | |||
331 | // Patching window.open | ||
332 | const originalWindowOpen = window.open; | ||
333 | |||
334 | window.open = (url, frameName, features) => { | ||
335 | debug('window.open', url, frameName, features); | ||
336 | if (!url) { | ||
337 | // The service hasn't yet supplied a URL (as used in Skype). | ||
338 | // Return a new dummy window object and wait for the service to change the properties | ||
339 | const newWindow = { | ||
340 | location: { | ||
341 | href: '', | ||
342 | }, | ||
343 | }; | ||
344 | |||
345 | const checkInterval = setInterval(() => { | ||
346 | // Has the service changed the URL yet? | ||
347 | if (newWindow.location.href !== '') { | ||
348 | if (features) { | ||
349 | originalWindowOpen(newWindow.location.href, frameName, features); | ||
350 | } else { | ||
351 | // Open the new URL | ||
352 | ipcRenderer.sendToHost('new-window', newWindow.location.href); | ||
353 | } | ||
354 | clearInterval(checkInterval); | ||
355 | } | ||
356 | }, 0); | ||
357 | |||
358 | setTimeout(() => { | ||
359 | // Stop checking for location changes after 1 second | ||
360 | clearInterval(checkInterval); | ||
361 | }, 1000); | ||
362 | |||
363 | return newWindow; | ||
364 | } | ||
365 | |||
366 | // We need to differentiate if the link should be opened in a popup or in the systems default browser | ||
367 | if (!frameName && !features && typeof features !== 'string') { | ||
368 | return ipcRenderer.sendToHost('new-window', url); | ||
369 | } | ||
370 | |||
371 | if (url) { | ||
372 | return originalWindowOpen(url, frameName, features); | ||
373 | } | ||
374 | }; | ||
375 | |||
376 | if (isDevMode) { | ||
377 | window.log = console.log; | ||
378 | } | ||