Skip to content

Commit

Permalink
Merge pull request #1337 from reneaaron/feature/capture-links-in-dyna…
Browse files Browse the repository at this point in the history
…mic-content

Capture links in dynamic content
  • Loading branch information
bumi committed Sep 6, 2022
2 parents 897d502 + 8f7b664 commit a1db6f3
Showing 1 changed file with 91 additions and 80 deletions.
171 changes: 91 additions & 80 deletions src/extension/inpage-script/index.js
Expand Up @@ -13,103 +13,114 @@ if (document) {
window.dispatchEvent(readyEvent);

// Intercept any `lightning:` requests
window.addEventListener("click", (ev) => {
const target = ev.target;
if (!target || !target.closest) {
return;
}
const lightningLink = target.closest('[href^="lightning:" i]');
const lnurlLink = target.closest('[href^="lnurl" i]');
const bitcoinLinkWithLighting = target.closest('[href*="lightning=ln" i]'); // links with a lightning parameter and a value that starts with ln: payment requests (lnbc...) or lnurl (lnurl*)
let href;
let paymentRequest;
let lnurl;
let link; // used to dispatch a succcess event
window.addEventListener(
"click",
(ev) => {
// Use composedPath() for detecting links inside a Shadow DOM
// https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath
const target = ev.composedPath()[0];

if (!lightningLink && !bitcoinLinkWithLighting && !lnurlLink) {
return;
}
ev.preventDefault();

if (lightningLink) {
href = lightningLink.getAttribute("href").toLowerCase();
paymentRequest = href.replace("lightning:", "");
link = lightningLink;
} else if (bitcoinLinkWithLighting) {
href = bitcoinLinkWithLighting.getAttribute("href");
link = bitcoinLinkWithLighting;
const url = new URL(href);
const query = new URLSearchParams(url.search);
paymentRequest = query.get("lightning");
} else if (lnurlLink) {
href = lnurlLink.getAttribute("href").toLowerCase();
link = lnurlLink;
lnurl = href.replace(/^lnurl[pwc]:/i, "");
}
if (!target || !target.closest) {
return;
}
const lightningLink = target.closest('[href^="lightning:" i]');
const lnurlLink = target.closest('[href^="lnurl" i]');
const bitcoinLinkWithLighting = target.closest(
'[href*="lightning=ln" i]'
); // links with a lightning parameter and a value that starts with ln: payment requests (lnbc...) or lnurl (lnurl*)
let href;
let paymentRequest;
let lnurl;
let link; // used to dispatch a succcess event

// if we did not find any paymentRequest and no LNURL we give up and return
if (!paymentRequest && !lnurl) {
return;
}
if (!lightningLink && !bitcoinLinkWithLighting && !lnurlLink) {
return;
}
ev.preventDefault();

// it could be it is a LNURL behind a lightning: link
if (paymentRequest && paymentRequest.startsWith("lnurl")) {
lnurl = paymentRequest.replace(/^lnurl[pwc]:/i, ""); // replace potential scheme. the different lnurl types are handled in the lnurl action (by checking the type in the LNURL response)
}
// it could be a lightning address behind a lightning: link
if (paymentRequest && paymentRequest.match(/(\S+@\S+)/)) {
lnurl = paymentRequest.match(/(\S+@\S+)/)[1];
}
if (lightningLink) {
href = lightningLink.getAttribute("href").toLowerCase();
paymentRequest = href.replace("lightning:", "");
link = lightningLink;
} else if (bitcoinLinkWithLighting) {
href = bitcoinLinkWithLighting.getAttribute("href");
link = bitcoinLinkWithLighting;
const url = new URL(href);
const query = new URLSearchParams(url.search);
paymentRequest = query.get("lightning");
} else if (lnurlLink) {
href = lnurlLink.getAttribute("href").toLowerCase();
link = lnurlLink;
lnurl = href.replace(/^lnurl[pwc]:/i, "");
}

window.webln.enable().then((response) => {
if (!response.enabled) {
// if we did not find any paymentRequest and no LNURL we give up and return
if (!paymentRequest && !lnurl) {
return;
}

if (lnurl) {
// it could be it is a LNURL behind a lightning: link
if (paymentRequest && paymentRequest.startsWith("lnurl")) {
lnurl = paymentRequest.replace(/^lnurl[pwc]:/i, ""); // replace potential scheme. the different lnurl types are handled in the lnurl action (by checking the type in the LNURL response)
}
// it could be a lightning address behind a lightning: link
if (paymentRequest && paymentRequest.match(/(\S+@\S+)/)) {
lnurl = paymentRequest.match(/(\S+@\S+)/)[1];
}

window.webln.enable().then((response) => {
if (!response.enabled) {
return;
}

if (lnurl) {
return window.webln
.lnurl(lnurl)
.catch((e) => {
console.error(e);
if (
![ABORT_PROMPT_ERROR, USER_REJECTED_ERROR].includes(e.message)
) {
alert(`Error: ${e.message}`);
}
})
.then((response) => {
const responseEvent = new CustomEvent("lightning:success", {
bubbles: true,
detail: {
lnurl,
response,
},
});
link.dispatchEvent(responseEvent);
});
}

return window.webln
.lnurl(lnurl)
.catch((e) => {
console.error(e);
if (
![ABORT_PROMPT_ERROR, USER_REJECTED_ERROR].includes(e.message)
) {
alert(`Error: ${e.message}`);
}
})
.sendPayment(paymentRequest)
.then((response) => {
console.info(response);
const responseEvent = new CustomEvent("lightning:success", {
bubbles: true,
detail: {
lnurl,
paymentRequest,
response,
},
});
link.dispatchEvent(responseEvent);
})
.catch((e) => {
console.error(e);
if (
![ABORT_PROMPT_ERROR, USER_REJECTED_ERROR].includes(e.message)
) {
alert(`Error: ${e.message}`);
}
});
}

return window.webln
.sendPayment(paymentRequest)
.then((response) => {
console.info(response);
const responseEvent = new CustomEvent("lightning:success", {
bubbles: true,
detail: {
paymentRequest,
response,
},
});
link.dispatchEvent(responseEvent);
})
.catch((e) => {
console.error(e);
if (![ABORT_PROMPT_ERROR, USER_REJECTED_ERROR].includes(e.message)) {
alert(`Error: ${e.message}`);
}
});
});
});
});
},
{ capture: true }
);
} else {
console.warn("Failed to inject WebLN provider");
}

0 comments on commit a1db6f3

Please sign in to comment.