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!
Related
I wanted to make some sort of 'website blocker' (?) chrome extension, that redirects to html page that says website is blocked.
I already have manifest.json:
{
"name": "Redirector",
"version": "1",
"description": "...",
"manifest_version": 2,
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"permissions": ["tabs"]
}
and my content.js looks like this:
window.location.assign("index.html");
but every time i enter some website it redirects me from https://currentwebsite.com/ to https://currentwebsite.com/index.html, but i want it to redirect to index.html.
*Sorry for every language mistake.
**I am starting with js, dont flame me for bad code pls.
Simply putting "index.html" indeed won't work, your path should look like "http://index.html", though I don't think that'd be a page that you want to be redirected to. I suggest changing it to simply
window.location.assign("https://google.com");
or you may want to use that to redirect back to previous page:
window.history.back();
I'm writing a Chrome extension for Twitter that runs fine when I load any twitter page by putting in the URL manually, or when I refresh a twitter page. However, often (though not always) it will not run when I am navigating within twitter. For example, often if I click on someone's profile, the extension doesn't run. But if I refresh the page (still on the profile page) it will run.
I feel like it might be related to this question, Chrome extension is not loading on browser navigation at YouTube, but I'm exactly sure how.
I can tell that it's not running (as opposed to not working in some other way) because I have log a bunch of stuff to the console whenever it runs.
Here is my manifest:
{
"name": "Twitter Extend",
"version": "1.0",
"description": "A sea of white space",
"permissions": ["tabs", "<all_urls>"],
"content_scripts": [
{
"matches": ["http://*.twitter.com/*", "https://*.twitter.com/*"],
"js": ["main.js"]
}
],
"manifest_version": 2
}
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
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.
Okay, so here's my problem:
On my home computer, I have a Google Chrome Extension installed - WXFZ's \Code. This extension works perfectly, I use it every day for work purposes. However, I guess the developer gave up on it, because it can no longer be found on the Google Extensions download page.
I'm trying to transfer that extension from my home computer to my office computer. I have the extension folder on my work computer and I've tried dragging and dropping it into the extensions page to install it, but I receive an error:
"Could not load extension from 'U:\Downloads\pekinghlicdifnlgafajjohhoiochfdh\2.1_0'. The 'manifest_version' key must be present and set to 2 (without quotes). See developer.chrome.com/extensions/manifestVersion.html for details."
I'm not entirely sure what that means, but I've copied the contents of the manifest folder below. I've tried changing some things around in the manifest file, but nothing would work :/
{
"app": {
"launch": {
"local_path": "bscode.html"
}
},
"background_page": "storage.html",
"content_scripts": [ {
"all_frames": true,
"js": [ "js/jquery-1.4.4.min.js", "js/bscode.js", "js/bscode-cs.js" ],
"matches": [ "http://*/*", "https://*/*" ]
} ],
"description": "Simple \\code and \\\\macro engine for common web-forms.",
"icons": {
"128": "icon_128.png",
"16": "icon.png",
"48": "icon_48.png"
},
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClVb9xGcyZp3P4Fe+rpjGUqVrvRq8rqQl278gMjFzmxqD65cu7uf/erOBlFWbAc6YK15yvgnsYn+HDYvoSV4shajLAnytek7CI35nia5AnYACJsXW+JrfoT9pEgK9Zd4fE1XFr8bNCzhwKeoupH+gtMdvJ9lqAN4Xj/Tam5+QvzQIDAQAB",
"name": "wxfz\u2019s \\code",
"permissions": [ "http://*/*", "https://*/*", "tabs" ],
"update_url": "http://clients2.google.com/service/update2/crx",
"version": 2
}
Any advice on this problem, I'd appreciate it. Like I said, the extension still works; I was assuming there has to be a way to get it to work on my other computer :/
UPDATE
My apologies, the updated source code is :
{
"app": {
"launch": {
"local_path": "bscode.html"
}
},
"background_page": "storage.html",
"content_scripts": [ {
"all_frames": true,
"js": [ "js/jquery-1.4.4.min.js", "js/bscode.js", "js/bscode-cs.js" ],
"matches": [ "http://*/*", "https://*/*" ]
} ],
"description": "Simple \\code and \\\\macro engine for common web-forms.",
"icons": {
"128": "icon_128.png",
"16": "icon.png",
"48": "icon_48.png"
},
"key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClVb9xGcyZp3P4Fe+rpjGUqVrvRq8rqQl278gMjFzmxqD65cu7uf/erOBlFWbAc6YK15yvgnsYn+HDYvoSV4shajLAnytek7CI35nia5AnYACJsXW+JrfoT9pEgK9Zd4fE1XFr8bNCzhwKeoupH+gtMdvJ9lqAN4Xj/Tam5+QvzQIDAQAB",
"name": "wxfz\u2019s \\code",
"permissions": [ "http://*/*", "https://*/*", "tabs" ],
"update_url": "http://clients2.google.com/service/update2/crx",
"version": "2.1"
"manifest_version": 2
}
In the original post I had:
"version": 2
I see now that was incorrect, it was supposed to be 2.1, so I changed that back, along with making the changes you suggested.
The error you get is asking for a "manifest_version": 2 property in your manifest.json. So, at the very least youneed to:
Change "version": 2 to "version": "2" (version must be a string value).
Add "manifest_version": 2 (2 without quotes - it's a number value).
Change "background_page": "storage.html", to "background": {"page": "storage.html"},.
Beware though that some features may break and need refactoring as well (in order to conform with manifest v2).
UPDATE:
It turned out there were quite a few things that needed to be changed in order for the extension to be compliant with Manifest V2 (and functional). The re is no point in posting the code here or list every single modification in detail, so I'll try to summarize and focus on the "nature" of the modification (see further down for a link to the updated source code):
The major source of problems was the fact that the new Content Security Policy (CSP) that applies to Google Chrome Extensions does not allow eval and inline scripts/event listeners. To circumvent this the following changes were necessary:
Declare a CSP in the manifest that allows eval
("content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'").
Unfortunately(?) there is no way to relax the policy against inline scripts.
In the background page (namely storage.html, an inline script was used, so I ended up moving the code to an external file (background.js) and including the JS scripts like this:
"background": {
"persistent": true,
"scripts": [
"js/bscode.js",
"js/background.js"
]
},
The old jquery-1.4.4 (which relies on inline scripting) was a no go as well. So I had to replace to the less old jquery-1.7.2 (I tried using the latest versions of jquery and jquery-ui, but they didn't play well with the rest of the code, so I rolled back to the oldest version that didn't rely on inline scripting). This change affected both the content_scripts declaration and bscode.html (where the user-defined macros are defined and edited).
Migrating to jquery-1.7.2 required porting all occurrences of the deprecated .live() to the equivalent syntax using .on(). (Luckily, this only affected one file: chrome-ui.js)
bscode.html had 2 inline scripts that needed to be moved to an external file (and placed at the right place inside the body, since the code calls document.write.
bscode.html had a lot of inline event listeners, which would not work. Furthermore, elements (which also contain inline event listeners) are inserted dynamicaly into the DOM, so the solution had to take that into account as well.
I tackled both the problems by using an external JS file that utilizes a MutationObserver to listen for node insertions and convert any inline event listeners to "attached" event listeners (by means of addEventListener()).
Finally, to make things easier, I set-up bscode.html as the Options Page for the extension, so you can quickly bring it up from the chrome://exrensions page.
(I hope I didn't leave something out...)
The refactored (and fully functional as far as I can tell) source code of the extension can be downloaded here.