Chrome extension with declarativeContent.RequestContentScript - javascript

I am trying to make a Chrome extension, which will monitor GMail and do something when user starts to write a message. After some study of examples and documentation I have figured out that I should do it with declarativeContent, which reacts on page change.
This is what I have done by now.
manifest.json:
{
"manifest_version": 2,
"name": "Gmail helper",
"version": "0.1",
"permissions": [ "declarativeContent" ],
"background": {
"scripts": ["background.js"],
"persistent": false
}
}
background.js:
chrome.runtime.onInstalled.addListener (function (details) {
chrome.declarativeContent.onPageChanged.removeRules (undefined, function () {
chrome.declarativeContent.onPageChanged.addRules ([{
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostEquals: 'mail.google.com', schemes: ['https'] },
css: ["div"]
// css: ["div[aria-label='Message Body']"]
})
],
actions: [ new chrome.declarativeContent.RequestContentScript({js: ["content.js"]}) ]
}]);
});
});
content.js:
alert ("Test");
My plan was to declare a content script that would trigger on page changes in GMail. I have added a declarative rule, which has pageURL, css and actions defined. According to my understanding content.js should be executed when pageUrl and css content match. However, content.js is not executed.
What am I doing wrong?
Thanks.

Running a content script on a site requires permissions for the site, which isn't stated explicitly in the documentation of declarativeContent API, but is deduced by the lack of "This action can be used without host permissions" note, which is present in other actions. The purpose of declarativeContent API is to install extensions from the WebStore without any permission confirmation warning so naturally this API can't grant you access to mail.google.com unless you add it explicitly in your manifest:
"permissions": ["declarativeContent", "https://mail.google.com/"]

From description of your task it looks like you don't need declarativeContent.
You need to add a content script to page if GMail page is open and in content script you need to add a listener to message editor DOM element (or whatever another element you need to track).
Assuming that you know how to do the second, to add content script to GMail page you need to add the following into manifest:
"content_scripts": [
{
"matches": [
"https://mail.google.com/*"
],
"js": ["content.js"]
}
You also don't need background script and permissions in this case.
Note:
Although you don't need to specify permissions, your extension will require to ask them from the user.
During installation, Chrome will warn the user that your extension will have access to all user data on the page to make the user able to cancel installation if he or she does not agree.

In the document description, RequestContentScript is experimental, but it is not. In my test, Chrome version >= 60 is available, but allFrames does not seem to work.
Before using "RequestContentScript", you need to declare host permissions in "permissions".
https://developer.chrome.com/extensions/declarativeContent#type-RequestContentScript

Related

Content script not injected in mail.google.com/tasks/canvas recently

I'm writing a chrome extension that uses content script to make Google tasks web UI look a little better. The extension used to work fine, but it didn't work anymore starting from the recent 1~2 days.
After investigation, it seems that content script does not execute in mail.google.com domain. To verify this, I changed manifest to match all web pages:
manifest.json:
{
"manifest_version": 2,
"name": "Tasks",
"short_name": "Tasks",
"description": "Use Google Tasks in a much nicer way.",
"version": "0.0.2",
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["js/script.js"]
}
]
}
js/scipt.js
alert('Content script is alerting.');
With this change, I can see chrome pop up an alert window when I visit pages like https://www.google.com/, https://stackoverflow.com and etc, but NOT https://mail.google.com/tasks/canvas, OR https://mail.google.com/mail.
Is there anything on mail.google.com that prevents content script from executing? How can I fix this? Thanks!

How to get content_scripts to execute in file:/// URLs in a Chrome extension

