I cannot execute the function in the new pop-up I just created
chrome.windows.create({ url: "alert.html",type: 'popup', width: 200, height: 100}, function (newWindow) {
console.log(newWindow);
chrome.scripting.executeScript({
target: {tabId: newWindow.tabs[0].id},
func: () => {
console.log('hello world');
}
});
});
alert.html is a file in my folder. The error message given is
Uncaught (in promise) Error: Cannot access contents of url "chrome-extension://{extension_id}/alert.html". Extension manifest must request permission to access this host.
I saw this issue was mention here comment #19. But later they said the issue has been fixed... around Feb 2022. But I have the latest chrome (
Version 104.0.5112.79 (Official Build) (x86_64)) so I don't know why this is still occurs.
Please help, thanks!
Related
All I'm trying to do here is to be able fetch paypal_api_key from backend api something like:
app.get("/api/keys/paypal", (req, res) => {
res.send(process.env.PAYPAL_CLIENT_ID || "sb");
});
frontend side:
const loadPaypalScript = async () => {
const { data: clientId } = await axios.get("/api/keys/paypal", {
headers: { authorization: `Bearer ${userInfo.token}` },
});
paypalDispatch({
type: "resetOptions",
value: {
"client-id": clientId,
currency: "GBP",
},
});
paypalDispatch({ type: "setLoadingStatus", value: "pending" });
};
loadPaypalScript();
ERROR:
Uncaught Error: Attempted to load sdk version 5.0.343 on page, but window.paypal at version undefined already loaded.
To load this sdk alongside the existing version, please specify a different namespace in the script tag, e.g. <script src="https://www.paypal.com/sdk/js?client-id=CLIENT_ID" data-namespace="paypal_sdk"></script>, then use the paypal_sdk namespace in place of paypal in your code.
at VM827 js:2
at Module.<anonymous> (VM827 js:2)
at t (VM827 js:2)
at VM827 js:2
at VM827 js:2
I've tried this
<script src="https://www.paypal.com/sdk/js?client-id=***"></script>
it works but I'm not interested in passing my api key in plain sight like that
The Client ID is and must be public information, it's required for the script to load. Fetching it asynchronously after page load and using it to load the script dynamically does not in any way hide it; it will be in "plain sight" the moment the browser makes its request and also the moment the resource is loaded. So if that's the reason you're loading the script asynchronously, it does not make any sense; you are accomplishing nothing and should just do what works, ether putting the script tag in your page as HTML or using the official react-paypal-js.
In any case, the cause of your error is you are doing something that loads the SDK more than once. You need to ensure it's only loaded once. (for the rare use case that requires multiple SDKs concurrently, data-namespace is available but this is not your case)
I am trying to integrate the credential manager API into my extension so I can save the API credentials using it but am having issues.
Just for testing purposes, I just tried saving the credentials from the popup (Where the user login happens) and when I tried that I got an error saying "NotSupportedError: The user agent does not support public key credentials." I did some googling but didn't find what I was looking for. I thought it might have something to do with the popup so I tried doing the same through the background script but it can't access the window object so that didn't work.
I haven't yet tried doing this though a content script which I would imagine would work but ideally I'd prefer to just store it when the user logs in and then just call it as I need it.
Here is the basic code I'm using for testing that I grabbed from the MDN site;
if ("PasswordCredential" in window) {
let cmAPICredential = new PasswordCredential({
id: "extension",
name: uname,
password: pwd
});
navigator.credentials.store(cmAPICredential).then(() => {
if (isDebugMode) {
chrome.runtime.sendMessage({ message: "debug_log", str: `**LOGIN DEBUGGING** | Credentials stored in the user agent's credential manager.`, cpage: "main.js" }, function(response) {});
}
}, (err) => {
if (isDebugMode) {
chrome.runtime.sendMessage({ message: "debug_log", str: `**LOGIN DEBUGGING** | Error while storing the credential: ${err}`, cpage: "main.js" }, function(response) {});
}
});
} else {
if (isDebugMode) {
chrome.runtime.sendMessage({ message: "debug_log", str: `**LOGIN DEBUGGING** | Password credential isn't supported in this browser`, cpage: "main.js" }, function(response) {});
}
}
Is there any way that I can do what I am attempting? The only thing I really want to secure is the password and this seems to be the only good way to do it through a chrome extension.
Based on #wOxxOm response and some other research, it looks like I can't use the credential management API with chrome extensions.
So the answer to my question is you can't.
I would like to show an alert on Chrome's error page(see example at the bottom) when Chrome encounters a specific type of error for a specific url/domain.
I tried the below:
chrome.webNavigation.onErrorOccurred.addListener(details => {
if (
details.error === "net::ERR_BLOCKED_BY_CLIENT" &&
details.url.includes("ycombinator.com")
) {
chrome.scripting.executeScript(
{
target: { tabId: details.tabId },
files: ["alert.js"],
},
() => console.log("script executed")
)
}
})
but it throws an error:
Unchecked runtime.lastError: Cannot access contents of url "chrome-error://chromewebdata/". Extension manifest must request permission to access this host.
alert.js content
const blocked = () => alert('This website is blocked temporarily');
blocked()
In my manifest(v3), I have webNavigation, scripting and tabs in permissions and ["http:///", "https:///"] in host_permissions.
I tried adding "chrome-error://*/" to host_permissions but that didn't fix the error.
Example error page:
I've built a Chrome Extension (pop-up) and one of the primary functions is opening different web pages when the user clicks on a link. Sometimes I want to focus on specific text on the new page so I'm trying to use the "scroll to text fragment" feature through my extension.
Unfortunately, when the page loads, this feature (scroll to text) fails. I have tested the exact same link manually and it works fine, but when I inject this link into the browser through my extension, nothing happens except the page loading as normal.
Here are a few more details that might help:
The problem I'm having is using Chrome.tabs.update() which is triggered by a user clicking a link in my popup
We are using manifest v2 not v3
The exact command from the popup javascript is (not tab id as it defaults to current tab):
chrome.tabs.update({ url: "http://example.com/#:~:text=example", })
In the manifest, we do not have the "tabs" permission.
Is there a special permission needed to use this feature in my extension? Is there something I need to do in my extension code to make this work as expected? I'm at a loss for next steps.
This is the exact feature I'm referring to: https://chromestatus.com/feature/4733392803332096
And here's an example of the feature in action:
https://chromestatus.com/feature/4733392803332096#:~:text=Motivation-,Navigating%20to%20a%20URL,-today%20will%20load
Any help would be greatly appreciated. Thank you.
There's no special permission so apparently it's a bug in Chrome: crbug.com/1241508
A simple workaround is to use chrome.tabs.create and close the original tab, but it flickers in the tab strip and loses the tab's back/forward history, sessionStorage, and so on.
function navigate(url) {
chrome.tabs.query({active: true, currentWindow: true}, ([tab]) => {
chrome.tabs.remove(tab.id);
chrome.tabs.create({ url, index: tab.index });
});
}
Another workaround is to set the hash part of the URL in the content script, but it requires host permissions for the navigated site in manifest.json like *://example.com/
async function navigate(url) {
if (await setUrlInContentScript(url)) {
return true;
}
const [base, hash] = url.split('#');
await onTabReceivedUrl(await new Promise(resolve => {
chrome.tabs.update({ url: base }, resolve);
}));
return setUrlInContentScript('#' + hash, 'hash');
function setUrlInContentScript(url, part = 'href') {
return new Promise(resolve => {
chrome.tabs.executeScript({
code: `location.${part}=${JSON.stringify(url)}`,
runAt: 'document_start',
}, () => resolve(!chrome.runtime.lastError));
});
}
function onTabReceivedUrl(tab) {
return new Promise(resolve => {
chrome.tabs.onUpdated.addListener(function onUpdated(tabId, info) {
if (tabId === tab.id && info.url) {
chrome.tabs.onUpdated.removeListener(onUpdated);
resolve();
}
});
});
}
}
In my case I discovered, that one of the characters ~ was encoded. You need the real characters to get Scroll to Text working.
Background page:
chrome.tabs.create({ url: 'http://google.com' }, tab => {
chrome.tabs.executeScript({ code: '2+2;' }, (r) => {
console.log(`url: ${tab.url}, result: ${r[0]}`);
});
});
I open background page to see output:
url: http://google.com/, result: 4
Looks good, but now I press F5 or Ctrl+F5:
Unchecked runtime.lastError while running tabs.executeScript: Cannot access contents of url "chrome-devtools://devtools/bundled/inspector.html?&remoteBase=https://chrom…om/serve_file/#e8926f681fbb840b4f389e7e692343d4505722ce/&dockSide=undocked". Extension manifest must request permission to access this host.
at Object.callback (chrome-extension://laaoiaaacchfpefjhklpmnfjbeamjfli/background.js:2:15)
In 'manifest.json' I have <all_urls> permission.
When the first parameter, tabId, of chrome.tabs.executeScript is omitted the code is injected into the active tab of the active window. In your case the active window is the devtools debugger of the background page and it doesn't allow injection of code.
Specify tabId explicitly: chrome.tabs.executeScript(tab.id, { code: .......