My current client is a radio station.
They use sockets to push data.
Some examples
song play (contains song info, thumb, playlists, artist info and
more)
program start (program info, dj's and more)
The extention I built has a socket listening script built in.
https://chrome.google.com/webstore/detail/q-music-nl/mhobnnhfmhcnomoehjomodcjmcjhfaea
The socket listening is done via "SockJS client, version 0.3.4, http://sockjs.org, MIT License".
This is built in the back.html like so:
MANIFEST
{
"manifest_version": 2,
"name": "NAME",
"description": "DESC",
"version": "3.1",
"icons": {
"128": "logo_128.png"
},
"permissions": [
"notifications"
],
"browser_action": {
"name": "Click to start",
"default_icon" : "Q.png",
"default_popup": "popup.html"
},
"background": {
"page": "back.html"
},
"options_page": "options.html"
}
BACK.HTML
<script src="back.js">
</script>
BACK.JS
function init() {
(function(){
var a = document.createElement('script');
a.type = 'text/javascript';
a.async = true;
a.src = 'sock.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(a, s);
})();
}
window.onload = init;
This works perfect!
The problem is after resuming my MAC (Software OS X 10.8.4 (12E55)) from sleep the connection seems to be lost.
No loggings in back html console, no other indications, just no communication over the wire anymore.
The pushes are there however.
What am I doing wrong?
*edit you may email me for the full source code of the extension.
Related
I am trying to get into chrome extension development and want to make an extension which highlights a specific word on every page from a background script.
If I give my extension the activeTab permission, it is listed as "Access requested" and I need to invoke it by opening the popup, then after reloading the page it will highlight the word.
The documentation says "essentially, activeTab grants the tabs permission temporarily", so I switched to giving the tabs permission because I don't want to open the popup every time I visit a new website. However, now the extension is listed as "no access needed" and the highlighting does not work regardless of whether I invoke the popup or not.
Here is my service-worker background.js:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if (changeInfo.status == 'complete') {
chrome.scripting.executeScript({
target: { tabId: tabId },
function: highlightwords,
});
}
})
function highlightwords(){
var list = document.getElementsByTagName("p")
var search_words = ["the", "it", "you"]
var words = []
for(var i = 0; i < list.length; i++){
var words = list[i].textContent.split(' ')
for (var j = 0; j < words.length; j++) {
if (search_words.includes(words[j])) {
console.log(words[j]);
var elem = document.createElement("span")
elem.textContent = words[j]
elem.style.color = "red"
words[j]=elem.outerHTML
}
}
list[i].innerHTML = words.join(' ')
}
}
manifest.json:
{
"name": "Getting Started Example",
"description": "Build an Extension!",
"version": "1.0",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"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"
},
"options_page": "options.html",
"permissions": ["storage", "scripting", "tabs"]
}
I'd be very grateful for any hint on what's going wrong here or which alternatives there are (apart from using manifest v2, which probably doesn't have much of a future, at least in Chrome).
The only purpose of the tabs permission is to show url in changeInfo and tab objects e.g. in chrome.tabs.onUpdated event. You don't use it and you don't need it for this task.
Remove tabs and scripting permissions, remove the background worker.
Declare a content script in manifest.json
"content_scripts": [{
"matches": ["*://*/*"],
"js": ["content.js"]
}]
content.js will run in all http/https sites (this is what the first * in *://*/* means) and highlight the text.
P.S. Note that your current code destroys event listeners added by the page to any nested elements inside p because you assign to innerHTML. This is bad. A much better approach is to replace the matching parts of text inline by using DOM methods createTreeWalker and splitText, example, or just use mark.js.
I am writing a Chrome Extension mainly for Pull Requests on Github Enterprise and have ran into an issue. When the page is loaded via a refresh or direct entering of the url from your browser it runs, when it is ran from clicking a link within Github it does not.
For instance if you go to this page with Pull Requests and click into one of them it will not run. But if you refresh that same page it will run.
manifest.json
{
"name": "Github Sample",
"manifest_version": 2,
"version": "0.0.1",
"description": "Sample",
"permissions": [
"tabs", "<all_urls>",
"http://github.com/*"
],
"content_scripts": [
{
"matches": [ "https://github.com/*" ],
"js": ["github.sample.js"],
"run_at": "document_end"
}
]
}
github.sample.json
// ==UserScript==
// #author Jacob Schoen
// ==/UserScript==
alert("Extension has Ran");
To make this easier I have pushed this to github.
Any ideas on how to address this?
GitHub site uses jquery-pjax library (see How to make github style page transitions by pjax).
Basically you only need to run the content script once and attach pjax event handlers inside an injected <script> element code which will be reusing a jQueryor $ variable of the site.
In those handlers you can send a message with document.dispatchEvent to your content script that will receive it in its window.addEventListener("blabla", ...)
or you can allow the access to chrome.runtime.sendMessage on the github site in manifest.json so that page-injected code will be able to send a message that can be received by the extension in chrome.runtime.onMessageExternal listener.
Alternatively you can use chrome.webNavigation.onHistoryStateUpdated in the background script but that will cause a warning during the installation that the extension can "Read your browsing history" which is a global permission unlike the content script solution.
The working example I came up with, in case it helps anyone else.
manifest.json
{
"name": "Github Sample",
"manifest_version": 2,
"version": "0.0.1",
"description": "Sample",
"permissions": [
"activeTab",
"tabs", "<all_urls>",
"http://github.com/*"
],
"content_scripts": [
{
"matches": [ "https://github.com/*" ],
"js": ["github.sample.js"],
"run_at": "document_idle"
}
],
"web_accessible_resources": ["inject.js"]
}
github.sample.js
// ==UserScript==
// #author Jacob Schoen
// ==/UserScript==
function myAlert() {
alert("Extension has Ran");
}
window.addEventListener("pageLoadTransition", myAlert);
var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('inject.js');
s.onload = function() {
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
//still have to load this one for direct page loads
myAlert();
inject.js
$(document).on('pjax:success', function() {
var evt=document.createEvent("CustomEvent");
evt.initCustomEvent("pageLoadTransition", true, true, null);
document.dispatchEvent(evt);
})
I also updated the Github repository with the working example.
I wrote a short content script, which stops a particular site from creating new windows for link clicks.
This is my first Chrome extension, and I've scored this website and the internet for a reason why it won't run, but I can't find any. I'm probably making a fundamental amateur mistake somewhere.
Manifest.json:
{
"manifest_version": 2,
"name": "DHS Links",
"description": "Stops the school's site from constantly opening new windows.",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png"
},
"content_scripts":[
{
"matches": ["*://www.darienps.org/dhs/*"],
"js": ["jquery.js", "makeNormalLinks.js"],
"run_at": "document_end"
}
]
}
I tested the Javascript file by itself on a local version of the site, so I'm pretty sure it's fine, but just in case:
makeNormalLinks.js:
$(document).ready(function() {
$("a").each(function(){
$(this).removeAttr("onclick");
});
});
A copy of jQuery is in the same directory and doesn't seem to have any issues.
Here's the onclick code for many links on the website:
onclick="window.open(this.href,'targetWindow','toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,')
Thank you for looking this over!
Edit:
I tried two of the injection methods from Rob W's response to another question linked to in the comments by Teepeemm.
Here's the new code for Method 1:
Manifest.json:
{
"manifest_version": 2,
"name": "DHS Links",
"description": "Stops the school's site from constantly opening new windows.",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png"
},
"content_scripts":[
{
"matches": ["*://www.darienps.org/dhs/*"],
"js": ["jquery.js", "scriptLauncher.js"]
}
],
"web_accessible_resources": ["makeNormalLinks.js"]
}
scriptLauncher.js:
var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('makeNormalLinks.js');
s.onload = function() {
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
Method 2a:
(Uses old Manifest.js)
makeNormalLinks.js:
var actualCode = ['$(document).ready(function(){',
'$("a").each(function(){',
'$(this).removeAttr("onclick");',
'});',
'});'].join('\n');
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
Unfortunately, neither method seems to work. I'm extremely grateful to those who commented and think we're getting close to an answer.
Solution:
Manifest.json:
{
"manifest_version": 2,
"name": "DHS Links",
"description": "Stops the school's site from constantly opening new windows.",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png"
},
"content_scripts":[
{
"matches": ["*://www.darienps.org/dhs/*"],
"js": ["makeNormalLinks.js"]
}
]
}
makeNormalLinks.js:
document.addEventListener("click", function(e) {
e.stopPropagation();
}, true);
Thanks you, Scott and all who commented!
Using the onclick attribute has many weird side effects. A more up to date approach would be to add a listener to the document that filters unwanted events. Like:
document.addEventListener("click", function(e) {
e.stopPropagation();
}, true);
The true argument is important (see event capture). This will block all click event listeners from firing, but the default click action will still be triggered.
I was having a similiar issue getting the content script to fire in Google Mail. I stumbled upon a page that recommended using the "hashchange" event.
// Event listener
window.addEventListener("hashchange", function () {
alert("hashchanged");
}, false);
I have absolutely no experience in chrome extension developing, but for some punctual need, I have to modify an existing extension, in order to ask the user to enter a port of connection for a socket.
It is composed of a manifest json file and two content scripts, one of which is the jquery library. I think it should be very simple, but after some google research, I could not find the direct answer to my problem.
manifest.json
{
"name": "MyExtension",
"version": "1.0",
"manifest_version": 2,
"content_scripts": [
{
"matches": ["http://myurl.com/"],
"css": ["style.css"],
"js": ["jquery-1.7.2.min.js", "script.js"]
}
]
}
script.js
(function() {
var sock = null;
function connect() {
if (sock !== null) {
return;
}
sock = new WebSocket('ws://localhost:1234/'));
[...]
}
[...]
})();
Just to be clear, my goal is to replace the '1234' port for the socket with a customized port set by the user through a dialog window.
Thanks by advance for your help,
Romain Laroche
I am trying to integrate CodeMirror's syntax highlighting with a textarea using chrome extensions.
Here is my test.js...
var srcArray = ["lib/codemirror.js",
"lib/util/matchbrackets.js",
"lib/util/continuecomment.js",
"mode/htmlmixed/htmlmixed.js",
"mode/xml/xml.js",
"mode/javascript/javascript.js",
"mode/css/css.js",
"mode/clike/clike.js",
"mode/php/php.js"];
function AddScript(value)
{
var s = document.createElement("SCRIPT")
s.src = chrome.extension.getURL(value);
s.onload = function() {
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
}
srcArray.forEach(AddScript);
... and manifest.json:
{
"name":"Test",
"description":"Test description",
"version":"1.0",
"manifest_version": 2,
"browser_action": {
"default_icon": "icon.png"
},
"content_scripts": [
{
"matches": ["file:///*Test*"],
"js": ["test.js"]
}
],
"web_accessible_resources": ["lib/codemirror.js",
"lib/util/matchbrackets.js",
"lib/util/continuecomment.js",
"mode/htmlmixed/htmlmixed.js",
"mode/xml/xml.js",
"mode/javascript/javascript.js",
"mode/css/css.js",![enter image description here][1]
"mode/clike/clike.js",
"mode/php/php.js"]
}
And here is the issue I am facing:
<script>...</script> are being added to the page, however when the last one is added they all disappear.
I suspect this has someting to do with security mechanisms introduced in 2nd version of the manifest. I cannot however figure out what is missing.
Your advice would be greatly appreciated, thanks.