I can't seem to make this work no matter what I do. Let me demonstrate with a very simple example extension. Here is the manifest.json:
{
"manifest_version": 2,
"name": "Sample Of Content Script",
"description": "Changes the background of a page pink",
"version": "1.0",
"content_scripts": [
{
"matches": [ "<all_urls>" ],
"js": [ "changer.js" ]
}
],
"permissions": [
"webNavigation"
],
"background": {
"scripts": [ "background.js" ]
}
}
Notice that my content_scripts entry matches all_urls, which (according to Google documentation) should match file:/// URLs.
The background.js:
(function (chrome) {
'use strict';
chrome.webNavigation.onCompleted.addListener(function (details) {
chrome.tabs.sendMessage(details.tabId, {
action: 'changeBackground',
color: 'pink'
});
});
})(chrome);
And the changer.js (content script):
(function (chrome) {
'use strict';
chrome.runtime.onMessage.addListener(function (request) {
if (request.action !== 'changeBackground') { return; }
document.body.style.background = request.color;
});
})(chrome);
This extension has been published on the Chrome Web Store so you can see the result in action:
https://chrome.google.com/webstore/detail/sample-of-content-script/bkekbfjgkkineeokljnobgcoadlhdckd
It's a pretty simple extension. Navigate to a page, and it turn's the page's background pink. Unfortunately, it doesn't work for any file:/// URLs. The changer.js script is not loaded into the page, and nothing happens.
Extra info
It actually seems to work just fine when running as an Unpacked extension in Developer mode. Pages loaded from the file system turn pink.
I tried using chrome.tabs.executeScript() instead of putting the script into the manifest. This failed in a more obvious way, saying that I didn't request permissions to modify file:/// URLs in the manifest.
I added "file:///*/*" to the permissions section of manifest.json. That seemed to workwell with chrome.tabs.executeScript(), but the Chrome Web Store rejected the extension, saying that file:/// permissions are not allowed.
I reverted to a content_script section in manifest.json and tried adding "file:///*/* to the matches section in the manifest. Again, this worked in a development build, but when I uploaded it to the Chrome Web Store and then installed it, it didn't work.
<all_urls> indeed covers file:// scheme, but it must be manually activated in the extensions list.
If an extension has permissions that cover file:// scheme, it will have a checkbox "Allow access to file URLs" next to "Allow in incognito". The user must enable that manually; you can help by creating a tab with preconfigured URL, after explaining the process:
chrome.tabs.create({url: "chrome://extensions/?id=" + chrome.runtime.id});

Using content scripts/messaging with Chrome Apps (not extension) to send data

So I've been trying to send data from a web page to the Chrome Application (not Chrome Extension). Reading stuff around, according to me, this primarily would require the use of url_handlers for invoking Chrome App from a web page, content scripts to inject JS into the web page and/or Messaging for communication between Chrome Application and the web page.
Also, installed App from it's .crx, else loading unpacked directory leads to this error:
"content_scripts is only allowed for extensions and legacy packaged apps, but this is a packaged app."
Now, I tried injecting JS in the required site. However, on inspecting using Chrome Dev Tools, there's no such entry in the Sources->Content scripts section for that site. It simply didn't inject itself when using a Chrome App. It works perfectly with extensions but I want to use Chrome App for other functionalities.
As an alternative, I looked for Messaging examples where its usage is mentioned as:
"... your app or extension can receive and respond to messages from regular web pages."
But, somehow I couldn't get it working.
Any headers on either of the approaches? Other Suggestions?
manifest.json:
{
"name": "App",
"version": "1.0",
"manifest_version": 2,
"minimum_chrome_version": "31",
"app": {
"background": {
"scripts": ["background.js"]
}
},
"permissions": [
{"fileSystem": ["write", "retainEntries", "directory"]},
"storage",
"http://example.com/*"
],
"externally_connectable": {
"matches": ["http://example.com/*"]
},
"content_scripts": [{
"matches": ["http://example.com/*"],
"js": ["content.js"]
}]
}
Indeed, you can't have content scripts in an app.
However, using externally_connectable is valid.
You have already declared that you want to be externally connectable from example.com. (Note: be careful when defining match patterns, for instance this one does not cover www.example.com)
In example.com's own scripts, you can then include the following:
chrome.runtime.sendMessage("idOfYourAppHere", message, function(response) {
/* ... */
});
And in the app (probably its background script) you can catch that with
chrome.runtime.onMessageExternal.addListener(function(message, sender, sendResponse) {
/* ... */
sendResponse(response);
});
This does require you to know the ID in advance. You can pin it by packing your extension and extracting the "key" field from the manifest. See this question for some more details.

Write to a Google Doc from inside a Chrome Extension

