I need to turn alert notification off by my extension. The alert function is a javascript built-in function and i override it like below in content script but it still works.
content script:
window.alert = function(){}
It does not turn it off. The problem is realy simple but it does not work and i am going crazy :)
manifest.json:
"content_scripts": [
{
"js": [ "assets/js/jquery-1.12.4.min.js", "assets/js/common.js", "assets/js/handlers.js" ],
"matches": [ "http://*/*", "https://*/*" ],
"run_at": "document_start"
}
],
handler.js:
window.alert = function (msg) {
debugger;
console.log(msg);
}
You can't switch off notifications globally in Chrome (at least, not that way).
By doing
window.alert = function(){}
you simply switch off notifications for your own extension (= your own window context). You can't do this globally for security reasons (think what malicious extension could do if this was possible).
Edit: you actually can inject your code into the content pages; but this is still not a "global" change that you seek. If you still want this, then:
manifest.js of your extension:
{
"name": "MyExtension",
...
"permissions": ["tabs", "http://*/*"],
"content_scripts" : [{
"js" : ["script.js"]
}]
}
And your script.js:
window.alert = function(){}
As Dmitriy mention it must be injected to the page. It works great please vote for Dimitry i just added the answer for sharing my code.
contend script:
function override_alert() {
window.alert = function alert(msg) {
console.log('Hidden Alert ' + msg);
};
}
if (!document.xmlVersion) {
var script = document.createElement('script');
script.appendChild(document.createTextNode('(' + override_alert + ')();'));
document.documentElement.appendChild(script);
}
Could you try something like this?
$(document).ready( function() {
window.alert = function(){};
});
Related
I created an extension, where I placed a script into a page markup and performs some actions according to the following article:
var s = document.createElement('script');
s.src = chrome.runtime.getURL('code.js');
s.onload = function() {
this.remove();
};
(document.head || document.documentElement).appendChild(s);
I also displayed a checkbox in "default_popup" which should indicate whether to execute a part of methods in script from "code.js" (web_accessible_resources) or not.
However, I have no idea how to interact between the script from "content_scripts" (which has access to "default_popup") and the script from "web_accessible_resources".
Could you suggest something?
I understand that I can completely replace the "web_accessible_resources" script, but this does not seem to be the best practice.
Thank you.
This is a sample of communication between popup and tab.
manifest.json
{
"name": "content_scripts + popup",
"version": "1.0",
"manifest_version": 3,
"content_scripts": [
{
"js": [
"matches.js"
],
"matches": [
"<all_urls>"
]
}
],
"host_permissions": [
"<all_urls>"
],
"action": {
"default_popup": "popup.html"
}
}
popup.js
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
console.log("Send");
chrome.tabs.sendMessage(tabs[0].id, "message", (response) => {
console.log("Recv response = " + response.title);
document.getElementById("title").innerText = response.title;
});
});
matches.js
console.log("matches.js");
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log("Recv. Send response = " + document.title);
sendResponse({ title: document.title });
return true;
});
popup.html
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
* {
font-size: x-large;
}
</style>
</head>
<body style="min-width:300px">
<div id="title"></div><br>
<script src="popup.js"></script>
</body>
</html>
I'm not sure exactly what you're asking but I'm assuming you have 3 things: (1) a pop up, (2) a content script, and (3) a script injected into the page, running in page context. Firstly, to send messages to the popup, you can run chrome.runtime.sendMessage() and have a listener in your popup's script.js file with chrome.runtime.onMessage(). To get the data from the page script is different, it cannot communicate with your browser extension directly. So, from your page context script, you can create an element with a unique ID and store some data in an attribute. Use a modification of a MutationObserver to run a waitForElm() function (see this thread - How to wait until an element exists?). In your content script, you'll wait for the element to be created, collect data from the attribute you set, and then run chrome.runtime.sendMessage() as mentioned earlier to get that data to your pop up.
What I want to do.
Using a Chrome extension I need to inject a script into the page context in such a way that the injected script runs before any other javascript on the page.
Why do I need this?
I need to hijack all console commands for a specific page so my extension can listen to the messages.
My current issue
Currently I am catching some of the messages logged by the page but not all of them, specifically, all messages from web-directory-132a3f16cf1ea31e167fdf5294387073.js are not being caught. After some digging I discovered that the web-directory-132a3f16cf1ea31e167fdf5294387073.js is also hijacking console but doing so before my script has a chance to.
As a visual, if I look at the network tab after loading the page, I see this:
My injected script is consoleInterceptor.js. It correctly captures the output of the js files that are loaded here accept web-directory-132a3f16cf1ea31e167fdf5294387073.js
Inside of web-directory-132a3f16cf1ea31e167fdf5294387073.js is some code something like this:
....
_originalLogger: t.default.Logger,
...
// do stuff with logging ....
this._originalLogger[e].apply(this._originalLogger, s),
What I think the problem is
It seems to me that, web-directory-132a3f16cf1ea31e167fdf5294387073.js is grabbing the standard console functions and storing them internally before my script has had a chance to replace them with my own versions. So even though my script works, the web-directory-132a3f16cf1ea31e167fdf5294387073.js still uses the original standard console functions it saved.
Note that web-directory-132a3f16cf1ea31e167fdf5294387073.js is an ember application and I dont see any simple way to hook into that code to overwrite those functions too but Im open to that as a solution.
My current code:
manifest.js
...
"web_accessible_resources": [
"js/ajaxInterceptor.js",
"js/consoleInterceptor.js"
],
"version" : "5.2",
"manifest_version": 2,
"permissions": [
"<all_urls>",
"tabs",
"activeTab",
"storage",
"webNavigation",
"unlimitedStorage",
"notifications",
"clipboardWrite",
"downloads",
"tabCapture",
"cookies",
"browsingData",
"webRequest",
"*://*/*",
"gcm",
"contextMenus",
"management"
],
"externally_connectable": {
"matches": ["*://apps.mypurecloud.com/*","*://*.cloudfront.net/*"]
},
...
background.js
var options = {url: [{hostContains: 'apps.mypurecloud.com'}]};
chrome.webNavigation.onCommitted.addListener(function(details) {
// first inject the chrome extension's id
chrome.tabs.executeScript(details.tabId, {
code: "var chromeExtensionId = " + JSON.stringify(chrome.runtime.id)
});
// then inject the script which will use the dynamically added extension id
// to talk to the extension
chrome.tabs.executeScript(details.tabId, {
file: 'js/injectConsoleInterceptor.js'
});
},
options
);
chrome.runtime.onMessageExternal.addListener(
function(msg, sender, sendResponse) {
if(msg.action === 'console_intercepted'){
_this.processConsoleMessage(sender, msg.details.method, msg.details.arguments);
}
});
injectConsoleInterceptor.js
var interceptorScript = document.createElement('script');
interceptorScript.src = chrome.extension.getURL('js/consoleInterceptor.js');
interceptorScript.onload = function(){this.remove();};
(document.head || document.documentElement).prepend(interceptorScript);
consoleInterceptor.js
if(!window.hasConsoleInterceptor){
window.hasConsoleInterceptor = true;
console.log('overriding console functions');
var originals ={};
var console = window.console;
if (console){
function interceptConsoleMethod(method){
originals[method] = console[method];
console[method] = function(){
// send the data to the extension
// chromeExtensionId should be injected into the page separately and before this script
var data = {
action: 'console_intercepted',
details: {
method: method,
arguments: arguments
}
};
chrome.runtime.sendMessage(chromeExtensionId, data);
originals[method].apply(console, arguments)
}
}
// an array of the methods we want to observe
var methods = ['assert', 'count', 'debug', 'dir', 'dirxml', 'error', 'group','groupCollapsed','groupEnd','info','log', 'profile', 'profileEnd','time','timeEnd','timeStamp','trace','warn','table'];
for (var i = 0; i < methods.length; i++){
interceptConsoleMethod(methods[i])
}
console.log('Successfully overridden console functions: '+methods.join(','));
}
}
My question
What can I do to make consoleInterceptor.js run before web-directory-132a3f16cf1ea31e167fdf5294387073.js loads so that web-directory-132a3f16cf1ea31e167fdf5294387073.js uses my modified console functions rather than the default browser console funcitons?
You can try this.In manifest.json file:
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["script/inject.js"],
"run_at":"document_start"
}
]
In inject.js:
var ss = document.createElement("script");
ss.innerHTML= "xxx";
document.documentElement.appendChild(ss);
So I've found several pages on here, as well as various blog posts that seem to do pretty much exactly what I want to do, but they are all a few years old and seem really easy but don't work.
As the title says, On thisdomain.com there is a iframe from thatdomain.com and I want to get the value in a div in that iframe.
Manifest.json
{
"manifest_version": 1,
"name": "MyExtention",
"version": "1.0",
"description": "Nothing Yet",
"permissions": [
"storage",
"tabs",
"unlimitedStorage",
"webRequest",
"webNavigation",
"*://*.match-both-iframe-and-main-domain.com/*",
"*://*/*"
],
"background": {
"scripts": ["listener.js"],
"persistent": true
},
"content_scripts":
[
{
"matches": ["*://*.matchnothing.shshdjdjffkdj.com/*"],
"js": ["mainscript.js"],
"all_frames": true
}
]
}
The content script url matches nothing because it is fired from a listener (which works). Basically it waits for a request from one of 2 urls before it activates.
listener.js
var chrome = chrome || {};
var callback = function(listenerRes) {
console.log(listenerRes.url);
if (listenerRes.url.indexOf("listenurl1") > -1 ||
listenerRes.url.indexOf("listenurl2") > -1) {
chrome.tabs.get(listenerRes.tabId, function(tab) {
chrome.tabs.executeScript(tab.id, {file: "mainscript.js"});
});
}
};
chrome.webRequest.onBeforeRequest.addListener( callback, {urls: ["*://*.google.com/*"]} );
mainscript.js
var chrome = chrome || {};
... // helper functions and such
var iframe = document.getElementsByid('myiframe');
// Get all data.
var datas = [];
try {
datas = iframe.contentWindow.document.getElementsByClassName('mydata'); // error is here
}catch(e){
console.log(e);
}
... // do stuff with the data
On the commented line it throws a "Blocked a frame with origin URL from accessing a cross-origin frame."
So I am under the impression that some combination of all_frames = true, the chrome.tabs.executeScript, and the domains in the permissions should allow for this to work. But it doesn't.
It might be important to note, the reason for this listener is because the iframe isnt on the page to start.
Please help, Im an experienced web developer but this is my 1st foray into Chrome Extentions.
How to get access to variable app from content script app.js in background script background.js?
Here is how I try it (background.js):
chrome.tabs.executeScript(null, { file: "app.js" }, function() {
app.getSettings('authorizeInProgress'); //...
});
Here is what I get:
Here is manifest.json:
{
"name": "ctrl-vk",
"version": "0.1.3",
"manifest_version": 2,
"description": "Chrome extension for ctrl+v insertion of images to vk.com",
"content_scripts": [{
"matches": [
"http://*/*",
"https://*/*"
],
"js": ["jquery-1.9.1.min.js"
],
"run_at": "document_end"
}],
"web_accessible_resources": [
"jquery-1.9.1.min.js"
],
"permissions" : [
"tabs",
"http://*/*",
"https://*/*"
],
"background": {
"persistent": false,
"scripts": ["background.js"]
}
}
Full code for instance, at github
https://github.com/MaxLord/ctrl-vk/tree/with_bug
To avoid above error use following code
if (tab.url.indexOf("chrome-devtools://") == -1) {
chrome.tabs.executeScript(tabId, {
file: "app.js"
}, function () {
if (app.getSettings('authorizeInProgress')) {
alert('my tab');
REDIRECT_URI = app.getSettings('REDIRECT_URI');
if (tab.url.indexOf(REDIRECT_URI + "#access_token") >= 0) {
app.setSettings('authorize_in_progress', false);
chrome.tabs.remove(tabId);
return app.finishAuthorize(tab.url);
}
} else {
alert('not my');
}
});
}
instead of
chrome.tabs.executeScript(null, {
file: "app.js"
}, function () {
if (app.getSettings('authorizeInProgress')) {
alert('my tab');
REDIRECT_URI = app.getSettings('REDIRECT_URI');
if (tab.url.indexOf(REDIRECT_URI + "#access_token") >= 0) {
app.setSettings('authorize_in_progress', false);
chrome.tabs.remove(tabId);
return app.finishAuthorize(tab.url);
}
} else {
alert('not my');
}
});
Explanation
chrome://extensions/ page also fires chrome.tabs.onUpdated event, to avoid it we have to add a filter to skip all dev-tool pages.
(Would've submitted this as comment to the accepted answer but still lack the required reputation)
You should also give the tabId to chrome.tabs.executeScript as first argument when you have it. Otherwise you risk user switching windows/tabs right after requesting a URL and background.js doing executeScript against wrong page.
While fairly obvious on hindsight it threw me for a loop when I got that same error message "Cannot access contents of url "chrome-devtools://.." even though my chrome.tabs.onUpdated eventhandler was checking that the page user requested had some specific domain name just before doing the executeScript call.
So keep in mind, chrome.tabs.executeScript(null,..) runs the script in active window, even if the active window might be developer tools inspector.
We should notice that, in the manifest cofigļ¼
"content_scripts": [{
"matches": [
"http://*/*",
"https://*/*"
],
"js": ["jquery-1.9.1.min.js"
],
in the "matches" part, only http, https are matched, so if you load your extension in page like: 'chrome://extensions/', or 'file:///D:xxx', that error will occur.
You may load your extension in the page with the url 'http://'; or add more rules in your 'matches' array.
I'm trying to pass a message from my content script to my background page. This error occurs when the content script is executed:
Uncaught TypeError: Cannot call method 'sendRequest' of undefined
Content Script:
function injectFunction(func, exec) {
var script = document.createElement("script");
script.textContent = "-" + func + (exec ? "()" : "");
document.body.appendChild(script);
}
function login() {
chrome.extension.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
var d = window.mainFrame.document;
d.getElementsByName("email")[0].value = "I need the response data here";
d.getElementsByName("passwort")[0].value = "Here too.";
d.forms["login"].submit();
}
injectFunction(login, true);
Background:
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
});
manifest.json:
{
"name": "Sephir Auto-Login",
"version": "1.0",
"manifest_version": 2,
"description": "Contact x#x.com for support or further information.",
"options_page": "options.html",
"icons":{
"128":"icon.png"
},
"background": {
"scripts": ["eventPage.js"]
},
"content_scripts": [
{
"matches": ["https://somewebsite/*"],
"js": ["login.js"]
},
{
"matches": ["somewebsite/*"],
"js": ["changePicture.js"]
}
],
"permissions": [
"storage",
"http://*/*",
"https://*/*",
"tabs"
]
}
Those are the examples on the documentation from google, so they should work.
Any help? I'm completely lost.
The problem is caused by your misunderstanding of the script executing environment. Read Chrome extension code vs Content scripts vs Injected scripts for more information. To be precise, you're using a form of this method to execute code in the context of a web page. Web pages do not have any access to the chrome.extension API.
I suggest to rewrite your code to not use injected scripts, because it's not necessary in this case.
function login() {
chrome.extension.sendRequest({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
var d = document.getElementById('mainFrame').contentDocument;
d.getElementsByName("email")[0].value = "I need the response data here";
d.getElementsByName("passwort")[0].value = "Here too.";
d.forms["login"].submit();
}
login();
* Only works if the frame is located at the same origin. Otherwise, you need this method to execute code correctly.
sendRequest and onRequest are deprecated. You need to use sendMessage and onMessage.
Also, you are injecting function to the DOM, that makes it run outside the content script context so chrome.extension API is no longer available for this function.