Keyboard Shortcuts for chrome extension can be seen in chrome://extensions/shortcuts but not working - google-chrome

This is a chrome extension which clears the input fields of the webpage. it works perfectly fine when I click at the extension.
I tried to give a keyboard shortcut to it. it was working at first but next day when I opened chrome extension was not there(maybe because I kept my extension in my chrome's profile folder at /home/user/.config/google-chrome/Profile 3/Extensions/). so chrome might have not recognised and removed it because it's not from store.
I added it again but this time keyboard shortcut was not working. I don't have any knowledge of developing extensions. I just looked up at the google.developer guides and created this.
// manifest.json
{
"name": "Reset Answers",
"description": "Resets checkboxes, radio button, Input Text!",
"version": "0.0.0.1",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"permissions": ["activeTab", "scripting"],
"action": {},
"commands": {
"_execute_action": {
"suggested_key": "Alt+C",
"description": "clears input fields"
}
},
"icons": {
"16": "/images/icon16.png",
"48": "/images/icon48.png",
"128": "/images/icon128.png"
}
}
// background.js
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: {tabId: tab.id},
func: clear,
});
});
function clear() {
var elements = document.getElementsByTagName("input");
for (let i = 0; i < elements.length; i++) {
if (elements[i].type == "text" || elements[i].type == "number") {
elements[i].value = "";
} else if (elements[i].type == "radio" || elements[i].type == "checkbox") {
elements[i].checked = false;
}
}
}
chrome.commands.onCommand.addListener((command) => {
});
I tried calling clear function inside that event listener function is also not working.
chrome://extension/shortcuts page shows the extension and the shortcut like this but its not working.
Alt+C is not being used for any other keyboard shortcut on my pc. What I am doing wrong here?

Certain operating system and Chrome shortcuts (e.g. window management) always take priority over Extension command shortcuts and can not be overwritten.
The following sample outputs to console.log when Ctrl+Shift+1 is entered.
manifest.json
{
"name": "hoge",
"version": "1.0",
"manifest_version": 3,
"commands": {
"command1": {
"suggested_key": "Ctrl+Shift+1",
"description": "hoge"
}
},
"background": {
"service_worker": "background.js"
}
}
background.js
chrome.commands.onCommand.addListener((c) => {
switch (c) {
case "command1":
console.log("command1");
break;
}
});

Related

Can `content_scripts` detect if a `command` is set?

My extension currently uses the [esc] key to perform an action.
This is done in the content-script, using addEventListener('keydown').
I'd like the user to be able to choose a different shortcut.
I've updated to Manifest V3, and added a new "commands" key, i.e.
{
...
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"content_scripts": [ {
"js": [ "screenshot.js" ],
"matches": [ "http://*/*", "https://*/*" ]
}],
"commands": {
"stop-animations": {
"description": "Stop Animations"
}
}
}
I've updated background.js to use chrome.commands.onCommand, and this works well.
But, how can I get my content-script to determine if the user has set their own shortcut?
Because I should not listen to the 'keydown' event to check if they have pressed the [esc] key.
I've tried using chrome.commands.getAll(), but this method is only available at install time.
A partial option would be to use something like browser.storage to set a simple boolean "custom-command-set" to true whenever onCommand is used, but I cannot think of a way to switch it off again if the user deletes the shortcut command (i.e. they want to go back to using the [esc] key).
At the moment I don't have a toolbar icon (action default_popup), or any other UI, and I'd prefer to not add one just to provide a custom way to set the shortcut.
Content scripts can't call chrome.commands.getAll() directly, so they need to send a message to the service worker. The SW calls chrome.commands.getAll() and sends the result back to the content script.
manifest.json
{
"manifest_version": 3,
"name": "chrome.commands.getAll",
"version": "1.0.0",
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"js": [ "content_script.js" ],
"matches": [ "*://*/*" ]
}
],
"commands": {
"test": {
"description": "Test"
}
},
"permissions": ["commands"]
}
background.js
function commands_on_command(command) {
console.log("on_command", command);
}
function runtime_on_message(message, sender, sendResponse) {
if (message == "get_all_commands") {
chrome.commands.getAll()
.then(commands => {
console.log("background.js", "runtime_on_message", commands);
sendResponse(commands);
});
return true; // https://developer.chrome.com/docs/extensions/mv3/messaging/#simple
}
else {
console.log("background.js", "runtime_on_message", "unknown command");
sendResponse("unknown command");
}
}
chrome.commands.onCommand.addListener(commands_on_command);
chrome.runtime.onMessage.addListener(runtime_on_message);
content_script.js
(async () => {
let response = await chrome.runtime.sendMessage("get_all_commands");
console.log("content_script.js", response);
})();