I want to create a Chrome extension that runs through a forum and copies all the links to each post on a particular page to a Google Spreadsheet. I can't find much on using Google Apps Script in a Chrome Extension - does anyone have any resources or can you point me in the right direction? Thanks in advance!
You can absolutely launch an Apps Script published as a web app from a chrome extension. Here is a simple example. This extension will ask you to launch a script every time you open www.google.com. Annoying, but I tried to make it as simple as possible.
Background.js
// Handle requests for script launch
chrome.runtime.onMessage.addListener(function(request) {
if (request.type === 'launch_script') {
chrome.tabs.create({
url: 'https://script.google.com/a/macros/YOUR SCRIPT URL/exec',
active: false
}, function(tab) {
// After the tab has been created, open a window to inject the tab
chrome.windows.create({
tabId: tab.id,
type: 'popup',
focused: true
// incognito, top, left, ...
});
});
}
});
manifest.json
{
"name": "Script Launch Test",
"version": "1.0",
"manifest_version": 2,
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [{
"matches": ["https://www.google.com/*"],
"js": ["open-dialog.js"]
}]
}
open-dialog.js
if (confirm('Launch Script?'))
chrome.runtime.sendMessage({type:'launch_script'});
The basic answer is yes, this is possible. This answer to a similar question includes a minimal working example.
However, given the restrictions GAS works under, I would instead consider skipping the Apps script part entirely, and instead using the Sheets APIs to access the content directly.

Is it possible to ask for password when enable false or removing chrome extension?

I'm kinda new in developing chrome extension. My extension is actually about blocking some web pages, where user can insert domain names of websites that he/she want to block so that children cannot see the page, such as adult content pages, etc.
But I'm facing a problem with the question "How if the children unable or remove the extension, or even unchecked the 'allow in incognito'?" Then it would all be useless. So I am searching for a way to solve this problem, probably with using password before unable/remove the extension/unchecked the 'allow in incognito'.
Here is my manifest file:
{
"manifest_version": 2,
"name": "AmanNet",
"description": "Extension ini memblok halaman yang dianggap berbahaya secara konten html.",
"version": "1.0",
"browser_action": {
"default_icon": "icon_16x16.png",
"default_popup": "popup.html",
"default_title": "AmanNet"
},
"options_page": "pengaturan.html",
"background": {
"scripts": ["background.js"],
"persistent": true
},
"icons": {
"128": "icon_128x128.png"
},
"permissions": [
"http://*/*", "https://*/*", "tabs"
],
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"exclude_matches": ["http://*.google.com/*","https://*.google.com/*"],
"js": [
"content.js"
],
"run_at": "document_start",
"all_frames": false
}
]
}
How am I going to do this? Should I add something to manifest, or else? Please help.
Your problem is not solvable with a Chrome Extension in the general case.
Google has made every step possible in the direction of making the user empowered to remove unwanted extensions. This is because extensions are a notorious malware vector.
For instance, there is a method for external software to install their extensions through the registry. Since it was introduced, the following measures were taken:
Only extensions hosted on the Web Store are allowed (to enable takedowns by Google)
The user will be expressly asked whether they want that extension activated.
If they decline or uninstall the extension, it will be blacklisted on that profile and cannot be installed via registry again.
There are exceptions to the rule: enterprise installs. An extension on ExtensionInstallForcelist domain policy cannot be uninstalled or deactivated. This is, however, not an option for most users.
You can do some clever hacks with 2 separate extensions and management API, but you can't prevent uninstall, only detect it.
Note that Chrome includes a feature called "supervised users". However, it has its problems - it deals with the question of unwanted extensions/apps by just blanket banning all of them. If I was to set up parental control, I wouldn't accept a solution that would not allow AdBlock.
Bottom line: there is no chance preventing extension uninstall by extensions themselves, and no "good" ways of doing so with external programs. Custom parental control can only be effective if implemented outside Chrome (and even then questionably effective).
Typically you won't be able to prevent removal of any extensions. Chrome does have a "Kiosk" mode which is designed to be tamper proof but is only for Chrome OS: https://developer.chrome.com/apps/manifest/kiosk_enabled
There is no protection against removal. But you could use some steganography/obfuscation technics, like embedding your extension in another one.

Categories

Resources