-
Notifications
You must be signed in to change notification settings - Fork 197
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: fast provider injection 🔥 (#2691)
* feat: add webln * fix: all_frames property name * feat: use service worker instead of manifest * feat: inject content scripts on start * feat: inline and inject provider in mv2 via custom webpack plugin intercept build files add provider during build time and inject signed-off-by: pavan joshi <[email protected]> * chore: comment/refactor * fix: use helper function * fix: move injection from onend to onstart * fix: remove injectScripts, separate WebLN from index * fix: add inpage script registration for other providers * fix: added todo * fix: remove web accessible resources * fix: separate index from webln * fix: rename scripts, merge manifest content script definition * feat: rewrite webpack plugin inject all the provider via single variable solve plugin error, while inlinining all the scripts in single variable signed-off-by: pavan joshi <[email protected]> * feat: add webln * fix: all_frames property name * feat: use service worker instead of manifest * feat: inject content scripts on start * feat: inline and inject provider in mv2 via custom webpack plugin intercept build files add provider during build time and inject signed-off-by: pavan joshi <[email protected]> * chore: comment/refactor * fix: use helper function * fix: move injection from onend to onstart * fix: remove injectScripts, separate WebLN from index * fix: add inpage script registration for other providers * fix: added todo * fix: remove web accessible resources * fix: separate index from webln * fix: rename scripts, merge manifest content script definition * feat: merge all the providers into single script * chore: move function into separate file * chore: place comment * feat: do brower side checks in the inpage script itself do browser side checks + extension side cheks such as blocklist in the provider's content script signed-off-by: pavan joshi <[email protected]> * feat: refactor clickhandlers in separate function remove document check in inpage index signed-off-by: pavan joshi <[email protected]> * chore: change plugin variable names * feat: be defensive about window and doctype are available or not * fix: add fallback injection for blocked inline scripts --------- Co-authored-by: pavanjoshi914 <[email protected]> Co-authored-by: Pavan Joshi <[email protected]>
- Loading branch information
1 parent
50558e2
commit f98edca
Showing
21 changed files
with
183 additions
and
161 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
const { sources } = require("webpack"); | ||
|
||
const PLUGIN_NAME = "ProviderInjectionPlugin"; | ||
const PROVIDER_SCRIPT_FILENAME = "js/inpageScript.bundle.js"; | ||
const CONTENT_SCRIPT_FILENAME = "js/contentScriptOnStart.bundle.js"; | ||
|
||
// plugin to intercept webln bundle during built times and inline/attach provider to make it available immediately | ||
// works only on MV2 and designed specifically for firefox as main world execution is not supported for firefox | ||
class ProviderInjectionPlugin { | ||
apply(compiler) { | ||
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => { | ||
compilation.hooks.processAssets.tap( | ||
{ | ||
name: PLUGIN_NAME, | ||
stage: compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE, | ||
}, | ||
(assets) => { | ||
let providerScriptSource = | ||
assets[PROVIDER_SCRIPT_FILENAME].source().toString(); | ||
providerScriptSource = JSON.stringify(providerScriptSource); | ||
let contentScriptSource = | ||
assets[CONTENT_SCRIPT_FILENAME].source().toString(); | ||
|
||
assets[CONTENT_SCRIPT_FILENAME] = new sources.RawSource( | ||
contentScriptSource.replace( | ||
'"@@@WINDOW_PROVIDER@@@"', | ||
providerScriptSource | ||
) | ||
); | ||
} | ||
); | ||
}); | ||
} | ||
} | ||
|
||
module.exports = ProviderInjectionPlugin; |
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,15 @@ | ||
export const registerInPageContentScript = async () => { | ||
try { | ||
await chrome.scripting.registerContentScripts([ | ||
{ | ||
id: "inpageScript", | ||
matches: ["file://*/*", "http://*/*", "https://*/*"], | ||
js: ["js/inpageScript.bundle.js"], | ||
runAt: "document_start", | ||
world: "MAIN", | ||
}, | ||
]); | ||
} catch (err) { | ||
console.warn(`Dropped attempt to register inpage content script. ${err}`); | ||
} | ||
}; |
File renamed without changes.
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 |
---|---|---|
@@ -1,20 +1,37 @@ | ||
// load the inpage scripts | ||
// only an inpage script gets access to the document | ||
|
||
// and the document can interact with the extension through the inpage script | ||
export default function injectScript(url: string) { | ||
export function injectScript(script: string) { | ||
try { | ||
if (!document) throw new Error("No document"); | ||
const container = document.head || document.documentElement; | ||
if (!container) throw new Error("No container element"); | ||
const scriptEl = document.createElement("script"); | ||
scriptEl.setAttribute("async", "false"); | ||
scriptEl.setAttribute("type", "text/javascript"); | ||
scriptEl.setAttribute("src", url); | ||
scriptEl.textContent = script; | ||
container.insertBefore(scriptEl, container.children[0]); | ||
scriptEl.onload = () => { | ||
container.removeChild(scriptEl); | ||
}; | ||
container.removeChild(scriptEl); | ||
} catch (err) { | ||
console.error("injection failed", err); | ||
console.error("Alby: provider injection failed", err); | ||
} | ||
} | ||
|
||
export function injectScriptByUrl(url: string) { | ||
try { | ||
if (!document) throw new Error("No document"); | ||
const container = document.head || document.documentElement; | ||
if (!container) throw new Error("No container element"); | ||
const scriptEl = document.createElement("script"); | ||
scriptEl.setAttribute("async", "false"); | ||
scriptEl.setAttribute("type", "text/javascript"); | ||
scriptEl.src = url; | ||
container.insertBefore(scriptEl, container.children[0]); | ||
container.removeChild(scriptEl); | ||
} catch (err) { | ||
console.error("Alby: provider injection failed", err); | ||
} | ||
} | ||
|
||
export default { injectScript, injectScriptByUrl }; |
File renamed without changes.
File renamed without changes.
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
File renamed without changes.
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 was deleted.
Oops, something went wrong.
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 was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
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,13 @@ | ||
import { | ||
doctypeCheck, | ||
documentElementCheck, | ||
suffixCheck, | ||
} from "../shouldInjectBrowserChecks"; | ||
export default function shouldInjectInpage() { | ||
const isHTML = doctypeCheck(); | ||
const noProhibitedType = suffixCheck(); | ||
const hasDocumentElement = documentElementCheck(); | ||
const injectedBefore = window.webln !== undefined; | ||
|
||
return isHTML && noProhibitedType && hasDocumentElement && !injectedBefore; | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
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,33 @@ | ||
// Checks the doctype of the current document if it exists | ||
export function doctypeCheck() { | ||
if (window && window.document && window.document.doctype) { | ||
return window.document.doctype.name === "html"; | ||
} else { | ||
return true; | ||
} | ||
} | ||
|
||
// Returns whether or not the extension (suffix) of the current document is prohibited | ||
export function suffixCheck() { | ||
const prohibitedTypes = [/\.xml$/, /\.pdf$/]; | ||
const currentUrl = window.location.pathname; | ||
for (const type of prohibitedTypes) { | ||
if (type.test(currentUrl)) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
// Checks the documentElement of the current document | ||
export function documentElementCheck() { | ||
// todo: correct? | ||
if (!document || !document.documentElement) { | ||
return false; | ||
} | ||
const docNode = document.documentElement.nodeName; | ||
if (docNode) { | ||
return docNode.toLowerCase() === "html"; | ||
} | ||
return true; | ||
} |
Oops, something went wrong.