onInstalled opens blank new tab on mobile

I have a Chrome extension that I'm testing on mobile (Kiwi Browser). The below code snippet works fine on desktop but not on mobile:
background.js
chrome.runtime.onInstalled.addListener(function(details) {
if (details.reason == 'install') {
let install_window = window.open('https://www.google.com', '_blank');
install_window.opener = null;
}});
manifest.json
{
"app": {
"background": {
"scripts": ["background.js"]
}
},
"manifest_version": 2,
"name": "My App",
"version": "0"
}
What is the difference between desktop and mobile that would make this be the case?
From #wOxxOm in the comments:
Use the extensions API like chrome.tabs.create instead of window.open

chrome extension: Getting the source HTML of the current page on page load

I found this answer on how to grab the page source of current tab:
Getting the source HTML of the current page from chrome extension
However, this answer requires user to press the extension popup.
I would like to know how I can access the page source upon loading of page (without having to invoke the popup).
In my background.js I've tired this:
chrome.tabs.onUpdated.addListener(function (tabId , info) {
console.log(info)
chrome.tabs.executeScript(null, {
file: "getPagesSource.js"
}, function() {
if (chrome.runtime.lastError) {
message.innerText = 'There was an error injecting script : \n' + chrome.runtime.lastError.message;
}
});
});
but this results in the following error:
There was an error injecting script : Cannot access contents of the
page. Extension manifest must request permission to access the
respective host.
My manifest.js:
{
"name": "Getting Started Example",
"version": "1.0",
"description": "Build an Extension!",
"permissions": ["declarativeContent",
"https://www.example.com/*",
"storage",
"activeTab"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["content.js"]
}
],
"options_page": "options.html",
"manifest_version": 2,
"page_action": {
"default_popup": "popup.html",
"default_icon": {
"16": "images/get_started16.png",
"32": "images/get_started32.png",
"48": "images/get_started48.png",
"128": "images/get_started128.png"
}
},
"icons": {
"16": "images/get_started16.png",
"32": "images/get_started32.png",
"48": "images/get_started48.png",
"128": "images/get_started128.png"
}
}
I don't think the issue is really with permissions because I am able to get the page source from the popup.html (which is page_action script). But I am not able to get it via "background" or "content_scripts". Why is that and what is the proper way to accomplish this?
It is about the permissions.
Your example a bit insufficient, but as I can see you are using "activeTab" permission.
According to the activeTab docs, the extension will get access (e.g. sources) to current tab after any of these actions will be performed:
Executing a browser action
Executing a page action
Executing a context menu item
Executing a keyboard shortcut from the commands API
Accepting a suggestion from the omnibox API
That's why you can get sources after opening the popup.
In order to get access to tabs without those actions, you need to ask for the following permissions:
tabs
<all_urls>
Be noted, it allows you to run content-script on every tab, not only the active one.
Here is the simplest example:
manifest.json
{
"name": "Getting Started Example",
"version": "1.0",
"description": "Build an Extension!",
"permissions": ["tabs", "<all_urls>"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"manifest_version": 2
}
background.js
chrome.tabs.onUpdated.addListener(function (tabId, info) {
if(info.status === 'complete') {
chrome.tabs.executeScript({
code: "document.documentElement.innerHTML" // or 'file: "getPagesSource.js"'
}, function(result) {
if (chrome.runtime.lastError) {
console.error(chrome.runtime.lastError.message);
} else {
console.log(result)
}
});
}
});

chrome extension - update tab without changing url

I'm building a small chrome extension, that can open an page in a proxy
for example i'm opening www.mysite.com, and the clicking on my extension button, and it update the page to www.myproxy.net/q=www.mysite.com.
it's working like a charm, but i want to hide the chnage in the adress bar, so the url will remain the original site.
i made a few searches, but can't find out how to do such a thing.
can you please help me?
thanks
my manifest file
{
"name": "proxy",
"version": "1",
"browser_action": {
"default_icon" : "icon.png"
},
"permissions": ["tabs"],
"manifest_version": 2,
"background":{
"scripts": ["popup.js"]
},
"commands": {
"_execute_browser_action": {
"suggested_key": {
"default": "Ctrl+B",
"windows": "Ctrl+B"
}
}
}
}
my popup.js
chrome.browserAction.onClicked.addListener(function(activeTab){
chrome.tabs.query({active: true, currentWindow: true}, function(tab) {
var newURL = "http://myproxy.net/?q=" + tab[0].url;
chrome.tabs.update(undefined, {url: newURL});
});
});
AFAIK, this is not possible via Chrome API. The fact that you couldn't find searches means it's not doable yet. Unless maybe, you can write your own implementation.
You can use history.pushState or history.replaceState to do this. Refer to this article https://developer.mozilla.org/en-US/docs/Web/API/History_API
Example:
On the page of www.myproxy.net/q=www.mysite.com, add a script
history.pushState( {} , '', '/' );

Can't get Chrome Context Menu item to show on Chrome Extension

I have a Chrome extension that opens a KML/KMZ file in Google Maps. The extension is triggered when the user right-clicks a link to the KML document. But the context menu does not appear. It uses a background script. Here is the manifest.json:
{
"manifest_version": 2,
"name": "KML/KMZ Viewer",
"version": "1.0.0",
"description": "Can be used to view KML/KMZ Files.",
"icons": {
"19": "tiny.jpg",
"24": "icon.png",
"128": "image.png"
},
"permissions": [
"tabs",
"contextMenus",
"activeTab",
"background"
],
"background": {
"scripts": ["background.js"]
}
}
Here is the background.js:
// Set up context menu at install time.
chrome.runtime.onInstalled.addListener(function() {
menuCreate();
console.log('Issued function');
});
// add click event
chrome.contextMenus.onClicked.addListener(onClickHandler);
// The onClicked callback function.
function onClickHandler(info, tab) {
var url = info.selectionText;
openWin(url);
};
function openWin(kml) {
chrome.windows.create({"url":"http://www.nearby.org.uk/google/fake-kmlgadget.html? up_kml_url="+kml+"&up_view_mode=earth&up_lat=&up_lng=&up_zoom=&up_earth_2d_fallback=1&up_earth_fly_from_space=1&up_earth_show_nav_controls=1&up_earth_show_buildings=1&up_earth_show_terrain=1&up_earth_show_roads=1&up_earth_show_borders=1&up_earth_sphere=earth&up_maps_streetview=1&up_maps_default_type=hybrid"});
}
function menuCreate() {
chrome.contextMenus.create({"title": "Open KML/KMZ", "contexts": ["link"], "id": "kmlopen", "targetUrlPatterns": ["*.kml", "*.kmz"]});
console.log('Function ran');
}
Yet when I right-click on a link to a KML or KMZ file, the context menu doesn't show. According to the JavaScript console, the functions ran. This is what the console outputs when I run chrome.contextMenus.create({"title": "Open KML/KMZ", "contexts": ["link"], "id": "kmlopen", "targetUrlPatterns": ["*.kml", "*.kmz"]}); manually under _generated_background_page.html I get the kmlopen, the id of the menu item. What am I doing wrong? The openWin(/*some url*/); function works fine.
Wrong pattern.
The patterns follow the standard Match pattern format.
So you should use the patterns
"targetUrlPatterns": ["*://*/*.kml", "*://*/*.kmz"]
However, be mindful of query strings.